[原创][开源] SunnyUI.Net 开发日志:ListBox 增加跟随鼠标滑过高亮
SunnyUI.Net, 基于 C# .Net WinForm 开源控件库、工具类库、扩展类库、多页面开发框架

- Blog: https://www.cnblogs.com/yhuse
- Gitee: https://gitee.com/yhuse/SunnyUI
- GitHub: https://github.com/yhuse/SunnyUI
- SunnyUI.Net 系列文章目录
- 欢迎交流,QQ群:56829229 (SunnyUI技术交流群)
SunnyUI.Net 开发日志:ListBox 增加跟随鼠标滑过高亮
QQ群里,寸木说,ListBox鼠标移动时,当前行需要焦点,我想了想,不难实现啊

不就是在鼠标移动时重绘Item嘛,何况选中的Item已经改了颜色了。
见UIListBox代码:
protected override void OnDrawItem(DrawItemEventArgs e)
{
base.OnDrawItem(e);
BeforeDrawItem?.Invoke(this, Items, e);
if (Items.Count == 0)
{
return;
} e.DrawBackground(); if (e.Index < 0 || e.Index >= Items.Count)
{
return;
} StringFormat sStringFormat = new StringFormat();
sStringFormat.LineAlignment = StringAlignment.Center; Color backColor = (e.State & DrawItemState.Selected) == DrawItemState.Selected ? ItemSelectBackColor : BackColor;
Color foreColor = (e.State & DrawItemState.Selected) == DrawItemState.Selected ? ItemSelectForeColor : ForeColor; Rectangle rect = new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width - 1, e.Bounds.Height - 1);
e.Graphics.FillRectangle(BackColor, e.Bounds);
e.Graphics.FillRoundRectangle(backColor, rect, 5);
e.Graphics.DrawString(Items[e.Index].ToString(), e.Font, foreColor, e.Bounds, sStringFormat);
}
看:(e.State & DrawItemState.Selected) == DrawItemState.Selected 选中行状态嘛
看了e.State有e.State == DrawItemState.HotLight,不就是高亮的么,于是开始撸代码,加状态判断
Run
晕。。。没变,这HotLight不起作用,好吧,问度娘。。。
翻山越岭,跋山涉水。。。
找到这篇:https://www.jb51.cc/csharp/101121.html
其中提到:
我在我的WinForms应用程序中使用OwnerDrawFixed作为DrawMode用于自定义ListBox控件.当用户将鼠标悬停在列表框项目上时,我希望重新绘制ListBoxItem的背景(或执行其他操作),即在MouseMove …DrawItemState.HotLight永远不适用于ListBox,所以我想知道如何模拟它,如何解决这个问题.
DrawItemState.HotLight永远不适用于ListBox,是永远。。。怎么这么远。。。
继续往下看:
解决方法
DrawItemState.HotLight仅适用于所有者绘制的菜单,而不适用于列表框.对于ListBox,您必须自己跟踪项目:
public partial class Form1 : Form
{
private int _MouseIndex = -1; public Form1()
{ InitializeComponent(); } private void listBox1_DrawItem(object sender,DrawItemEventArgs e)
{
Brush textBrush = SystemBrushes.WindowText; if (e.Index > -1)
{
if (e.Index == _MouseIndex)
{
e.Graphics.FillRectangle(SystemBrushes.HotTrack,e.Bounds);
textBrush = SystemBrushes.HighlightText;
}
else
{
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
e.Graphics.FillRectangle(SystemBrushes.Highlight,e.Bounds);
textBrush = SystemBrushes.HighlightText;
}
else
e.Graphics.FillRectangle(SystemBrushes.Window,e.Bounds);
}
e.Graphics.DrawString(listBox1.Items[e.Index].ToString(),e.Font,textBrush,e.Bounds.Left + 2,e.Bounds.Top);
}
} private void listBox1_MouseMove(object sender,MouseEventArgs e)
{
int index = listBox1.IndexFromPoint(e.Location);
if (index != _MouseIndex)
{
_MouseIndex = index;
listBox1.Invalidate();
}
} private void listBox1_MouseLeave(object sender,EventArgs e)
{
if (_MouseIndex > -1)
{
_MouseIndex = -1;
listBox1.Invalidate();
}
}
}
兄弟们,人家这花两年时间解决的,应该有用,继续再找找,又找到一篇洋文的:
https://stackoverflow.com/questions/1316027/listbox-drawitem-hotlight-state-in-the-ownerdraw-mode
It took me only two years to find the answer for you, but here it is:
The DrawItemState.HotLight only applies to owner drawn menus, not the listbox.
For the ListBox, you have to keep track of the item yourself:
看看,也是两年,估计上面中文的从这个翻译过来。
除了这俩,还真没找到。
继续撸代码,果真管用。不过还是有问题,鼠标滑快了,ListBox闪烁的厉害。
分析代码 listBox1.Invalidate(); 这是刷新全部的。鼠标滑过也就和本次选中和上次选中的有关系。
就刷这两个Item就行,有了思路,撸代码三连发:
private int lastIndex = -1;
private int mouseIndex = -1; [Browsable(false)]
public int MouseIndex
{
get => mouseIndex;
set
{
if (mouseIndex != value)
{
if (lastIndex >= 0 && lastIndex != SelectedIndex)
{
OnDrawItem(new DrawItemEventArgs(this.CreateGraphics(), Font, GetItemRectangle(lastIndex), lastIndex, DrawItemState.Grayed));
} mouseIndex = value;
if (mouseIndex >= 0 && mouseIndex != SelectedIndex)
{
OnDrawItem(new DrawItemEventArgs(this.CreateGraphics(), Font, GetItemRectangle(value), value, DrawItemState.HotLight));
} lastIndex = mouseIndex;
}
}
} protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
MouseIndex = IndexFromPoint(e.Location);
} protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
MouseIndex = -1;
}
其中 new DrawItemEventArgs(this.CreateGraphics(), Font, GetItemRectangle(value), value, DrawItemState.HotLight)
第一个参数Graphics,也找了一会儿,后来看这篇:
https://www.cnblogs.com/yuanyeguhong/archive/2013/09/20/3330606.html
其实就是Graphics对象的DrawString方法,而参数e中的Graphics是如何来的呢。
我们接着分析DrawItemEventArgs这个类,他既然是对listBox1某一项的属性的打包,
那么我估计其中的Graphics对象就是由listBox1.creatgraphics而来的。
好了,到此我们就可以自定义重绘listbox某项的函数了,可任意调用的哦!
好了,至此,问题都已找到答案,再捋一下思路,把逻辑理顺。撸代码,调试,OK!!!
主要代码如下:
protected override void OnDrawItem(DrawItemEventArgs e)
{
base.OnDrawItem(e); BeforeDrawItem?.Invoke(this, Items, e);
if (Items.Count == 0)
{
return;
} bool otherState = e.State == DrawItemState.Grayed || e.State == DrawItemState.HotLight;
if (!otherState)
{
e.DrawBackground();
} if (e.Index < 0 || e.Index >= Items.Count)
{
return;
} StringFormat sStringFormat = new StringFormat();
sStringFormat.LineAlignment = StringAlignment.Center; bool isSelected = (e.State & DrawItemState.Selected) == DrawItemState.Selected;
Color backColor = isSelected ? ItemSelectBackColor : BackColor;
Color foreColor = isSelected ? ItemSelectForeColor : ForeColor; Rectangle rect = new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width - 1, e.Bounds.Height - 1);
if (!otherState)
{
e.Graphics.FillRectangle(BackColor, e.Bounds);
e.Graphics.FillRoundRectangle(backColor, rect, 5);
e.Graphics.DrawString(Items[e.Index].ToString(), e.Font, foreColor, e.Bounds, sStringFormat);
}
else
{
if (e.State == DrawItemState.Grayed)
{
backColor = BackColor;
foreColor = ForeColor;
} if (e.State == DrawItemState.HotLight)
{
backColor = HoverColor;
foreColor = ForeColor;
} e.Graphics.FillRectangle(BackColor, e.Bounds);
e.Graphics.FillRoundRectangle(backColor, rect, 5);
e.Graphics.DrawString(Items[e.Index].ToString(), e.Font, foreColor, e.Bounds, sStringFormat);
} AfterDrawItem?.Invoke(this, Items, e);
}
看,DrawItemState.HotLight咱也给实现了,DrawItemState.Grayed 我是随便选的状态,区别于其他。
想看全部代码,看我的开源项目吧,https://gitee.com/yhuse/SunnyUI ,哎,客官别走嘛,点个Star先。
原创文章,转载请保留链接 Sunny's blog
[原创][开源] SunnyUI.Net 开发日志:ListBox 增加跟随鼠标滑过高亮的更多相关文章
- [原创][开源] SunnyUI.Net 开发日志:UIBarChart 坐标轴刻度取值算法
_ 在开发UIBarChart的过程中,需要绘制Y轴的刻度,数据作图时,纵横坐标轴刻度范围及刻度值的取法,很大程度上取决于数据的分布.对某一组数据,我们很容易就能知道如何选取这些值才能使图画得漂亮.但 ...
- [原创][开源] SunnyUI.Net 更新日志
SunnyUI.Net, 基于 C# .Net WinForm 开源控件库.工具类库.扩展类库.多页面开发框架 Blog: https://www.cnblogs.com/yhuse Gitee: h ...
- [原创][开源] SunnyUI.Net 系列文章目录
SunnyUI.Net, 基于 C# .Net WinForm 开源控件库.工具类库.扩展类库.多页面开发框架 Blog: https://www.cnblogs.com/yhuse Gitee: h ...
- [原创][开源]SunnyUI.Net, C# .Net WinForm开源控件库、工具类库、扩展类库、多页面开发框架
SunnyUI.Net, 基于 C# .Net WinForm 开源控件库.工具类库.扩展类库.多页面开发框架 Blog: https://www.cnblogs.com/yhuse Gitee: h ...
- [原创][开源] SunnyUI.Net 安装
SunnyUI.Net, 基于 C# .Net WinForm 开源控件库.工具类库.扩展类库.多页面开发框架 Blog: https://www.cnblogs.com/yhuse Gitee: h ...
- [原创][开源] SunnyUI.Net 字体图标
SunnyUI.Net, 基于 C# .Net WinForm 开源控件库.工具类库.扩展类库.多页面开发框架 Blog: https://www.cnblogs.com/yhuse Gitee: h ...
- [原创][开源] SunnyUI.Net 主题
SunnyUI.Net, 基于 C# .Net WinForm 开源控件库.工具类库.扩展类库.多页面开发框架 Blog: https://www.cnblogs.com/yhuse Gitee: h ...
- [原创][开源] SunnyUI.Net 国际化
SunnyUI.Net, 基于 C# .Net WinForm 开源控件库.工具类库.扩展类库.多页面开发框架 Blog: https://www.cnblogs.com/yhuse Gitee: h ...
- C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志
C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...
随机推荐
- 2019-2020-1 20199310《Linux内核原理与分析》第八周作业
1.问题描述 在前面的文章中,学习了在Linux系统之中如何创建一个新进程进行追踪,本文将围绕编译链接的过程和ELF可执行文件格式,对Linux内核装载和启动一个可执行程序. 2.解决过程 2.1 E ...
- fseek 在以字符串模式打开的文件中工作不正常 [MSDN]
For streams opened in text mode, fseek and _fseeki64 have limited use, because carriage return-linef ...
- MySQL join的7种理论及SQL写法
转载于 https://www.cnblogs.com/dinglinyong/p/6656315.html 建表 在这里呢我们先来建立两张有外键关联的张表. CREATE DATABASE d ...
- js 实现对象的混合与克隆效果,带完整版解析代码[helpers.js]
前言: 本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽. 本篇文章为您分析一下原生JS写淘宝无缝轮播图效果 对象混合 ...
- mysql 之 清空表中数据
清空表的时候注意外键约束 命令版 查询数据库中所有表名select table_name from information_schema.tables where table_schema='DB_n ...
- 【JAVA基础】10 Object类
1. Object类概述 是类层次结构的根类 每个类都使用 Object 作为超类 所有类都直接或者间接的继承自该类 所有对象(包括数组)都实现这个类的方法. 2. Object的构造方法 publi ...
- Ubuntu搭建NTP服务器
NTP简介 NTP是Network Time Protocol的缩写,又称为网络时间协议.是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提 ...
- MongoDB学习(四):通过Java使用MongoDB
环境配置 在Java项目中使用MongoDB,需要在项目中引入mongo.jar这个包.下载地址:下载 请尽量下载较新的版本,本文用的是2.10.1. 连接MongoDB public synchro ...
- vlookup匹配不出,明明文本内容是一样的,求解答。
看起来很简单,肉眼看都知道就是匹配他,但是就是匹配不出.用trim去掉了空格,用分列去掉空格.tab这些看不见的.也改了单元格是数字型,而且粘贴是用数值型粘贴,全都匹配不出用if函数验证两个匹配对象是 ...
- Knapsack Problem
0-1背包 描述:N件物品,第i件的重量是w[i],价值v[i].有一个容量为W的背包,求将哪些物品放入背包可使总价值最大.每件物品可以用0或1次. 分析:根据题意,可以写出表达式: \[max(\S ...