Понимание владельца выведенного списка + свойство OwnerDrawVariable - PullRequest
0 голосов
/ 23 июля 2010

У меня есть этот код для списка владельцев, который перерисовывается слишком часто. Похоже, это связано с попыткой прокрутить событие с высоты, отличной от обычной.

Вот «наименьший код для воспроизведения проблемы», который можно вставить в чистую форму (стереть файл конструктора) - версия VB (c #, конечно, делает то же самое):

Public Class Form1
    Inherits System.Windows.Forms.Form
    Friend WithEvents ListBox1 As New System.Windows.Forms.ListBox

    Private Sub ListBox1_DrawItem(ByVal sender As Object, ByVal e As  _
                                   System.Windows.Forms.DrawItemEventArgs) Handles ListBox1.DrawItem
        If e.Index = -1 Then Exit Sub
        Dim i As Integer = CType(ListBox1.Items(e.Index), Integer)
        e.DrawBackground()
        If i Mod 4 <> 0 Then
            e.Graphics.DrawString("Item #: " & i.ToString & Space(20).Replace(" ", " <Filler>"), _
                                  ListBox1.Font, Brushes.Black, 0, e.Bounds.Top)
        Else
            e.Graphics.DrawLine(Pens.Blue, 10, e.Bounds.Top + 1, 52, e.Bounds.Top + 1)
        End If
        e.DrawFocusRectangle()
    End Sub

    Private Sub ListBox1_MeasureItem(ByVal sender As Object, ByVal e As  _
                   System.Windows.Forms.MeasureItemEventArgs) Handles ListBox1.MeasureItem
        If e.Index = -1 Then Exit Sub
        If CInt(ListBox1.Items(e.Index)) Mod 4 = 0 Then
            e.ItemHeight = 2
        End If
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As  _
                           System.EventArgs) Handles MyBase.Load

        Me.ListBox1.Dock = System.Windows.Forms.DockStyle.Fill
        Me.ListBox1.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable
        Me.ClientSize = New System.Drawing.Size(454, 899)
        Me.Controls.Add(Me.ListBox1)

        For i As Integer = 0 To 500
            ListBox1.Items.Add(i)
        Next
    End Sub
End Class

Ownerdrawn listbox рисует ОК, но у меня есть приложение, которое использует список этого стиля, это макрос-проигрыватель.

Вы можете выбрать начальную точку, затем нажать «один шаг» или «автозапуск». Конечно, во время воспроизведения макроса он уходит вниз по списку. Когда он начинает прокручиваться, он мерцает как сумасшедший , перекрашивая при попадании в предмет нестандартного размера.

Попробуйте прокрутить в этом сокращенном варианте, повторяющем проблему, - с помощью полосы прокрутки или просто положите стрелку вниз.

Есть идеи, что я делаю неправильно - без необходимости заново изобретать список? Очень признателен. (Я переделал этот вопрос, чтобы прояснить его).

Ответы [ 3 ]

1 голос
/ 24 июля 2010

Этот блог имеет решение, которое может помочь. Это в C #. Кажется, что переопределение OnPaint может быть способом.

1 голос
/ 24 июля 2010

Я пересоздал вашу программу на C # в .NET 3.5 и .NET 2.0, и я не уверен, что я смог увидеть - временами было небольшое мерцание, но не так уж плохо

Здесьвидео программы в действии:
http://pixetell.com/p00148Ce5hdFxqn78wII8FrtMRK1Hy8f1D84KE7McLQgvrU9l35

public class Form1 : System.Windows.Forms.Form
{
    System.Windows.Forms.ListBox ListBox1 = new System.Windows.Forms.ListBox();

    public Form1() : base()
    {
        this.Load += new System.EventHandler(Form1_Load);

        ListBox1.DrawItem+=new System.Windows.Forms.DrawItemEventHandler(ListBox1_DrawItem);
        ListBox1.MeasureItem += new System.Windows.Forms.MeasureItemEventHandler(ListBox1_MeasureItem);
    }

    private void ListBox1_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
    {
        if (e.Index == -1)
            return;

        int i = System.Convert.ToInt32(ListBox1.Items[e.Index]);

        e.DrawBackground();

        if (i % 4 != 0)
        {
            string spaces = new string(' ', 20);

            e.Graphics.DrawString(
                "Item #: " + i.ToString() + spaces.Replace(" ", " <Filler>"),
                    ListBox1.Font,
                    System.Drawing.Brushes.Black,
                    0,
                    e.Bounds.Top);
        }
        else
        {
            e.Graphics.DrawLine(
                System.Drawing.Pens.Blue,
                10,
                e.Bounds.Top + 1,
                52,
                e.Bounds.Top + 1);
        }

        e.DrawFocusRectangle();
    }

    private void ListBox1_MeasureItem(object sender, System.Windows.Forms.MeasureItemEventArgs e)
    {
        if (e.Index == -1)
            return;

        if ((System.Convert.ToInt32(ListBox1.Items[e.Index]) % 4) == 0)
        {
            e.ItemHeight = 2;
        }
    }

    private void Form1_Load(object sender, System.EventArgs e)
    {
        ListBox1.Dock = System.Windows.Forms.DockStyle.Fill;
        ListBox1.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;

        ClientSize = new System.Drawing.Size(454, 899);
        Controls.Add(ListBox1);

        for (int i = 0; i < 500; i++)
        {
            ListBox1.Items.Add(i);
        }

        ListBox1.Visible = true;
    }
}
0 голосов
/ 24 сентября 2011

Может быть немного поздно с этим ответом, но почему бы не использовать BeginUpdate () и EndUpdate ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...