0

我创建了一个 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);
                }

            });

        }

结果是项目文本被字符覆盖。

最初 搜索后

我无法识别错误部分,是在矩形边界还是在拉绳部分。除了项目背景颜色之外,如何更改项目文本中子字符串的背景。请帮助我。

4

1 回答 1

2

好吧,这项任务并不像应有的那么容易,因为对于这项工作来说,这两者似乎都不是很准确TextRenderer.MeasureTextGraphics.MeasureString但是使用Graphics.MeasureString传递矩形宽度的不同重载,StringFormat.GenericTypographic它似乎工作得更好一些。

这是我对您的问题的尝试,希望对您有所帮助:

    private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
    {
        ListBox listBox = (ListBox)sender;
        this.Invoke((MethodInvoker)delegate
        {
            e.DrawBackground();
            e.DrawFocusRectangle();

            string MyString = listBox.GetItemText(listBox.Items[e.Index]);
            string stringToFind = searchInput.Text;


            if (!string.IsNullOrEmpty(stringToFind))
            {
                string[] strings = MyString.Split(new string[] { stringToFind }, StringSplitOptions.None);

                Rectangle rect = e.Bounds;

                for (int i=0;i<strings.Length;i++)
                {
                    string s = strings[i];
                    if (s != "")
                    {
                        int width = (int)e.Graphics.MeasureString(s, e.Font,e.Bounds.Width, StringFormat.GenericTypographic).Width;
                        rect.Width = width;
                        TextRenderer.DrawText(e.Graphics, s, e.Font, new Point(rect.X, rect.Y), listBox.ForeColor);
                        rect.X += width;
                    }

                    if (i < strings.Length - 1)
                    {
                        int width2 = (int)e.Graphics.MeasureString(stringToFind, e.Font, e.Bounds.Width, StringFormat.GenericTypographic).Width;
                        rect.Width = width2;
                        TextRenderer.DrawText(e.Graphics, stringToFind, e.Font, new Point(rect.X, rect.Y), listBox.ForeColor, Color.Yellow);
                        rect.X += width2;
                    }
                }
            }
            else
            {
                TextRenderer.DrawText(e.Graphics, MyString, e.Font, new Point(e.Bounds.X, e.Bounds.Y), listBox.ForeColor);
            }

        });


    }
于 2016-04-26T10:22:07.493 回答