原本以为这并不会造成困难,然而由于全部采用了自绘,一些系统默认处理的东西会出现问题,下面是我遇到的麻烦和解决办法。

麻烦1:最大化时覆盖了任务栏

这个在手动发送WM_SYSCOMMAND时都会遇到,网上也有解决办法,具体就是截获WM_GETMINMAXINFO对最大大小进行限制:

1
2
3
4
5
UIRect ret;
SystemParametersInfo(SPI_GETWORKAREA, 0, &(ret.rect()), 0);
MINMAXINFO* info = reinterpret_cast<MINMAXINFO*>(v_lparam);
info->ptMaxSize.x = ret.width();
info->ptMaxSize.y = ret.height();

麻烦2:最大化后按钮状态未归位

最大化后再还原没有鼠标移动离开按钮区域消息产生,因此每次按钮都会保持Hover的状态,我的解决方法就是在UIButton::OnInvisible中手动归位SetState(kBS_Normal);,因为我们最大化时是将最大化按钮invisible,这样即可在不可见时归位了。

麻烦3:最大化时移动窗口按钮状态未改变

我们在最大化时移动窗口都是会还原的(相当于还原后再移动),然而这个还原却并不响应WM_SYSCOMMAND消息,因此我们的还原按钮也就无法变成最大化按钮,这里我试了很多方法,比如截获WM_MOVING``WM_NCMOUSEMOVE等消息还有其他的方式,效果都不好,最后我想到这样相当于改变了窗口大小,肯定会响应WM_SIZE,果然在这里捕获到了消息。
但是还有一个问题,响应这个消息时IsZoomed将会返回false,也就是已经还原了才响应,这样我们也就无法知道是真正的改变大小还是最大化后拖动,而如果什么都不管直接还原将会多次响应按钮的OnVisible消息,这显然是不合理的。为了效率和代码简洁性,我在响应里面这样:

1
2
if (v_wparam == SIZE_RESTORED)
OnRestore();

然后在OnRestore里面判断一下当前按钮的显示隐藏状态修改即可。

麻烦4:拖动窗口到屏幕边缘无法自动排列

win7之后win的新特性就是拖动窗口到边缘将会自动排列/最大化,然而我们重绘之后就失去了这个特性,搜遍网络都找不到解决办法(网上唯一一篇directui中实现的博文测试无效)。
经过2天的调试和Demo试验,终于锁定了问题代码,我的Dialog中的Pos属性初始化时是相对于屏幕,但是会在后来转换为相对窗口,并会在WM_SIZE中更新,然而问题在于这个时候widthheight属性是没有问题的,但是lefttop却是0,而不是窗口的左上角坐标,这样UpdateLayeredWindow第二个参数就被错误初始化为0,虽然不知道为什么显示时没有问题,但是却无法自动排列了。解决方法就是直接GetWindowRect而不是采用Dialog的GetPos

麻烦5:调整大小sizebox判断错误和鼠标不同步

这个问题还是比较好解决的,我复查麻烦4的时候意识到这个问题了,我没有实时更新UIWindow的Pos,只是在更新Dialog的时候顺带更新的,然而这两个的参考完全不同,一个是屏幕,一个是窗口,自然会发生问题,解决办法是WM_MOVEGetWindowRect更新一下就行。

麻烦6:WM_MOVE和WM_SIZE一直响应

分层窗口在移动和调整大小时WM_MOVEWM_SIZE消息并没有按手册上那样在移动/大小修改完成后响应,而是一直在响应,也是没有在网上搜到答案,无奈只有去MSDN上问大牛。经过数次讨论,1天后@Viorel_(110035分)大牛猜测可能是Windows的所谓”Show window contents while dragging”特性导致的,就是当你拖动时即时刷新窗口,估计就是采用不断发送WM_MOVEWM_SIZE消息来伪造窗口移动完成触发刷新。
解决方法只能采取曲线救国,响应WM_EXITSIZEMOVE消息,这个只会在结束移动和修改大小时响应,然后通过内部对窗口大小/位置的判断来识别是移动还是调整大小,从而实现目的……