OnMouseHover()和OnMouseLeave()消息

当鼠标停留在程序窗口一定时间后,会产生一个WM_MOUSEHOVER消息;当鼠标离开程序窗口后,会产生一个WM_MOUSELEAVE消息。那如何才能使窗口响应这两个消息呢?按下面的步骤,即可让指定的窗口能捕获并响应WM_MOUSEHOVER和WM_MOUSELEAVE消息了。

一:方法1:
1、在窗口类的头文件中添加:

afx_msg   void   OnMouseHover();  
afx_msg   void   OnMouseLeave();  
BOOL   m_bTrackLeave;   // 捕获设置标记
 ```

2、在窗口类的cpp文件中添加:

void   CXXXWnd::OnMouseHover()  
{  
          MessageBox( "鼠标已进入 ");  
          m_bTrackLeave = FALSE;  
}  

void   CXXXWnd::OnMouseLeave()  
{  
          MessageBox( "鼠标已离开 ");  
          m_bTrackLeave = FALSE;  
}  

3、用ON_MESSAGE添加消息映射:

ON_MESSAGE( WM_MOUSEHOVER, OnMouseHover )  
ON_MESSAGE( WM_MOUSELEAVE, OnMouseLeave )  

4、在OnMouseMove响应函数中,调用_TrackMouseEven(),设置捕获WM_MOUSEHOVER和WM_MOUSELEAVE消息

void  CXXXWnd::OnMouseMove(UINT   nFlags,   CPoint   point)    
{  
    if (!m_bTracking)  
    {  
//   鼠标移入窗时,请求WM\_MOUSEHOVER和WM\_MOUSELEAVE 消息  
        TRACKMOUSEEVENT tme;  
        tme.cbSize = sizeof(tme);  
        tme.hwndTrack = m_hWnd;  
        tme.dwFlags = TME_LEAVE|TME_HOVER;  
        tme.dwHoverTime = 1;  
        m_bTracking = _TrackMouseEvent(&tme);  
    }  

      CWnd::OnMouseMove(nFlags,   point);  
}  

5、相关说明
(1)调用一次_TrackMouseEvent只能请求一次WM_MOUSEHOVER和WM_MOUSELEAVE消息,所以要放到OnMouseMove中多次请求
(2)让一个相对独立的窗口捕获WM_MOUSEHOVER和WM_WM_MOUSELEAVE消息,直接上述方法就可以了,如果让子窗口CButton、CStatic等来捕获,则需要在基类的基础上派生出一个子类,在子类中按上述方法来实现就行了

二:方法二:
使用MFC自带函数SetCapture(),GetCapture()和ReleaseCapture()来使窗口捕获WM_MOUSEHOVER和WM_MOUSELEAVE消息
在OnMouseMover消息相应函数中添加如下代码

void CXXXWnd::OnMouseMove(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default
    //设置鼠标捕获,即使光标离开按钮区域,仍然能接收鼠标消息
    CRect rect;
    GetClientRect(rect);
    if(rect.PtInRect(point))//鼠标在自定义按钮窗口的范围内
    {
        //GetCapture()返回捕获了鼠标的窗口指针,
        //因为自绘按钮设置了SetCapture(),
        //所以会调用了SetCapture()函数的自绘按钮的指针,
        //所以这句的作用是避免多次调用SetCapture()
        if(GetCapture()!=this)
            SetCapture();

        //如果==this,说明此事鼠标在自定义按钮上
        m_bTrack=TRUE;
    }
    else//如果鼠标不在自定义按钮窗口范围内
    {
        if(!m_bPress)//如果鼠标没按下,则解除捕获鼠标(拖着鼠标离开窗口)
            ReleaseCapture();
        m_bTrack=FALSE;
    }
    Invalidate(FALSE);
    CWnd::OnMouseMove(nFlags, point);
}

然后就可在其他函数中根据变量m_bTrack的值来判断鼠标是否在某个窗口内(包括自定义窗口)来实现相关代码

注意:当 CWnd 不再需要任何鼠标输入时,应用程序应调用 ReleaseCapture 功能,以便其他窗口可以接收鼠标输入。
当鼠标输入捕获时,WM_NCHITTEST 或 WM_SETCURSOR 信息不会发送到活动窗口。

参考

http://blog.csdn.net/s_52588/article/details/8230053

猜你喜欢

转载自blog.csdn.net/chenyonken/article/details/77922642