winform listbox drawitem изменить цвет подстроки

Я создал пользовательский элемент управления winform, который имеет текстовое поле и список, совместно использующие один и тот же источник привязки, так что список можно отфильтровать с помощью ввода текстового поля.

Мне нужно переопределить drawism для lisbox, чтобы отфильтрованные элементы, которые искали текст как подстроку, были другого цвета или выделены. (т. е.) Ожидается выделение желтого цвета, как показано на рисунке ниже. образец ссылки

Я сделал как ниже

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);
                }

            });

        }

В результате текст элемента был перезаписан.

первоначально после поиска

Я не могу определить часть ошибки, находится ли она в границах прямоугольника или в части на шнуровке. Кроме цвета фона элемента, как я могу изменить фон подстроки в тексте элемента. Пожалуйста помоги мне с этим.

1 ответ

Решение

Ну, задача не так проста, как следовало бы, потому что ни TextRenderer.MeasureText ни Graphics.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);
            }

        });


    }
Другие вопросы по тегам