您的位置:首页 > 其它

避免多控件窗体闪烁

2010-04-22 16:55 211 查看
前面说到模仿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,
0
,
0
);

15



}

16



}

17



if
(
!
isToFreeze)

18







{

19



if
(
0

==
_paintFrozen)
return
;

20



if
(
0

==

--
_paintFrozen)

21







{

22



NativeMethods.SendMessage(toFreezeControl.Handle, NativeConsts.WM_SETREDRAW,
1
,
0
);

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,
0
,
0
);
//
禁止重绘

需要"解冻"时:
NativeMethods.SendMessage(taskBarHandle, NativeConsts.WM_SETREDRAW,
1
,
0
);

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

至于demo代码就很简单了,
在窗体的resize事

PS:原文
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: