分类: C/C++
2008-05-18 20:21:47
来源: | ||||||||
| ||||||||
摘要: 某天在上看到有人发帖询问QQ自动伸缩窗口是怎么实现的,我也好想知道,于是到百度一搜索,结果不多,来来去去都是那几篇,下载那些demo运行一下,发觉与QQ相差很大,于是决定自己动手做个,要求要近乎完美地模仿这个功能。由于是些效果的东西,贴图也看不出来,所以文章里就不截图了,想看效果的就直接运行源代码的demo吧。 一、观察 模仿前最重要的一步就是观察,经过半天对QQ的摆弄和摸索,总结出了以下一些: 1、窗口开始粘附时,检测的是鼠标坐标与桌面边界的距离,特别地,粘附在下面的时候,检测的是与任务栏的距离; 2、在向上移动窗口时,窗口边界永远不会超出桌面上面边界; 3、窗口是个 TopMost 风格; 4、当窗口粘附在上面、左边或右边并显示时,你把鼠标移动到最顶端,光标变成改变窗口大小的图标,而单单是把窗口的top坐标设置为0是不行的; 5、粘附在下面的时候,当处于移动状态,那么窗口的底边是与任务栏顶边对齐的,但从隐藏到显示的时候,窗口的底端是与屏幕底边对齐的; 6、隐藏后显露出来的那条线可能是一个Border,但肯定的是绝不包含Client区域; 7、关于响应鼠标的进入与移出窗口,绝对不是WM_MOUSEMOVE、WM_MOUSELEAVE。证明:你以及其慢的速度隐藏状态的QQ边界,你会发现几乎是“一触即发”,你又以及其慢的速度移出显示状态的QQ,你会发现它的收缩反而不是“一触即发”的,而是离边缘10象素左右。而WM_MOUSEMOVE,WM_MOUSELEAVE,只有在进入、移出Client区域才,明显和QQ不同,其实从第6点也可以知道; 8、粘附在两边的时候,高度会调整为桌面上边界到任务栏下边界的距离; 9、在“拖动时显示窗口内容”模式下(桌面-外观-效果),粘附在两边的拖动出来时;如果收缩之前高度比收缩后小则回复原来高度,在非“拖动时显示窗口内容”模式下,光栅会回复原来高度,但左键时,高度却是收缩时调整后的高度,一开始我以为这是个BUG,但我编写时同样出现这个问题,发现这两种模式会影响WM_MOVING参数的意义; 10、粘附在两边的时候当你设置任务栏自动隐藏,QQ窗口会自动调整高度充满屏幕高度; 11、窗口显示或隐藏不是一瞬间的,这点在第9点提到的两种模式下,会有所不同; 12、任务栏并不显示QQ窗口; 二、编写代码 观察完毕,就开始编写了。 首先新建一个基于对话框的MFC程序,命名为QQHideWnd,在对话框属性的styles页把border改为Resizing,你也可同时把Entended styles 的 tool window 钩上,对于这点我在程序了动态修改了。 在QQHideWndDlg.h头文件添加以下成员函数:
继续添加成员变量:
增加消息响应,需要注意的是有些消息你只有把右下角的 Filter for message设置为window才能看到。
然后来到对应的cpp文件,在头部定义一些宏:
然后在构造函数初始化成员变量:
完成了一些初始的工作,那么就开始进入关键的函数实现了。首先是在OnCreate做些窗口的初始化和获得一些系统。 【代码一】
接着如何知道鼠标进入或移出窗口呢?在前面我已经证明了WM_MOUSEMOVE和WM_MOUSELEAVE不符合我们的要求,于是我用了WM_ NCHITTEST这个消息,你可以看到我在这个消息响应函数中用了两个SetTimer,一个用于检测鼠标是否离开,一个用于伸缩过程,不管你喜欢不喜欢,要达到第7点和第11点,这个是必须的,考虑的效率问题,在不需要的时候关闭这些Timer就好了。 【代码二】
然后在OnTimer中 【代码三】
暂时不管OnTimer中的DoHide(); DoShow(); |