关于WinForm控件重绘速度慢的问题

那句-诺言 2013-04-23 10:23:01
在一个WinForm项目中需要用到座席状态监控,我在一个Panel里放置了几百个控件,每个控件对应一个座席,控件的位置就是座席人员的物理位置,所以在调整Form大小时,控件要按比例的放大和缩小(不能重排,否则位置信息就乱掉了)。
缩放效果(原始):


缩放效果(缩小):


缩放代码如下:

float fWidthRate = (float)this.Size.Width / this._lastSize.Width;
float fHeightRate = (float)this.Size.Height / this._lastSize.Height;

this.toolStripContainer.ContentPanel.Scale(new SizeF(fWidthRate, fHeightRate));


获得调整后的窗口比例然后按照此比例调整Panel及其中的控件,功能上完全可以实现,但是改变大小时控件会有很明显的重绘过程(原有控件消失,新尺寸的控件重新出现),有没有什么办法让这种调整更加平滑,最好能做到像放大缩小图片那样没有刷新过程。GDI+可以做到吗?求各位大虾解答。
...全文
941 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
kimble11 2013-10-12
  • 打赏
  • 举报
回复
是否可以分享一下用WPF的結果 剛好也有繪製大量物件的煩惱
那句-诺言 2013-09-02
  • 打赏
  • 举报
回复
帖子发表很久了,忘记结帖了。用WPF可以完全避免这种问题。
那句-诺言 2013-04-25
  • 打赏
  • 举报
回复
大家好,暂时准备换WPF做了,已经完成了Demo,证明可行,WPF在展现层真的可以用Perfect形容,等真正做完回来给大家汇报。
ttllxx 2013-04-25
  • 打赏
  • 举报
回复
用一个Grid来处理。
wumin940590725 2013-04-25
  • 打赏
  • 举报
回复
引用 15 楼 assky124 的回复:
就用一堆图片来显示,生成控件的时候映射一下坐标位置。MouseDown的时候判断鼠标位置,和对象进行关联
搞个等待界面,排好之后再出来。这个不知道你那允不允许
good_jobs 2013-04-23
  • 打赏
  • 举报
回复
哪里需要这么多控件,GDI+速度秒杀,缩放等等都可以实现
那句-诺言 2013-04-23
  • 打赏
  • 举报
回复
引用 1 楼 jy251 的回复:
增加缓冲啊 很早之前就有人讨论过这个了 你界面上的都是一些button吧,没细看,或者是你自己写的一个轻量级控件。 将这些button使用GDI+画在一个bitmap里面,然后将bitmap画出来,可以达到你要求的减少闪烁的要求。
是自己实现的控件,GDI+我之前没用过,准备试一下,谢谢。
风一样的大叔 2013-04-23
  • 打赏
  • 举报
回复
底层重绘每次会清除画布,然后再全部重新绘制,这才是导致闪烁最主要的原因。于是重载消息发送函数操作,禁掉这条消息。代码如下: protected override void WndProc(ref Message m) { if (m.Msg == 0x0014) // 禁掉清除背景消息 return; base.WndProc(ref m); } 成功! 注:双缓冲还是有用的,在更新不是很频繁且控件内含元素不是特别多的时候。一旦元素过多,每次更新时间都比较长,即便使用了双缓冲,仍解决不了闪烁问题。个人认为最终比较理想的方法还是禁掉清除背景消息。
Code従業員 2013-04-23
  • 打赏
  • 举报
回复
参看 http://blog.chinaunix.net/uid-9255716-id-107911.html
jy251 2013-04-23
  • 打赏
  • 举报
回复
而且显示的更快,你可以实验一下
jy251 2013-04-23
  • 打赏
  • 举报
回复
增加缓冲啊 很早之前就有人讨论过这个了 你界面上的都是一些button吧,没细看,或者是你自己写的一个轻量级控件。 将这些button使用GDI+画在一个bitmap里面,然后将bitmap画出来,可以达到你要求的减少闪烁的要求。
assky124 2013-04-23
  • 打赏
  • 举报
回复
就用一堆图片来显示,生成控件的时候映射一下坐标位置。MouseDown的时候判断鼠标位置,和对象进行关联
那句-诺言 2013-04-23
  • 打赏
  • 举报
回复
引用 12 楼 wumin940590725 的回复:
引用 10 楼 najunuoyan 的回复:引用 6 楼 najunuoyan 的回复:引用 1 楼 jy251 的回复:增加缓冲啊 很早之前就有人讨论过这个了 你界面上的都是一些button吧,没细看,或者是你自己写的一个轻量级控件。 将这些button使用GDI+画在一个bitmap里面,然后将bitmap画出来,可以达到你要求的减少闪烁的要求。 是自己……
这个试过了,效果跟Panel.Scale()方法差不多
那句-诺言 2013-04-23
  • 打赏
  • 举报
回复
引用 2 楼 jy251 的回复:
而且显示的更快,你可以实验一下
我的这些Button都需要交互的,点击之后要有相应的操作。如果纯图片的话有些功能就没有了。有没有单纯加速重新呈现Button的方法呢大哥?
wumin940590725 2013-04-23
  • 打赏
  • 举报
回复
引用 10 楼 najunuoyan 的回复:
引用 6 楼 najunuoyan 的回复:引用 1 楼 jy251 的回复:增加缓冲啊 很早之前就有人讨论过这个了 你界面上的都是一些button吧,没细看,或者是你自己写的一个轻量级控件。 将这些button使用GDI+画在一个bitmap里面,然后将bitmap画出来,可以达到你要求的减少闪烁的要求。 是自己实现的控件,GDI+我之前没用过,准备试一下,……
int counttabPageTransducerTest = this.tabPageTransducerTest.Controls.Count * 2 + 2; float[] factortab2 = new float[counttabPageTransducerTest]; int i = 0; factortab2[i++] = tabPageTransducerTest.Size.Width; factortab2[i++] = tabPageTransducerTest.Size.Height; foreach (Control ctr in this.tabPageTransducerTest.Controls) { factortab2[i++] = (ctr.Location.X) / (float)tabPageTransducerTest.Size.Width; factortab2[i++] = (ctr.Location.Y) / (float)tabPageTransducerTest.Size.Height; ctr.Tag = ctr.Size; } proptt = factortab2; private void tabPageTransducerTest_Resize(object sender, EventArgs e) { int i = 2; float[] scale = (float[])proptt; foreach (Control ctr in this.tabPageTransducerTest.Controls) { ctr.Left = (int)(tabPageTransducerTest.Size.Width * scale[i++]); ctr.Top = (int)(tabPageTransducerTest.Size.Height * scale[i++]); ctr.Width = (int)(tabPageTransducerTest.Size.Width / (float)scale[0] * ((Size)ctr.Tag).Width); ctr.Height = (int)(tabPageTransducerTest.Size.Height / (float)scale[1] * ((Size)ctr.Tag).Height); //每次使用的都是最初始的控件大小,保证准确无误。 } scale = null; } 用这个缩放呢,直接修改panel中的缩放
wumin940590725 2013-04-23
  • 打赏
  • 举报
回复
引用 10 楼 najunuoyan 的回复:
引用 6 楼 najunuoyan 的回复:引用 1 楼 jy251 的回复:增加缓冲啊 很早之前就有人讨论过这个了 你界面上的都是一些button吧,没细看,或者是你自己写的一个轻量级控件。 将这些button使用GDI+画在一个bitmap里面,然后将bitmap画出来,可以达到你要求的减少闪烁的要求。 是自己实现的控件,GDI+我之前没用过,准备试一下,……
明显是图片,控制不了
那句-诺言 2013-04-23
  • 打赏
  • 举报
回复
引用 6 楼 najunuoyan 的回复:
引用 1 楼 jy251 的回复:增加缓冲啊 很早之前就有人讨论过这个了 你界面上的都是一些button吧,没细看,或者是你自己写的一个轻量级控件。 将这些button使用GDI+画在一个bitmap里面,然后将bitmap画出来,可以达到你要求的减少闪烁的要求。 是自己实现的控件,GDI+我之前没用过,准备试一下,谢谢。
这个画出来之后呈现出的Button还是控件吗?是不是只是图片的效果?
那句-诺言 2013-04-23
  • 打赏
  • 举报
回复
引用 4 楼 qiujialongjjj 的回复:
底层重绘每次会清除画布,然后再全部重新绘制,这才是导致闪烁最主要的原因。于是重载消息发送函数操作,禁掉这条消息。代码如下: protected override void WndProc(ref Message m) { if (m.Msg == 0x0014) // 禁掉清除背景消息 ……
试了,效果不太明显
那句-诺言 2013-04-23
  • 打赏
  • 举报
回复
引用 7 楼 good_jobs 的回复:
哪里需要这么多控件,GDI+速度秒杀,缩放等等都可以实现
关键是GDI+不熟悉啊大哥,我现在正在看,希望今天能行吧

110,539

社区成员

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

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

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