Winforms - элемент списка наведите курсор и выберите цвет - PullRequest
0 голосов
/ 04 мая 2020

Я переделываю программу, все шло хорошо, но теперь я столкнулся с проблемой. Программа, которую я переписываю, - это wpf, и я работаю в winforms, программа имеет список, который я не могу воссоздать так просто :( Вот изображение ListBox с выбранным элементом: Выбранный элемент

Как вы видите, выбранные элементы становятся синими, а их границы - синими, а когда вы прекращаете фокусироваться на форме, они становятся белыми: Белый элемент

И элементы, на которых при наведении указатель мыши станет синим, но немного светлее: Элемент наведения

Спасибо за помощь!

Кстати, я использую. NET Framework 4.8

1 Ответ

1 голос
/ 04 мая 2020

Вы можете создать свой собственный список, основанный на оригинальном. Как только новый список будет скомпилирован в первый раз, он появится на панели инструментов, так что вы сможете перетаскивать его на свои формы. Или вы можете изменить тип существующих списков на ListBoxEx в Form.designer.cs вручную.

public class ListBoxEx : ListBox
{
    public ListBoxEx()
    {
        DrawMode = DrawMode.OwnerDrawFixed;
        DoubleBuffered = true; // Eliminates flicker (optional).
    }

    private int _hotTrackedIndex = -1;
    private int HotTrackedIndex
    {
        get => _hotTrackedIndex;
        set {
            if (value != _hotTrackedIndex) {
                if (_hotTrackedIndex >= 0 && _hotTrackedIndex < Items.Count) {
                    Invalidate(GetItemRectangle(_hotTrackedIndex));
                }
                _hotTrackedIndex = value;
                if (_hotTrackedIndex >= 0) {
                    Invalidate(GetItemRectangle(_hotTrackedIndex));
                }
            }
        }
    }

    protected override void OnDrawItem(DrawItemEventArgs e)
    {
        var borderRect = e.Bounds;
        borderRect.Width--;
        borderRect.Height--;
        if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) {
            if (Focused) {
                e.Graphics.FillRectangle(Brushes.Teal, e.Bounds);
                e.Graphics.DrawRectangle(Pens.LightSkyBlue, borderRect);
            } else {
                e.Graphics.FillRectangle(Brushes.DimGray, e.Bounds);
                e.Graphics.DrawRectangle(Pens.White, borderRect);
            }
        } else if (e.Index == HotTrackedIndex) {
            e.Graphics.FillRectangle(Brushes.DarkSlateGray, e.Bounds);
            e.Graphics.DrawRectangle(Pens.DarkCyan, borderRect);
        } else {
            e.DrawBackground();
        }
        if (Items[e.Index] != null) {
            e.Graphics.DrawString(Items[e.Index].ToString(), e.Font, Brushes.White, 6, e.Bounds.Top, StringFormat.GenericTypographic);
        }
    }

    protected override void OnMouseLeave(EventArgs e)
    {
        HotTrackedIndex = -1;
        base.OnMouseLeave(e);
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        HotTrackedIndex = IndexFromPoint(e.Location);
        base.OnMouseMove(e);
    }

    protected override void OnGotFocus(EventArgs e)
    {
        if (SelectedIndex >= 0) {
            RefreshItem(SelectedIndex);
        }
        base.OnGotFocus(e);
    }

    protected override void OnLostFocus(EventArgs e)
    {
        if (SelectedIndex >= 0) {
            RefreshItem(SelectedIndex);
        }
        base.OnLostFocus(e);
    }
}

Мы изменим внешний вид списка, переопределив OnDrawItem. в конструкторе мы устанавливаем DrawMode = DrawMode.OwnerDrawFixed; для включения рисования владельца.

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

FillRectangle dr aws фон. DrawRectangle доктор aws граница. Обратите внимание, что прямоугольник границы должен быть на один пиксель меньше прямоугольника e.Bounds, в противном случае правая и нижняя границы не будут нарисованы.

Если текущий элемент не выбран, мы проверяем, является ли он горячий трек. Если это так, мы рисуем разными цветами. В противном случае мы рисуем фон по умолчанию с помощью e.DrawBackground();.

Затем мы рисуем текст поверх фона с помощью DrawString.


Чтобы все это работало, мы также должны сделать недействительными регионы списка, где цвета меняются. Мы обнаруживаем изменения в горячем отслеживании в OnMouseMove и OnMouseLeave. Там мы установили HotTrackedIndex. Это свойство, которое запускает рисование при необходимости.

В OnGotFocus и OnLostFocus мы обновляем sh выбранный элемент, чтобы изменить его цвет в зависимости от состояния фокусировки.


Мои цвета не соответствуют вашим изображениям, но вы можете легко настроить их. Если вам нужно создать кисти и ручки нестандартных цветов, то создайте их как stati c и только для чтения, либо не забудьте утилизировать их.

private static readonly Brush HotTrackBrush = new SolidBrush(new Color(123, 45, 67));
private static readonly Pen HotTrackPen = new Pen(new Color(234, 56, 78));

An улучшенная версия этого списка позволяет выставлять различные цвета выделения и горячего отслеживания в качестве свойств, чтобы их можно было легко изменить в окне свойств. (Свойства автоматически появляются там.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...