Рисование в списке отключает перерисовку в элементах списка - PullRequest
0 голосов
/ 25 октября 2009

В чем причина?

Я переопределяю OnPaintBackground и рисую строку. Он не появляется, пока я не вызову это в конструкторе:

this.SetStyle ( ControlStyles.UserPaint, true );

Но тогда я не вижу элементов в списке.

Почему и как это решить?

РЕДАКТИРОВАТЬ: код

    protected override void OnPaintBackground ( PaintEventArgs pevent )
    {
        base.OnPaintBackground ( pevent );

        // Create string to draw.
        String drawString = "76";

        // Create font and brush.
        Font drawFont = new Font ( "Arial", 36 );
        SolidBrush drawBrush = new SolidBrush ( Color.Blue );

        // Create point for upper-left corner of drawing.
        PointF drawPoint = new PointF ( 150.0F, 150.0F );

        // Draw string to screen.
        pevent.Graphics.DrawString ( drawString, drawFont, drawBrush, drawPoint );

        //pevent.Graphics.FillRectangle ( drawBrush, this.ClientRectangle );
    }`enter code here`

1 Ответ

5 голосов
/ 25 октября 2009

Как я уже говорил в прошлой теме об этой теме, OnPaint() и UserPaint не работают с ListView. Картина обрабатывается базовым элементом управления и не может быть перехвачена таким образом. Это отличается от других элементов управления

Итак, когда ControlStyles.UserPaint равно true, базовому элементу управления не предписано перерисовывать себя. Вместо этого весь рисунок перенаправляется на методы OnPaintBackground() и OnPaint(), которые, как вы обнаружили, ничего не делают.

Есть два способа сделать то, что вы просили (второй лучше первого):

Первый способ: перехватить WM_PAINT, выполнить базовую обработку, а затем нарисовать в виде списка. Примерно так:

public class MyListView : ListView
{
    protected override void WndProc(ref Message m) {
        switch (m.Msg) {
            case 0x0F: // WM_PAINT
                this.HandlePaint(ref m);
                break;
            default:
                base.WndProc(ref m);
                break;
        }
    }

    protected virtual void HandlePaint(ref Message m) {
        base.WndProc(ref m);

        using (Graphics g = this.CreateGraphics()) {
            StringFormat sf = new StringFormat();
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Center;
            sf.Trimming = StringTrimming.EllipsisCharacter;
            g.DrawString("Some text", new Font("Tahoma", 13),
                SystemBrushes.ControlDark, this.ClientRectangle, sf);
        }
    }
}

Но это создает проблемы с перерисовкой, когда то, что вы рисуете, находится вне области, в которой, по мнению списка, содержится содержимое элемента управления - оно не вызывает события рисования.

Второй способ: перехватить уведомление CustomDraw (это , а не то же, что OwnerDraw) и прослушать этап CDDS_POSTPAINT. На этом этапе вы можете смело рисовать в виде списка. Вы можете посмотреть код ObjectListView , чтобы увидеть, как это делается.

Вы также можете просто избавить себя от лишних хлопот и напрямую использовать ObjectListView:)

...