【发布时间】:2016-08-19 22:26:59
【问题描述】:
我创建了一个 winform 自定义控件,它的文本框和列表框都共享相同的绑定源,以便可以使用文本框输入过滤列表框。
我需要覆盖 lisbox drawitem,以便将搜索文本作为子字符串的过滤项目具有不同的颜色或突出显示。 (即,)预期的黄色突出显示如下示例图像。
我做了如下
private void DrawItemHandler(object sender, DrawItemEventArgs e)
{
this.Invoke((MethodInvoker)delegate
{
e.DrawBackground();
e.DrawFocusRectangle();
string MyString = listBox.GetItemText(listBox.Items[e.Index]);
string stringToFind = searchInput.Text ;
if (!string.IsNullOrEmpty(stringToFind))
{
List<int> positions = new List<int>();
int pos = 0;
while ((pos < MyString.Length) && (pos = MyString.IndexOf(stringToFind, pos, StringComparison.InvariantCultureIgnoreCase)) != -1)
{
positions.Add(pos);
pos += stringToFind.Length;
}
int c = 0, nLen = 0, width = 0;
Rectangle rect = e.Bounds;
rect.X = width;
do
{
if (positions.Contains(c))
{
//int opacity = 128;
e.Graphics.DrawString(MyString.Substring(c, stringToFind.Length),
e.Font,
//new SolidBrush(Color.FromArgb(opacity, Color.LightYellow)),
new SolidBrush(Color.LightYellow),
rect);
nLen = MyString.Substring(c, stringToFind.Length).Length;
width += nLen;
}
else
{
e.Graphics.DrawString(MyString[c].ToString(),
e.Font,
new SolidBrush(listBox.ForeColor),
rect);
nLen = MyString[c].ToString().Length;
width += nLen;
}
rect.X = width;
}
while ((c += nLen) < MyString.Length);
}
else
{
e.Graphics.DrawString(MyString,
e.Font,
new SolidBrush(listBox.ForeColor),
e.Bounds);
}
});
}
结果是项目文本被字符覆盖。
我无法识别错误部分,是在矩形边界还是在拉绳部分。除了项目背景颜色之外,如何更改项目文本中子字符串的背景。请帮我解决这个问题。
【问题讨论】:
-
要更改子字符串的背景,我怀疑您必须先使用 FillRectangle,然后在该矩形上使用 DrawString
-
要使用自定义背景色,请使用 TextRenderer 而不是 DrawString!您推进 rectangle.X 的方法是以字符而不是像素为单位使用字符串的长度。使用 Graphics.MeasureString(...Typographics) 找出突出显示部分的宽度。
-
尝试了带有 FillRectangle 建议的 MeasureString,我可以看到差异,但仍然需要一些调整。谢谢大家。
-
请注意,总会有一点松懈。使用带有两种颜色的 TextRenderer 重载来绘制字符串,至少可以将 BackColor 精确地置于文本之上或之下。
-
感谢@TaW,我会使用 textrenderer 并会记住这一点。
标签: c# winforms listbox ondrawitem