覆盖ListBox的DrawItem - 未重绘未选择的项目

时间:2010-07-18 08:45:08

标签: c# winforms listbox ondrawitem

这是一个C#桌面应用程序。我DrawStyle的{​​{1}}属性设置为ListBox

问题:我重写DrawItem以使用不同的字体绘制文本,并且它可以正常工作。但是当我开始在运行时调整窗体大小时,所选项目被正确绘制,但其余部分未重绘,导致文本看起来对于未选择的项目是否已损坏。

这是我的代码:

OwnerDrawFixed

此外,正确绘制的项目(所选项目)在窗体大小调整时闪烁。没什么大不了的,但如果有人知道为什么...... tnx

2 个答案:

答案 0 :(得分:5)

将以下代码放入Resize事件:

private void listDevices_Resize(object sender, EventArgs e) {
    listDevices.Invalidate();
}

这会导致重绘所有内容。

要停止闪烁,您需要双重缓冲。

为此,创建一个派生自ListBox的新类,并将以下内容放在构造函数中:

this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

或者只是将其粘贴到代码文件中:

using System.Windows.Forms;

namespace Whatever {
    public class DBListBox : ListBox {
        public DBListBox(): base() {
            this.DoubleBuffered = true;
            // OR
            // this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        }
    }
}

将“Whatever”替换为项目使用的命名空间,或者使其更有用。在编译之后,您应该能够在表单设计器中添加DBListBox。

答案 1 :(得分:4)

我重复了这个问题。代码中有几个错误,字体名称是“Arial”,你不应该调整rect.Width,你忘了在字体,画笔和区域上调用Dispose()。但他们没有解释这种行为。剪切区域出现问题,导致文本无法正确更新。我没看到发生的地方,图形对象状态没问题。

Graphics.DrawString()是一个非常麻烦的方法,你应该真的避免它。所有Windows窗体控件(包括ListBox)都使用TextRenderer.DrawText()。当我使用它时,这解决了问题。我知道测量更难,您可以通过在固定偏移处显示IP地址来解决这个问题。看起来也更好,他们会以这样的方式排成一列。

它因为你使用e.DrawBackground()而闪烁。这会删除现有文本,您可以在其上绘制文本。我不认为双缓冲会解决这个问题,你必须绘制整个项目,这样你就不必绘制背景了。如果你不能用大字体获得文本的确切大小,那么一个解决方法就是首先绘制一个位图。