DuiMini最大化最小化处理
原本以为这并不会造成困难,然而由于全部采用了自绘,一些系统默认处理的东西会出现问题,下面是我遇到的麻烦和解决办法。
麻烦1:最大化时覆盖了任务栏
这个在手动发送WM_SYSCOMMAND
时都会遇到,网上也有解决办法,具体就是截获WM_GETMINMAXINFO
对最大大小进行限制:
1 | UIRect ret; |
麻烦2:最大化后按钮状态未归位
最大化后再还原没有鼠标移动离开按钮区域消息产生,因此每次按钮都会保持Hover的状态,我的解决方法就是在UIButton::OnInvisible
中手动归位SetState(kBS_Normal);
,因为我们最大化时是将最大化按钮invisible
,这样即可在不可见时归位了。
麻烦3:最大化时移动窗口按钮状态未改变
我们在最大化时移动窗口都是会还原的(相当于还原后再移动),然而这个还原却并不响应WM_SYSCOMMAND
消息,因此我们的还原按钮也就无法变成最大化按钮,这里我试了很多方法,比如截获WM_MOVING``WM_NCMOUSEMOVE
等消息还有其他的方式,效果都不好,最后我想到这样相当于改变了窗口大小,肯定会响应WM_SIZE
,果然在这里捕获到了消息。
但是还有一个问题,响应这个消息时IsZoomed
将会返回false
,也就是已经还原了才响应,这样我们也就无法知道是真正的改变大小还是最大化后拖动,而如果什么都不管直接还原将会多次响应按钮的OnVisible
消息,这显然是不合理的。为了效率和代码简洁性,我在响应里面这样:
1 | if (v_wparam == SIZE_RESTORED) |
然后在OnRestore
里面判断一下当前按钮的显示隐藏状态修改即可。
麻烦4:拖动窗口到屏幕边缘无法自动排列
win7之后win的新特性就是拖动窗口到边缘将会自动排列/最大化,然而我们重绘之后就失去了这个特性,搜遍网络都找不到解决办法(网上唯一一篇directui中实现的博文测试无效)。
经过2天的调试和Demo试验,终于锁定了问题代码,我的Dialog中的Pos属性初始化时是相对于屏幕,但是会在后来转换为相对窗口,并会在WM_SIZE
中更新,然而问题在于这个时候width
和height
属性是没有问题的,但是left
和top
却是0,而不是窗口的左上角坐标,这样UpdateLayeredWindow
第二个参数就被错误初始化为0,虽然不知道为什么显示时没有问题,但是却无法自动排列了。解决方法就是直接GetWindowRect
而不是采用Dialog的GetPos
。
麻烦5:调整大小sizebox判断错误和鼠标不同步
这个问题还是比较好解决的,我复查麻烦4的时候意识到这个问题了,我没有实时更新UIWindow
的Pos,只是在更新Dialog的时候顺带更新的,然而这两个的参考完全不同,一个是屏幕,一个是窗口,自然会发生问题,解决办法是WM_MOVE
中GetWindowRect
更新一下就行。
麻烦6:WM_MOVE和WM_SIZE一直响应
分层窗口在移动和调整大小时WM_MOVE
和WM_SIZE
消息并没有按手册上那样在移动/大小修改完成后响应,而是一直在响应,也是没有在网上搜到答案,无奈只有去MSDN上问大牛。经过数次讨论,1天后@Viorel_(110035分)大牛猜测可能是Windows的所谓”Show window contents while dragging”特性导致的,就是当你拖动时即时刷新窗口,估计就是采用不断发送WM_MOVE
和WM_SIZE
消息来伪造窗口移动完成触发刷新。
解决方法只能采取曲线救国,响应WM_EXITSIZEMOVE
消息,这个只会在结束移动和修改大小时响应,然后通过内部对窗口大小/位置的判断来识别是移动还是调整大小,从而实现目的……