设置TrackMouseEvent捕获WM_MOUSEHOVER和WM_MOUSELEAVE消息

时间:2023-03-09 13:05:09
设置TrackMouseEvent捕获WM_MOUSEHOVER和WM_MOUSELEAVE消息

  WM_MOUSEHOVER(非客户区消息为WM_NCMOUSEHOVER)消息表示鼠标在客户区悬浮消息,WM_MOUSELEAVE(非客户区消息为WM_NCMOUSELEAVE)为鼠标离开客户区消息,这四个消息都需要提前调用TrackMouseEvent函数设置捕获。

  Windows API函数定义为:

BOOL WINAPI TrackMouseEvent(
_Inout_ LPTRACKMOUSEEVENT lpEventTrack
);

  在设置TrackMouseEvent函数前需要定义TRACKMOUSEEVENT结构体,参数含义为:

cbSize: sizeof(TRACKMOUSEEVENT)

dwFlags: TME_CANCEL(取消捕获,需配合TME_HOVER或TME_LEAVE或TME_NONCLIENT使用)、TME_HOVER(捕获WM_MOUSEHOVER)、TME_LEAVE(捕获WM_MOUSELEAVE)、TME_NONCLIENT(捕获WM_NCMOUSEHOVER和WM_NCMOUSELEAVE)、TME_QUERY

hwndTrack: 窗口句柄

dwHoverTime: 如果是WM_MOUSEHOVER消息,设置触发该消息的时间,或者使用系统默认HOVER_DEFAULT,单位ms

typedef struct tagTRACKMOUSEEVENT {
DWORD cbSize;
DWORD dwFlags;
HWND hwndTrack;
DWORD dwHoverTime;
} TRACKMOUSEEVENT, *LPTRACKMOUSEEVENT;

     TrackMouseEvent函数在设置后,如果成功捕获消息后,设置会立马失效,如果下次还需要捕获消息,需重新调用TrackMouseEvent设置。

  下例为通过一个布尔变量bTrackFlag 避免频繁的调用TrackMouseEvent设置,在捕获消息后重置bTrackFlag 变量,以便下次能重新捕获消息。

 //窗口消息处理过程
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam,LPARAM lParam)
{
//...
  switch (message)
  {
    case WM_MOUSEMOVE:
    {
if(!bTrackFlag ){
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE|TME_HOVER;
tme.hwndTrack = m_hwnd; //窗口句柄
tme.dwHoverTime = ;
::TrackMouseEvent(&tme);
bTrackFlag = TRUE;
}
    }
    break;
case WM_MOUSELEAVE:
{
bTrackFlag = FALSE;
//...
}
break;
case WM_MOUSEHOVER:
{
bTrackFlag = FALSE;
//...
}
//...    
  }
}

参考资料:

a): TrackMouseEvent function: https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms646265(v=vs.85).aspx

b): TRACKMOUSEEVENT structure: https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms645604(v=vs.85).aspx