窗口必须时刻停靠在屏幕上端位置
鼠标离开窗口后窗口隐藏
API接口
BOOL SSWinAutoHideWorkB(HWND hWnd, UINT_PTR uTimerID = 0);
BOOL SSWinAutoHideWorkE(HWND hWnd);
实现技术
1.在函数SSWinAutoHideWorkB中,调用G/SetWindowLongPtr 来Hook窗口过程,这样窗口的消息都会经过我们自己的回调函数.
2.窗口的显示隐藏动画效果需要需要在另外一个线程里来做,这样可以不影响界面响应.
3.控制窗口行为需要一些变量与窗口联系起来,同时为了支持多个窗口的控制不相互影响,不能用全局变量,在这里用SetProp来把这些变量与特定的窗口联系起来,这样,得到了窗口句柄就能取出来与之相关联的变量了.
4.监控鼠标进入离开窗口
因为已经Hook了窗口过程,所以只需要检查消息WM_MOUSEMOVE ,WM_NCMOUSEMOVE,就可以知道鼠标是否进入了窗口,而监控窗口离开主窗口
有两种方式
A)设定一个定时器,监控到鼠标进入窗口时候如果定时器没有运行就启动,定时器会隔一段时间(100ms?)去检测当前鼠标和窗口的位置,如果检测到鼠标离开了窗口,就停止定时器,动态隐藏窗口.
B)利用WM_MOUSELEAVE,WM_NCMOUSELEAVE消息来监测鼠标是否离开窗口
这里有一点小复杂,WM_NCMOUSELEAVE消息系统会自动发送到我们Hook的窗口过程,WM_MOUSELEAVE需要我们自己调用TrackMouseEvent函数来触发,并且接收到一个WM_MOUSELEAVE消息后必须重新调用此函数来方便再一次接收.我们必须在接收到鼠标离开消息的时候再次检测鼠标的位置,因为有可能收到了WM_NCMOUSELEAVE(这表示鼠标离开了窗口的NC部分),但是实际上窗口只是移动到了客户区,这时候我们不能简单的隐藏窗口.
还有一个问题,如果我们监控的窗口有子窗口,当鼠标从被监控窗口移动到它的子窗口上的时候,被监控窗口也会接收到WM_MOUSELVEAVE消息,这时候我们可以通过计算查询鼠标位置知道鼠标移动到了子窗口,但是我们不知道鼠标何时会离开子窗口,可以调用TrackMouseEvent函数来监控鼠标离开子窗口的消息,但是这个离开消息不会发送到我们Hook的窗口过程,因为这个窗口过程只是被监控窗口的窗口过程而不是它的子窗口的的,我只想到一种办法来解决,就是这种情况下,再Hook一下鼠标所在的子窗口的窗口过程,在鼠标移出子窗口后Unhook.
5.为了让窗口始终停靠在屏幕上方,只可以左右拖动不能上下拖动,我们可以在Hook的窗口过程中操纵消息WM_WINDOWPOSCHANGING 来实现.
6.WM_ENTERSIZEMOVE 和WM_EXITSIZEMOVE 消息区间,代表窗口正在被拖动,这时候不要试图判断鼠标是否在窗口而自作聪明的隐藏/显示窗口.我采取的方案为在用户停止拖动后强制判断一次鼠标和窗口的位置来决定是否隐藏窗口.
7.判断鼠标是在窗口的客户端还是NC区,不要用GetClientRect来比较鼠标位置,因为有可能别监控窗口是自画的,即在客户区里实现了标题栏等,这时候要用下面代码来判断
LMOUSE_POS LMouseInWindow(HWND hWnd)
{
POINT ptCursor = {0};
::GetCursorPos(&ptCursor);
RECT rtWnd = {0};
::GetWindowRect(hWnd, &rtWnd);
if(!::PtInRect(&rtWnd, ptCursor))
return MPOS_NONE;
UINT uHitTest = (UINT)::SendMessage(hWnd, WM_NCHITTEST, 0, MAKELPARAM(ptCursor.x, ptCursor.y));
if(uHitTest == HTCLIENT)
return MPOS_C;
if(uHitTest == HTNOWHERE)
return MPOS_C;
return MPOS_NC;
}
发送消息WM_NCHITTEST,如果窗口试图欺骗系统,那么也就欺骗我们好了...
8.关于显示,隐藏窗口的动画.在SSWinAutoHideWorkB中会启动一个线程,线程启动后来用WaitForMultiObjects来等待三个事件,一个为退出事件,一个为动态显示窗口事件,一个为动态隐藏窗口事件,这样如果我们想做这三个操作,只需要触发响应的事件就可以了.
9.某些时候窗口隐藏/显示,尤其是显示的时候闪烁的离开,特别是在窗口为自画窗口的时候,这时候可以考虑在自画窗口的WM_ERASEBACKGROUND消息中直接返回1来尝试解决.
SOURCE CODE : http://download.csdn.net/detail/patdz/4279573