文章移至這裏
最近項目中用到需要動態監測鼠標是否移入或者移出窗體,用來控制窗體的顯示和隱藏,常規思路:使用系統的消息WM_MOUSELEAVE(鼠標離開)和WM_MOUSEHOVER(鼠標進入)來檢測,具體做法就是在鼠標移動消息中增加如下代碼:
<span style="font-size:18px;"> //打開鼠標進入與離開的消息監聽
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE | TME_HOVER;
tme.dwHoverTime = 1;
m_bTracking = _TrackMouseEvent(&tme); </span>
具體代碼請參考這裏:http://blog.csdn.net/rankun1/article/details/51659679但是,這樣做有一個問題,就是當窗體上面有子窗體的時候,鼠標移動到子窗體上,監聽消息就會認爲鼠標已經離開主窗體(這是正確的),但並不是我想要的效果,我想要的是隻要鼠標在窗體上,不管是子窗體還是父窗體,只要在父窗體區域內,都認爲鼠標還在窗體上,沒有離開,於是就在WM_MOUSELEAVE和WM_MOUSEHOVER消息中增加判斷鼠標位置代碼,以此判斷鼠標是否離開窗體:
<span style="font-size:18px;">CPoint point;
CRect rectWindow;
BOOL bIn = FALSE;
GetWindowRect(rectWindow);
GetCursorPos(&point);
if (rectWindow.PtInRect(point))
{
bIn = TRUE;
}</span>
這樣貌似可以了,但是,當我快速把鼠標從窗體子控件上移出窗體的時候,有時候會捕獲不到鼠標離開的消息,猜測原因可能是鼠標移動消息沒有觸發或者鼠標消息觸發是週期性的,帶着這樣的疑問繼續查找鼠標移動消息的資料,查資料發現:WINDOWS系統並不是在鼠標每移動一個像素時都產生WM_MOUSEMOVE消息,但奇怪的是,我鼠標移動的距離已經超出了N個像素了,爲什麼還沒有觸發那,或者觸發了沒有檢測到鼠標離開消息,還是鼠標移動消息也是週期性的,有自己的時鐘週期,不得而知,總之,上面的方案沒有能解決我想要的效果。
在查檢測鼠標移入移出窗體的時候,也有人提到用鼠標鉤子的,處於安全考慮,沒敢用,進程你的鉤子鉤不到鼠標移出的消息,全局的鉤子還容易被殺毒軟件攔截,認爲是病毒誤報。
後來實在沒辦法,就選擇了一個笨方法:定時器,定時執行檢查鼠標是否在窗體上,代碼如下:
<span style="font-size:18px;">static int nLastStatue = -1;
CPoint point;
CRect rectWindow;
BOOL bIn = FALSE;
GetWindowRect(rectWindow);
GetCursorPos(&point);
if (rectWindow.PtInRect(point))
{
bIn = TRUE;
}
if (bIn && nLastStatue != 1)
{
nLastStatue = 1;
//顯示窗體
}else if (!bIn && nLastStatue != 0)
{
nLastStatue = 0;
//隱藏窗體
}
</span>
當窗體失去焦點的適合也要處理一下隱藏窗體代碼,這樣基本就能實現自己想要的效果了
也不知道自己分析的對不對,如果有問題,請留言指正,謝謝!!!