Winforms - 列表框项目悬停和 select 颜色
Winforms - Listbox item hover and select color
我正在重新制作一个程序,一切都很顺利,但现在我 运行 遇到了问题。我正在重写的程序是 wpf,我在 winforms 中工作,该程序有一个列表框,我不能那么容易地重新创建:(
这是带有所选项目的列表框的图片:Selected Item
如您所见,所选项目变为蓝色,边框变为蓝色,当您停止关注表单时,它将变为白色:White item
您将鼠标悬停在上面的项目会变成蓝色,但颜色会变浅一些:
Hover Item
感谢您的帮助!
顺便说一句,我使用的是 .NET Framework 4.8
您可以在原始列表框的基础上创建自己的列表框。首次编译新列表后,它将出现在工具箱中,以便您可以将其拖放到表单中。或者您可以手动将 Form.designer.cs 中现有列表框的类型更改为 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;
以启用所有者绘图。
我们必须考虑选定的项目和热跟踪的项目,即鼠标移动到的项目。如果要绘制的item是被选中的,我们进一步区分listbox是否有焦点的情况
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));
此列表框的改进版本可以将不同的选择和热跟踪颜色显示为属性,以便您可以轻松地在属性中更改它们 window。 (属性自动出现在那里。)
我正在重新制作一个程序,一切都很顺利,但现在我 运行 遇到了问题。我正在重写的程序是 wpf,我在 winforms 中工作,该程序有一个列表框,我不能那么容易地重新创建:( 这是带有所选项目的列表框的图片:Selected Item
如您所见,所选项目变为蓝色,边框变为蓝色,当您停止关注表单时,它将变为白色:White item
您将鼠标悬停在上面的项目会变成蓝色,但颜色会变浅一些: Hover Item
感谢您的帮助!
顺便说一句,我使用的是 .NET Framework 4.8
您可以在原始列表框的基础上创建自己的列表框。首次编译新列表后,它将出现在工具箱中,以便您可以将其拖放到表单中。或者您可以手动将 Form.designer.cs 中现有列表框的类型更改为 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;
以启用所有者绘图。
我们必须考虑选定的项目和热跟踪的项目,即鼠标移动到的项目。如果要绘制的item是被选中的,我们进一步区分listbox是否有焦点的情况
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));
此列表框的改进版本可以将不同的选择和热跟踪颜色显示为属性,以便您可以轻松地在属性中更改它们 window。 (属性自动出现在那里。)