一观察
模仿前最重要的一步就是观察经过半天对QQ的摆弄和摸索总结出了以下一些特点
窗口开始粘附时检测的是鼠标坐标与桌面边界的距离特别地粘附在下面的时候检测的是与任务栏的距离
在向上移动窗口时窗口边界永远不会超出桌面上面边界
窗口是个TopMost风格
当窗口粘附在上面左边或右边并显示时你把鼠标移动到最顶端光标变成改变窗口大小的图标而单单是把窗口的top坐标设置为是不行的
粘附在下面的时候当处于移动状态那么窗口的底边是与任务栏顶边对齐的但从隐藏到显示的时候窗口的底端是与屏幕底边对齐的
隐藏后显露出来的那条线可能是一个Border但肯定的是绝不包含Client区域
关于响应鼠标的进入与移出窗口绝对不是WM_MOUSEMOVEWM_MOUSELEAVE证明你以及其慢的速度接触隐藏状态的QQ边界你会发现几乎是一触即发你又以及其慢的速度移出显示状态的QQ你会发现它的收缩反而不是一触即发的而是离边缘象素左右而WM_MOUSEMOVEWM_MOUSELEAVE只有在进入移出Client区域才响应明显和QQ不同其实从第点也可以知道
粘附在两边的时候高度会调整为桌面上边界到任务栏下边界的距离
在拖动时显示窗口内容模式下(桌面属性-外观-效果)粘附在两边的拖动出来时如果收缩之前高度比收缩后小则回复原来高度在非拖动时显示窗口内容模式下光栅会回复原来高度但释放左键时高度却是收缩时调整后的高度一开始我以为这是个BUG但我编写时同样出现这个问题发现这两种模式会影响WM_MOVING参数的意义
粘附在两边的时候当你设置任务栏自动隐藏QQ窗口会自动调整高度充满屏幕高度
窗口显示或隐藏不是一瞬间的这点在第点提到的两种模式下会有所不同
任务栏并不显示QQ窗口
二编写代码
观察完毕就开始编写了
首先新建一个基于对话框的MFC程序命名为QQHideWnd在对话框属性的styles页把border改为Resizing你也可同时把Entended styles 的 tool window 钩上对于这点我在程序了动态修改了
在QQHideWndDlgh头文件添加以下成员函数
protected
//修正移动时窗口的大小void FixMoving(UINT fwSide LPRECT pRect);
//从收缩状态显示窗口
void DoShow();
//从显示状态收缩窗口
void DoHide();
//重载函数只是为了方便调用实际调用CWnd的SetWindowPos(…)
BOOL SetWindowPos(const CWnd* pWndInsertAfterLPCRECT pCRect
UINT nFlags = SWP_SHOWWINDOW);
继续添加成员变量
private::BOOL m_isSizeChanged;//窗口大小是否改变了BOOL m_isSetTimer;//是否设置了检测鼠标的Timer
INTm_oldWndHeight;//旧的窗口宽度INTm_taskBarHeight;
//任务栏高度INTm_edgeHeight;//边缘高度INTm_edgeWidth;//边缘宽度
INTm_hideMode;//隐藏模式
BOOL m_hsFinished;//隐藏或显示过程是否完成
BOOL m_hiding;//该参数只有在!m_hsFinished才有效
//真:正在隐藏假:正在显示
增加消息响应需要注意的是有些消息你只有把右下角的 Filter for message设置为window才能看到
WM_ NCHITTESTWM_MOVING
WM_CREATE
WM_TIMER
然后来到对应的cpp文件在头部定义一些宏
//收缩模式#define HM_NONE//不收缩#define HM_TOP//向上收缩
#define HM_BOTTOM//向下收缩
#define HM_LEFT//向左收缩
#define HM_RIGHT//向右收缩
#define CM_ELAPSE //检测鼠标是否离开窗口的时间间隔
#define HS_ELAPSE//伸缩过程每步的时间间隔
#define HS_STEPS//伸缩过程分成多少步完成
#define INTERVAL//触发粘附时鼠标与屏幕边界的最小间隔单位为象素
#define INFALTE//触发收缩时鼠标与窗口边界的最小间隔单位为象素
[] [] [] []