自绘的子控件,在窗口被遮挡后不复原 解决办法

今天遇到的问题,如题,研究了很久没有得到解决,还发帖咨询了,这儿:http://topic.csdn.net/u/20110306/00/06ce2f1c-e48e-46ba-9578-cbae14208796.html?64819

偶然静下心来,终于得到问题的症结所在:

上述帖子里的几种情况,都可以归结为一点,窗口某部分被遮挡后(移出屏幕,遇到其他窗口被遮挡等),按照《windows程序设计》里面讲的,窗口被遮挡部分后,windows不会记录这部分的情况(据说xp之后不同了?),直到该部分遮挡状态消失,windows像这个窗口发消息,要求它重绘自己之前被遮挡的部分。我的窗口的问题就是,例如,移出屏幕的部分移回来之后,windows给我的程序发了重绘要求,要求重绘该部分,我的程序超水平的完成了这个任务(主窗口的Proc函数里面最后是return 0,不是return DefWindowProc (hwnd, message, wParam, lParam);之前一直用的renturn 0写的界面代码,现在换成后者就会窗口死锁,但是我所有子控件处理函数最后都是return DefWindowProc (hwnd, message, wParam, lParam);),它刷掉了整个窗口,然后开始重绘自己,并且通知被遮挡部分的所有子控件(给所有子控件发WM_PAINT消息),但是我的子控件的画图代码和主窗口有点不一样,用的是这样的:

 

问题就出在BeginPaint上,之前说过,windows并不记录被遮挡的部分,那它记录了啥?就是被遮挡部分的坐标或者范围,这个范围通过BeginPaint传了过来影响到了hdcPaint,假设窗口分为A(x坐标:0-100),B(100-200)两个区域,之前被遮挡的是A部分,

那么有三种情况

子控件甲完全位于范围A,它发现自己在这个要求重绘范围内,于是果断的重绘了自己

子控件乙x方向的坐标是60-130,100以后的部分并不处在要求重绘的范围(hdcPaint里面只有或者只允许对之前被遮挡的,0-100的部分绘图),所以虽然上图的函数清晰地表示从坐标x=0开始,宽度为70,即逻辑坐标60-130的部分要绘制,但实际上绘上去了60-100的部分,于是这就成了一个半残的按钮

例子:(被别的窗口从上门斜着划过去,所以遮挡部分是斜的)

这样

至于子控件丙。结局很明显了,主窗口根本都不通知他,当然,就算通知他了,用BeginPaint他也一点都没法把自己画上去。

那么只要在两个地方处理一下就行了;

首先是主窗口处理函数的WM_PAINT部分:

例如我的是这样:

 

那一串的SendMessage部分就是改动一;

我不知道为啥我的主窗口会把整个窗口都刷掉,不知道是不是没有调用默认命令处理函数的原因,不知道别人的会不会这样,要是只刷需要的部分,那就没我今天这么多麻烦了,有兴趣的人可以去试一下;我还要先忙着这个播放器。

因为我的主窗口移出来之后把自己所有部分都刷掉了,但是只通知被遮挡过的部分,所以我们要告诉那些被刷掉但是又没得到通知的控件,你该重绘了。

我写的是所有控件(或许可以加一个区域判断函数让有些控件少画一次?)

改动二就是这样:

 

保留BeginPaint和EndPaint这一对,但是不用它,GetWindowDC能给我们一个完全真实的,没有被windows裁剪过的窗口DC,这样才能让BitBlt想怎么画就怎么画(经试验,去掉这一对会出现问题,但是只去掉其中某一个没问题,具体什么问题就不多说了)。

现在,窗口空白处按住,想怎么甩就怎么甩,界面怎么都不会出问题了。。。(窗口任意处都能拖得并且一拖就动没有虚框的函数是抄别人的,我写的那个是拖标题栏,有虚框很烦,就干脆直接用现成的了)。

猜你喜欢

转载自blog.csdn.net/yellowcath/article/details/6226461
今日推荐