VC 闪屏

背景介绍:

我在动态库中创建了一个对话框,这个对话框上有很多子控件,对话框本身是没有边框的child风格的,此对话框用来嵌到一个父窗口中(比如CView类中),结果发现,只要CView窗口大小改变,我的对话框上面的子控件就不断地闪屏,以下记录我解决此问题的过程


1.窗口需要重绘时会发出连个消息 WM_ERASEBKGND和WM_PAINT消息,顺序是先发送WM_ERASEBKGND然后才发送WM_PAINT;

1):WM_PERASEBKGND消息的作用是擦掉窗口中原先的东西,然后以画刷来刷新背景,比如一个对话框上有多个子控件,当对话框需要重绘时会先收到

WM_ERASEBKGND消息,默认处理程序会把对话框上所有的子控件擦掉,并用指定画刷刷整个窗口,这样整个窗口就显现出一模一样的背景;

2):在上述工作做完之后,系统是发送WM_PAINT消息来提供重绘工作,父窗口重绘时会通知它上面所有的子窗口进行重绘,子窗口重绘时同样是先收到

WM_PERASEBKGND消息擦掉以前的东西,然后才进行重绘;这个过程中如果重绘过快(比如改变父窗口大小),会导致子窗口控件不断里擦掉背景,重新绘制控件本身,这样频繁里擦除-绘制如果机器太差就会造成闪屏(原先的控件擦掉了,新的控件还没有完成绘制),可以通过子类化控件类,然后处理WM_PERASEBKGND这个消息,让其不擦掉背景,直接在原先的基础上绘制,就不会导致不断擦除-绘制工作了,只是在原先的基础上做无用功,而不会擦掉背景。但是对于Spin控件能这样解决,而对与CStatic控件还不能解决,CStatic控件仍然闪屏。。。。。

3):有待解决部分控件闪屏问题,

找到问题所在:因为CStatic控件没设成透明的,把它的背景搞成透明的 然后跟上面的一样处理就不会闪屏了;

4):经过一下午的调试发现上面的解决办法都不靠谱,因为只要父窗口大小发生改变,就会不停的发送重绘消息,一旦父窗口收到重绘消息,全部子窗口必然都收到重绘消息,不管你怎么处理,都有处理不完的WM_PAINT和WM_ERASEBKGND消息,如果每个子控件都让处理WM_ERASEBKGND的函数返回TRUE;对话框上面的子控件随便移动位置时就有可能因为背景没有擦掉而导致控件重合,接下来我创建了一个基于对话框的工程,让我的对话框嵌入到这个对话框工程中,我发现此事更改对话框工程并不会造成我DLL中对话框上面的控件全部重绘,通过SPY++工具我发现CView窗口与CDialog窗口的Class风格有所不同,CView窗口多出个CS_HREDRAW和CS_VREDRAW两个属性,而对话框工程则没有,所以我猜测是因为这两个属性导致父窗口不断里发出WM_PAINT消息,得出结论,只要把父窗口的这两个Class属性去掉就OK了。可能有人有疑惑,这样当父窗口的大小缩小到遮挡住了我的DLL中的对话框界面了,当父窗口重新放大时,我的DLL对话框还能收到WM_PAINT消息吗? 答案是肯定能收到,系统会自动判断被遮挡的窗口部分并发出重绘消息。

补充两点:

1.if(0==SetClassLong(this->m_hWnd,GCL_STYLE,GetClassLong(this->m_hWnd,GCL_STYLE)&~CS_HREDRAW ) )
MessageBox("修改失败");
if(0==SetClassLong(this->m_hWnd,GCL_STYLE,GetClassLong(this->m_hWnd,GCL_STYLE)&~CS_VREDRAW ) )
MessageBox("修改");通过这个方法去除窗口类的这两个属性风格,放在OnCreate函数中就行了;

2.如果你是单文档框架,你把我的DLL中的对话框嵌入到视类中,然后通过改变视类边框调整大小,就要注意你此时拉的边框不是视类的 而是框架类的,所以既要把视类的这两个属性去掉,也要把框架类中的这两个属性去掉,这是MFC的基本知识。


以上就是这两天的工作心得,如果有疑问 可以留言 我们共同探讨。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值