我正在尝试为我的Winforms应用程序从WPF应用程序重新创建一个列表框。但我真的不知道从哪里开始。所选项目的边框为蓝色(1),当它未聚焦时,它将变为白色(2)。悬停颜色应为浅蓝色(3)谢谢你的帮助!(By我使用的是.NET Framework 4.8)
ccgok5k51#
您可以从原始列表框派生创建自己的列表框。新列表首次编译后,它将出现在工具箱中,以便您可以将其拖放到表单中。或者您可以在Form.designer.cs中手动将现有列表框的类型更改为ListBoxEx。
ListBoxEx
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绘制背景。DrawRectangle绘制边框。请注意,边框矩形必须比e.Bounds矩形小一个像素,否则不会绘制右边框和下边框。如果当前项目没有被选中,我们测试它是否是热跟踪。如果是,我们用不同的颜色绘制。否则我们用e.DrawBackground();绘制默认背景。然后我们用DrawString在背景上绘制文本。为了使所有这些工作,我们还必须使列表框中颜色发生变化的区域无效。我们在OnMouseMove和OnMouseLeave中检测热跟踪的变化。在那里我们设置HotTrackedIndex。这是一个在必要时触发绘制的属性。在OnGotFocus和OnLostFocus中,我们刷新所选项目以根据焦点状态更改其颜色。我的颜色与您的图像不匹配,但您可以轻松调整它们。如果您需要以非标准颜色创建画笔和钢笔,请将其创建为静态和只读,或者不要忘记将其丢弃。
OnDrawItem
DrawMode = DrawMode.OwnerDrawFixed;
FillRectangle
DrawRectangle
e.Bounds
e.DrawBackground();
DrawString
OnMouseMove
OnMouseLeave
HotTrackedIndex
OnGotFocus
OnLostFocus
private static readonly Brush HotTrackBrush = new SolidBrush(new Color(123, 45, 67)); private static readonly Pen HotTrackPen = new Pen(new Color(234, 56, 78));
型此列表框的改进版本可以将不同的选择和热跟踪颜色显示为属性,以便您可以在属性窗口中轻松更改它们。(属性自动显示在那里。)
1条答案
按热度按时间ccgok5k51#
您可以从原始列表框派生创建自己的列表框。新列表首次编译后,它将出现在工具箱中,以便您可以将其拖放到表单中。或者您可以在Form.designer.cs中手动将现有列表框的类型更改为
ListBoxEx
。字符串
我们通过重写
OnDrawItem
来改变列表框的外观。在构造函数中,我们设置DrawMode = DrawMode.OwnerDrawFixed;
以启用所有者绘制。我们必须考虑选中项和热跟踪项,即鼠标移动过的项。如果要绘制的项是选中项,我们进一步区分列表框是否具有焦点。
FillRectangle
绘制背景。DrawRectangle
绘制边框。请注意,边框矩形必须比e.Bounds
矩形小一个像素,否则不会绘制右边框和下边框。如果当前项目没有被选中,我们测试它是否是热跟踪。如果是,我们用不同的颜色绘制。否则我们用
e.DrawBackground();
绘制默认背景。然后我们用
DrawString
在背景上绘制文本。为了使所有这些工作,我们还必须使列表框中颜色发生变化的区域无效。我们在
OnMouseMove
和OnMouseLeave
中检测热跟踪的变化。在那里我们设置HotTrackedIndex
。这是一个在必要时触发绘制的属性。在
OnGotFocus
和OnLostFocus
中,我们刷新所选项目以根据焦点状态更改其颜色。我的颜色与您的图像不匹配,但您可以轻松调整它们。如果您需要以非标准颜色创建画笔和钢笔,请将其创建为静态和只读,或者不要忘记将其丢弃。
型
此列表框的改进版本可以将不同的选择和热跟踪颜色显示为属性,以便您可以在属性窗口中轻松更改它们。(属性自动显示在那里。)