现在的位置: 首页 > 综合 > 正文

[补充]避免多控件窗体闪烁demo

2013年06月28日 ⁄ 综合 ⁄ 共 1960字 ⁄ 字号 评论关闭
前情提要:  http://www.cnblogs.com/lovesanni/archive/2009/09/08/1562844.html

前面说到模仿Control类自身的BeginUpdateInternal和EndUpdateInternal方法,封装各个控件都适用的基础类,先看代码吧

 1    class AvoidControlFlicker
 2    {
 3        private int _paintFrozen;
 4
 5        public void FreezePainting(Control toFreezeControl, bool isToFreeze)
 6        {
 7            if (null == toFreezeControl)
 8                throw new ArgumentNullException("toFreezeControl");
 9
10            if (isToFreeze && toFreezeControl.IsHandleCreated && toFreezeControl.Visible)
11            {
12                if (0 == _paintFrozen++)
13                {
14                    NativeMethods.SendMessage(toFreezeControl.Handle, NativeConsts.WM_SETREDRAW, 00);
15                }

16            }

17            if (!isToFreeze)
18            {
19                if (0 == _paintFrozen) return;
20                if (0 == --_paintFrozen)
21                {
22                    NativeMethods.SendMessage(toFreezeControl.Handle, NativeConsts.WM_SETREDRAW, 10);
23                    toFreezeControl.Invalidate(true);
24                }

25            }

26        }

27    }

代码很简单, 当需要"冻结" 控件对象时,由windows向该控件发送WM_SETREDRAW事件, 不需要"冻结"时,将该事件再发一次,改变参数即可,注意的是
1.添加一个计数器,防止多次发同一个消息
2.将控件"解冻"后,需要强制让控件重绘,即23行代码: toFreezeControl.Invalidate(true); 因为Invalidate方法是Control类自身提供的,所以可以直接拿来用了,其中true参数表示该控件的所有子控件也一并重绘了,false表示只重绘自身

那么,如果针对外部窗体怎么写呢? (不属于该进程的窗体,或者无法直接访问的窗体对象),拿windows任务栏来说,需要先获取它的句柄:

IntPtr taskBarHandle = NativeMethods.FindWindowA("Shell_TrayWnd""");

拿到句柄后就可以给它发windows消息了:

NativeMethods.SendMessage(taskBarHandle, NativeConsts.WM_SETREDRAW, 00); //禁止重绘

需要"解冻"时:

NativeMethods.SendMessage(taskBarHandle, NativeConsts.WM_SETREDRAW, 10);
NativeMethods.RedrawWindow(taskBarHandle, IntPtr.Zero, IntPtr.Zero, NativeConsts.WM_NCPAINT); 
//强制重绘

至于demo代码就很简单了, 在窗体的resize事件我创建了225个Button对象,如果不应用AvoidControlFlicker类,可以很明显看出窗体缩放时有大块的空白区域,实际效果在demo压缩包里有2个截屏视频比较,废话不多说, 点我下载

ps. 根据我测试的结果, 在vista上如果对任务栏禁止重绘,而没有启用重绘则后果很悲剧:鼠标点击之后根本无响应,还好能点击开始菜单; 在xp上暂不知晓,暂时没法找到xp环境

抱歉!评论已关闭.