WM_MOUSEENTER / WM_MOUSELEAVE (實為 WM_MOUSEHOVER/WM_MOUSELEAVE) 雖有定義且看似實用,但預設不會自動發送,需在 WM_MOUSEMOVE 中手動啟動追蹤。
BOOL m_bTracking = FALSE; // 追蹤狀態旗標
ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnMouseHover(WPARAM wParam, LPARAM lParam);
void CDemo::OnMouseMove(UINT nFlags, CPoint point) {
if (!m_bTracking) {
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE | TME_HOVER; // 同時啟用離開與停留
tme.dwHoverTime = 1; // 停留判定時間(毫秒),1 為預設系統值
m_bTracking = _TrackMouseEvent(&tme); // 成功返回 TRUE
}
// 其他滑鼠移動邏輯...
}
LRESULT CDemo::OnMouseLeave(WPARAM wParam, LPARAM lParam) {
m_bTracking = FALSE; // 重置旗標,下次進入再啟動
// 滑鼠離開視窗客戶區處理邏輯
return 0;
}
LRESULT CDemo::OnMouseHover(WPARAM wParam, LPARAM lParam) {
// 滑鼠在視窗停留超過 dwHoverTime 處理邏輯
return 0;
}
_TrackMouseEvent 設定的追蹤為一次性,WM_MOUSELEAVE 或 WM_MOUSEHOVER 觸發後自動取消,需在處理函數中重置旗標,下次 WM_MOUSEMOVE 重新啟動TME_LEAVE:滑鼠離開視窗客戶區觸發 WM_MOUSELEAVETME_HOVER:滑鼠在視窗靜止超過 dwHoverTime 觸發 WM_MOUSEHOVERTME_NONCLIENT:擴展至非客戶區(標題列、邊框等)WM_MOUSELEAVE,依賴系統自動重置dwHoverTime = HOVER_DEFAULT (0xFFFFFFFF) 使用系統預設值(通常 400ms)CWnd::TrackMouseLeave 封裝了此邏輯,可簡化實作