C# 了解所有者绘制的列表框+;OwnerDrawVariable属性

C# 了解所有者绘制的列表框+;OwnerDrawVariable属性,c#,.net,vb.net,winforms,C#,.net,Vb.net,Winforms,我有一个ownerdrawn列表框的代码,它太频繁地重新绘制。这似乎与试图以不同于正常的高度滚动事件有关 下面是可以粘贴到空白表单中的“再现问题的最小代码”(删除设计器文件)-VB版本(c当然做同样的事情): 公共类表单1 继承System.Windows.Forms.Form Friend WithEvents ListBox1作为新System.Windows.Forms.ListBox 私有子ListBox1_DrawItem(ByVal sender作为对象,ByVal e作为对象_ S

我有一个ownerdrawn列表框的代码,它太频繁地重新绘制。这似乎与试图以不同于正常的高度滚动事件有关

下面是可以粘贴到空白表单中的“再现问题的最小代码”(删除设计器文件)-VB版本(c当然做同样的事情):

公共类表单1
继承System.Windows.Forms.Form
Friend WithEvents ListBox1作为新System.Windows.Forms.ListBox
私有子ListBox1_DrawItem(ByVal sender作为对象,ByVal e作为对象_
System.Windows.Forms.DrawItemEventArgs)处理ListBox1.DrawItem
如果e.Index=-1,则退出子系统
整数形式的Dim i=CType(列表框1.Items(e.Index),整数)
e、 退税地()
如果我修改了40,那么
e、 Graphics.DrawString(“Item#::”和i.ToString&Space(20)。替换(“,”)_
ListBox1.字体,画笔.黑色,0,e.Bounds.Top)
其他的
e、 图形.抽绳(钢笔.蓝色,10,e.Bounds.Top+1,52,e.Bounds.Top+1)
如果结束
e、 DrawFocusRectangle()
端接头
私有子列表框1u MeasureItem(ByVal发送方作为对象,ByVal e作为对象_
System.Windows.Forms.MeasureItemEventArgs)处理ListBox1.MeasureItem
如果e.Index=-1,则退出子系统
如果CInt(列表框1.Items(e.Index))Mod 4=0,则
e、 ItemHeight=2
如果结束
端接头
私有子表单1_加载(ByVal发送方作为System.Object,ByVal e作为System.Object_
System.EventArgs)处理MyBase.Load
Me.ListBox1.Dock=System.Windows.Forms.DockStyle.Fill
Me.ListBox1.DrawMode=System.Windows.Forms.DrawMode.OwnerDrawVariable
Me.ClientSize=新系统.Drawing.Size(454899)
Me.Controls.Add(Me.ListBox1)
对于i,作为整数=0到500
列表框1.Items.Add(i)
下一个
端接头
末级
ownerdrawn列表框绘制正常,但我有一个应用程序使用这种样式的列表框,它是一个宏重放器

您可以选择起点,然后单击单步或“自动播放”。当然,在播放宏时,它会从列表框中走下。当它开始滚动时,它会疯狂地闪烁,,当它碰到一个非标准大小的项目时,它会重新绘制

尝试在这个简化版本中滚动以复制问题-通过滚动条,或者只按向下箭头


你知道我做错了什么吗?不必彻底改造列表框?非常感谢。(为了让问题更清楚,我重播了这个问题。)

我在.NET 3.5和.NET 2.0中用C#重新创建了你的程序,我不确定我应该看到什么-有时会有一些闪烁,但不是那么糟糕

下面是一段正在进行的节目视频:

公共类表单1:System.Windows.Forms.Form
{
System.Windows.Forms.ListBox ListBox1=新的System.Windows.Forms.ListBox();
public Form1():base()
{
this.Load+=new System.EventHandler(Form1\u Load);
ListBox1.DrawItem+=new System.Windows.Forms.DrawItemEventHandler(ListBox1\u DrawItem);
ListBox1.MeasureItem+=新系统.Windows.Forms.MeasureItemEventHandler(ListBox1_MeasureItem);
}
私有无效ListBox1_DrawItem(对象发送者,System.Windows.Forms.DrawItemEventArgs e)
{
如果(e.Index=-1)
返回;
inti=System.Convert.ToInt32(列表框1.Items[e.Index]);
e、 牵引杆接地();
如果(i%4!=0)
{
字符串空格=新字符串(“”,20);
e、 拉丝(
“项:”+i.ToString()+空格。替换(“,”),
ListBox1.Font,
系统。图纸。刷子。黑色,
0,
e、 边界(顶部);
}
其他的
{
e、 拉丝(
System.Drawing.Pens.Blue,
10,
e、 上界+1,
52,
e、 上限+1);
}
e、 DrawFocusRectangle();
}
私有无效列表框1_MeasureItem(对象发送方,System.Windows.Forms.MeasureItemEventArgs e)
{
如果(e.Index=-1)
返回;
if((System.Convert.ToInt32(ListBox1.Items[e.Index])%4)==0)
{
e、 项目高度=2;
}
}
私有void Form1_加载(对象发送方,System.EventArgs e)
{
ListBox1.Dock=System.Windows.Forms.DockStyle.Fill;
ListBox1.DrawMode=System.Windows.Forms.DrawMode.OwnerDrawVariable;
ClientSize=新系统图纸尺寸(454899);
控件。添加(列表框1);
对于(int i=0;i<500;i++)
{
列表框1.项目。添加(i);
}
ListBox1.Visible=true;
}
}

这有一个解决方案可能会有所帮助。它是用C#写的。似乎覆盖OnPaint可能是一种方法。

回答这个问题可能有点晚,但为什么不使用BeginUpdate()和EndUpdate()。

那个博客有答案,谢谢。我鞠躬-我的谷歌fu很好,你的更好。谢谢你的回答,但问题是当系统决定重新绘制列表时,而不是当我。项目已经可以添加,并且取决于其他窗口中经常发生的情况,所有者绘制的所有内容都会疯狂地闪烁(特别是如果两个应用程序使用所有者绘制的列表框)。
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
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;
    }
}