MFC WM_MOUSELEAVE和WM_MOUSEHOVER
前言
学习书本,博客记录,便于往后回顾。
因为窗口接收WM_MOUSEMOVE消息,所以很容易知道光标何时进入了窗口或在窗口中移动了。使用**::TrackMouseEvent**,可以很容易确定光标何时离开窗口或在窗口上停止不动。
一个应用程序可以注册**::TrackMouseEvent**,当光标离开窗口时接收WM_MOUSELEAVE消息,而光标在窗口上方停滞时接收WM_MOUSEHOVER消息。
::TrackMouseEvent介绍
::TrackMouseEvent是一个结构体,只接收一个指向TRACKMOUSEEVENT结构体的指针参数,其在Winuser.h中如下:
typedef struct tagTRACEMOUSEEVENT{
DWORD cbSize;
DWORD dwFlags;
HWND hwndTrack;
DWORD dwHoverTime;
}TRACEMOUSEEVENT
cbSize:保存结构的大小;
dwFlags:{ 保存位标志用来指定调用者想要执行的操作:
注册接收WM_MOUSELEAVE消息(TME_LEAVE);
注册接收WM_MOUSEHOVER消息(TME_HOVER);
取消WM_MOUSELEAVE和WM_MOUSEHOVER消息(WM_CANCEL)
或允许系统用当前::TrackMouseEvent设置填写TRACEMOUSEEVENT结构(TME_QUERY)}
hwndTrack: 窗口的句柄,对此窗口将生成WM_MOUSELEAVE和WM_MOUSEHOUVER消息。
dwHoverTime:以毫秒计时的时间长度,光标必须暂停这么久,WM_MOUSEHOVER消息才向它下面的窗口发送。可以设置dwHouverTime等于HOVER_DEFAULT,系统默认值400ms。
光标并非必须纹丝不动系统才会产生WM_MOUSEHOVER消息。如果光标所在矩形的宽度和高度与用SPI_GETMOUSEHOVERWIDTH和SPI_GETMOUSEHOVERHEIGTH参数调用::SystemParametersInfo 返回的值相同,并且它停留的时间与用SPI_GETMOUSEHOVERTIME调用SystemParametersInfo返回的值也相同时,就会产生WM_MOUSEHOVER消息。
可以使用SPI_SETMOUSEHOVERWIDTH、SPI_SETMOUSEHOVERHEIGTH、SPI_SETMOUSEHOVERTIME值调用::SystemParametersInfo来修改这些参数。
示例
下列代码段在鼠标进入、离开或停留在窗口上时将“Mouse enter”、“Mouse leave”、“Mouse hover”写道调试输出窗口。m_bMouseOver是CMainWindow的一个BOOL成员变量。
//.cpp
#define _WIN32_WINNT 0x400
//#include ...
#include <Afxwin.h>
//#include ...
//In message map
ON_WM_MOUSEMOVE()
ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
ON_MESSAGE(WM_MOUSEHOVER, OnMoudeHover)
void CMainWindow::OnMouseMove(UINT nFlags, CPoint point)
{
if(!m_bMouseOver)
{
TRACE(_T("Mouse enter\n"));
m_bMouseOver = TRUE;
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_HOVER|TME_LEAVE;
tme.hwndTrack = m_hWnd;
tme.dwHoverTime = HOVER_DEFAULT;
::TrackMouseEvent(&tme);
}
}
LRESULT CMainWindow::OnMouseLeave(WParam wParam, LPARAM lParam)
{
TRACE(_T("Mouse leave\n"));
m_bMouseOver = FALSE;
return 0;
}
LRESULT CMainWindow::OnMouseHover(WParam wParam, LPARAM lParam)
{
TRACE(_T("Mouse hover(x= %d, y= %d)\n"), LOWORD(lParam), HIWORD(lParam));
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_HOVER|TME_LEAVE;
tme.hwndTrack = m_hWnd;
tme.dwHoverTime = HOVER_DEFAULT;
::TrackMouseEvent(&tme);
}
在使用::TrackMouseEvent时需要注意,在产生WM_MOUSELEAVE或WM_MOUSEHOVER消息时,它的影响就消失了。因此想要在光标离开或停留在窗口上时任何时候接收这些消息,就必须在接收到WM_MOUSELEAVE或WM_MOUSEHOVER消息时重新调用::TrackMouseEvent。
另外:伴随WM_MOUSEHOVER消息的lParam参数值在它的高位字中保存了光标的y坐标,在低位字中保存了光标的x坐标。wParam未被使用。在WM_MOUSELEAVE消息中lParam和wParam都未被使用。
最后关于::TrackMouseEvent的使用,必须在源代码中确保在#include <Afxwin.h>之前包括下列#define语句:
#define _WIN32_WINNT 0x400