fla*_*mey 4 c# listbox winforms ondrawitem
这是一个C#桌面应用程序.DrawStyle我的属性ListBox设置为OwnerDrawFixed.
问题:我重写DrawItem以不同的字体绘制文本,它的工作原理.但是当我在运行时开始调整表单大小时,正确绘制了所选项目,但其余部分未重绘,导致文本看起来已损坏未选中的项目.
这是我的代码:
private void listDevices_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
string textDevice = ((ListBox)sender).Items[e.Index].ToString();
e.Graphics.DrawString(textDevice,
new Font("Ariel", 15, FontStyle.Bold), new SolidBrush(Color.Black),
e.Bounds, StringFormat.GenericDefault);
// Figure out where to draw IP
StringFormat copy = new StringFormat(
StringFormatFlags.NoWrap |
StringFormatFlags.MeasureTrailingSpaces
);
copy.SetMeasurableCharacterRanges(new CharacterRange[] {new CharacterRange(0, textDevice.Length)});
Region[] regions = e.Graphics.MeasureCharacterRanges(
textDevice, new Font("Ariel", 15, FontStyle.Bold), e.Bounds, copy);
int width = (int)(regions[0].GetBounds(e.Graphics).Width);
Rectangle rect = e.Bounds;
rect.X += width;
rect.Width -= width;
// draw IP
e.Graphics.DrawString(" 255.255.255.255",
new Font("Courier New", 10), new SolidBrush(Color.DarkBlue),
rect, copy);
e.DrawFocusRectangle();
}
listDevices.Items.Add("Device001");
listDevices.Items.Add("Device002");
Run Code Online (Sandbox Code Playgroud)
此外,正确绘制的项目(选定的项目)在窗体大小调整时闪烁.没什么大不了的,但如果有人知道为什么...... tnx
将以下代码放在Resize事件中:
private void listDevices_Resize(object sender, EventArgs e) {
listDevices.Invalidate();
}
Run Code Online (Sandbox Code Playgroud)
这应该会导致重绘所有内容.
要停止闪烁,您需要双缓冲.
为此,创建一个派生自ListBox的新类,并将以下内容放在构造函数中:
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
Run Code Online (Sandbox Code Playgroud)
或者只是将其粘贴到代码文件中:
using System.Windows.Forms;
namespace Whatever {
public class DBListBox : ListBox {
public DBListBox(): base() {
this.DoubleBuffered = true;
// OR
// this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
}
}
}
Run Code Online (Sandbox Code Playgroud)
将"Whatever"替换为项目使用的命名空间,或者使其更有用.在编译之后,您应该能够在表单设计器中添加DBListBox.
我重现了这个问题。代码中有几个错误,字体名称为“Arial”,您应该没有调整rect.Width,您忘记在字体,画笔和区域上调用Dispose()。但他们没有解释这种行为。剪切区域有问题,无法正确更新文本。我没有看到发生的地方,Graphics 对象状态没问题。
Graphics.DrawString() 是一个很麻烦的方法,你真的应该避免它。所有 Windows 窗体控件,包括 ListBox,都使用 TextRenderer.DrawText()。这解决了我使用它时的问题。我知道测量更困难,您可以通过以固定偏移量显示 IP 地址来解决这个问题。看起来也更好,他们会这样排成一列。
它闪烁是因为您使用了 e.DrawBackground()。这会擦除现有文本,您可以在其上重新绘制文本。我不认为双缓冲会解决这个问题,你必须绘制整个项目,所以你不必绘制背景。如果您无法使用大字体获得文本的确切大小,那么解决方法是先绘制位图。