请教自绘聊天列表 滚动条事件侦听CPU过高的问题

ssslar 2017-06-20 09:33:05
如题,如下图,为通过panel、label等组合起来的一个列表控件。

其中右侧滚动条,是完全自绘的一个半透明控件。
效果为:
鼠标进入该区域后判断是否show出滚动条,离开后隐藏,并根据空间容器大小计算滚动条大小。
滚动条代码是:
class UMScrollBar:System.Windows.Forms.Control
{
private int Alpha = 125;
private System.ComponentModel.Container compents = new Container();

Color drawColor;
Pen borderPen;
SolidBrush fillBrush;

public UMScrollBar()
{
SetStyle(System.Windows.Forms.ControlStyles.Opaque, true);
base.CreateControl();

this.BackColor = System.Drawing.Color.FromArgb(180, 180, 180);
this.Width = 6;

drawColor = Color.FromArgb(this.Alpha, this.BackColor);
borderPen = new Pen(drawColor, 0);
fillBrush = new SolidBrush(drawColor);
}

protected override void Dispose(bool disposing)
{
if (disposing)
{
if (compents != null)
compents.Dispose();
}
base.Dispose(disposing);
}

protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawRectangle(borderPen, 0, 0, this.Size.Width, this.Size.Height);
e.Graphics.FillRectangle(fillBrush, 0, 0, this.Size.Width, this.Size.Height);

base.OnPaint(e);
}

protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00000020; //0x20; // 开启 WS_EX_TRANSPARENT,使控件支持透明
//cp.ExStyle |= 0x02000000;
return cp;
}
}

public void ReCalcHeight(int ContainerHeight,int ContentHeight)
{
float scale = (float)ContainerHeight / (float)ContentHeight;
this.Height = (int)(scale * ContainerHeight);

ReVisible(ContainerHeight, this.Visible);
}

public void ReCalcLocation(int ContentTop,int ContainerHeight,int ContentHeight)
{
float scale = (float)ContainerHeight / (float)ContentHeight;
this.Top = 0- (int)(ContentTop * scale);
}

public void ReVisible(int ContainerHeight,bool bVisible)
{
this.Visible = bVisible;

if (this.Height == ContainerHeight)
this.Visible = false;
}

}


现在问题有,当频繁的鼠标划入划出时,CPU占用较高。通过VS性能分析,发现ReVisible函数占用最大。
因为其中的每一条记录都是填充了父容器,所以父容器注册的MouseEnter,MouseLeave事件无法收到,遂把所有的子控件MouseEnter,MouseLeave事件均注册给了容器,统一来调用ReVisible.
请问,有没有什么好的方法和建议来优化这一问题?
1.不再通过事件,而是定时器?
2.通过事件,但只获取父容器的MouseEnter和MouseLeave?
...全文
228 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
ssslar 2017-06-26
  • 打赏
  • 举报
回复
现在结贴,最终没有完美解决。 折中了一下解决。 隐藏显示滚动条不再通过设置Visible属性,会触发OnPaint,而是通过移动位置到非客户区。 并添加了双缓冲,参照:http://www.cnblogs.com/zhaoshaoxiong/p/5157394.html
ssslar 2017-06-22
  • 打赏
  • 举报
回复
引用 9 楼 bloodish 的回复:
Windows Form,如果父容器被控件填满(Dock.Fill),是不会触发Mouse相关事件的. 楼主,你的Scrollbar的绘制,不管怎么说也该做些double buffer的处理,先画到bitmap,在把bitmap画到UI上.
引用 13 楼 crystal_lz 的回复:
http://bbs.csdn.net/topics/390277105虽然是5年前写的了。。。。
6666666666,研究下,先去弄别的了,弄完结贴,谢大拿
crystal_lz 2017-06-22
  • 打赏
  • 举报
回复
http://bbs.csdn.net/topics/390277105虽然是5年前写的了。。。。
xuggzu 2017-06-21
  • 打赏
  • 举报
回复
所有控件都调用revisible的话,势必会造成onpaint多次重绘。楼主可以在onpaint中打印调试信息,看重绘频率,再做处理。
ssslar 2017-06-21
  • 打赏
  • 举报
回复
引用 9 楼 bloodish 的回复:
Windows Form,如果父容器被控件填满(Dock.Fill),是不会触发Mouse相关事件的. 楼主,你的Scrollbar的绘制,不管怎么说也该做些double buffer的处理,先画到bitmap,在把bitmap画到UI上.
那这个时候如何处理这种mouse事件?
ssslar 2017-06-21
  • 打赏
  • 举报
回复
引用 9 楼 bloodish 的回复:
Windows Form,如果父容器被控件填满(Dock.Fill),是不会触发Mouse相关事件的. 楼主,你的Scrollbar的绘制,不管怎么说也该做些double buffer的处理,先画到bitmap,在把bitmap画到UI上.
对对,现在会有闪烁 请教可否给出代码部分
bloodish 2017-06-21
  • 打赏
  • 举报
回复
Windows Form,如果父容器被控件填满(Dock.Fill),是不会触发Mouse相关事件的. 楼主,你的Scrollbar的绘制,不管怎么说也该做些double buffer的处理,先画到bitmap,在把bitmap画到UI上.
ssslar 2017-06-21
  • 打赏
  • 举报
回复
引用 6 楼 Libby1984 的回复:
感觉要实现楼主要的功能,只需要在容器上注册一个MouseEnter和MouseLeave事件就可以,和里面的子元素完全没有关系。楼主说是ReVisible占用了大量的CUP资源,但是从代码上看,这个函数这是设置了一个Visible 属性,本身不会太占资源,那么楼主就要考虑是不是Visible属性的改变引起了重绘,导致占用资源,或者有某些意外的情况频繁的引起了这个函数的调用。
最初也是这么做的,但发现,当其内有子控件的时候,容器的事件好像被子控件拦截了?所以才给所有的子控件注册了事件,并统一调用ReVisible
ssslar 2017-06-21
  • 打赏
  • 举报
回复
引用 4 楼 xuggzu 的回复:
感觉问题出在鼠标出入判读显示上,楼主检查相关代码。
现在做的,就是在所有的控件的MouseEnter和MouseLeave中调用ReVisible
  • 打赏
  • 举报
回复
感觉要实现楼主要的功能,只需要在容器上注册一个MouseEnter和MouseLeave事件就可以,和里面的子元素完全没有关系。楼主说是ReVisible占用了大量的CUP资源,但是从代码上看,这个函数这是设置了一个Visible 属性,本身不会太占资源,那么楼主就要考虑是不是Visible属性的改变引起了重绘,导致占用资源,或者有某些意外的情况频繁的引起了这个函数的调用。
bloodish 2017-06-21
  • 打赏
  • 举报
回复
问题比较有意思, 楼主,方便的话,传个Demo上来.
xuggzu 2017-06-21
  • 打赏
  • 举报
回复
感觉问题出在鼠标出入判读显示上,楼主检查相关代码。
ssslar 2017-06-21
  • 打赏
  • 举报
回复
引用 2 楼 sp1234 的回复:
[quote=引用 楼主 peilinok 的回复:]因为其中的每一条记录都是填充了父容器,所以父容器注册的MouseEnter,MouseLeave事件无法收到,遂把所有的子控件MouseEnter,MouseLeave事件均注册给了容器
看不懂这是什么意思。 鼠标移动到滚动条上范围内的时候,才应该触发 MouseEnter、MouseLeave 之类的事件。怎么跟什么“子控件”的 MouseLeave 有关系?或者假设根本得不到什么 MouseEnter、MouseLeave 事件那么就不硬要捕获它,只要知道鼠标MouseOver之类的、然后跟滚动条区域判断是否“命中”这个区域就行了。 总之是自己在你的滚动条控件上它自己来产生MouseEnter、MouseLeave事件,怎么会跟别的控件有关?[/quote] 感谢回复,是这样的。你可以打开微信windows版。里面的通讯录或者聊天列表的滚动条时你的鼠标滑入整个区域内自动出现的,而不是放在滚动条上才会出现的。效果想要达到和微信一样的。
  • 打赏
  • 举报
回复
引用 楼主 peilinok 的回复:
因为其中的每一条记录都是填充了父容器,所以父容器注册的MouseEnter,MouseLeave事件无法收到,遂把所有的子控件MouseEnter,MouseLeave事件均注册给了容器
看不懂这是什么意思。 鼠标移动到滚动条上范围内的时候,才应该触发 MouseEnter、MouseLeave 之类的事件。怎么跟什么“子控件”的 MouseLeave 有关系?或者假设根本得不到什么 MouseEnter、MouseLeave 事件那么就不硬要捕获它,只要知道鼠标MouseOver之类的、然后跟滚动条区域判断是否“命中”这个区域就行了。 总之是自己在你的滚动条控件上它自己来产生MouseEnter、MouseLeave事件,怎么会跟别的控件有关?
ssslar 2017-06-20
  • 打赏
  • 举报
回复
在线等。。。。
本课程是《Flowable流程入门课程》的后续高级课程。在学习本课程前,应先学习入门课程,以掌握相关基础知识。高级课程着重讲解Flowable工作流的高级概念、复杂理论和实战应用。课程内容包括流程管理思想、技术与标准、工作流的控制模式和资源模式;Flowable数据库表及变量;与Spring、Spring Boot的集成;BPMN 2.0主要类图;Flowable高级服务如JAVA服务任务、脚本任务、Web Service任务、外部工作者任务、多实例任务、补偿处理程序、子流程和调用活动等;Flowable事件侦听器、执行侦听器和任务侦听器;Flowable历史和REST API;Flowable事务、并发性、身份管理及LDAP集成;Flowable高级主题如流程实例迁移、异步执行器的设计与配置、用于高并发的UUID ID生成器、多租户、高级流程引擎配置、执行自定义SQL和实验性流程调试器等;Flowable Eclipse设计器特性及定制;Flowable 事件注册;Flowable相关标准和规范如ISO8601标准和cron等。本课程对Flowable官方文档进行了彻底梳理和融汇贯通,并结合实践,形象生动、系统全面、简单易懂地呈现给大家,让大家从开源软件文档冗长耗时、英文晦涩难懂、概念理解困难、知识点分散等困境中解脱出来,从而能快速地将Flowable具有的高级特性应用到项目的高级需求和复杂实践中去。课程特色:案例和代码驱动、基础概念与经典实战相结合、知识环节融会贯通、关联知识平滑拓展、概念和原理展示形象生动。

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧