MFC中MouseLeave消息没有响应

探索该消息的起因

在一个基于MFC的程序中,有个窗口是直接继承自CWnd,需要给这个窗口里添加相应的ToolTip,当鼠标进入窗口并且悬停在某些地方的时候需要显示ToolTip.

这个乍看起来实现很简单,重写MouseHover和MouseLeave就完事了,显示相应的ToolTip的逻辑就在这两个函数里面,于是自己在这个类里面的添加了相应函数以及相应的消息,并且写了实现逻辑。emm,按下F5之后,发现压根没有显示相应的ToolTip,调试之后发现MouseHover以及MouseLeave压根没有进去;心里一万个问好^^??

自以为正确的操作代码实现

  1. 在对应的头文件添加相应的函数

      afx_msg void OnMouseMove(UINT nFlags, CPoint point);
      afx_msg void OnMouseLeave();
      afx_msg void OnMouseHover(UINT nFlags, CPoint point);
  2. MESSAGE_MAP中添加相应的消息

     ON_WM_MOUSELEAVE()
     ON_WM_MOUSEMOVE()
     ON_WM_MOUSEHOVER()
  3. 实现对应的函数,在这里我就直接将函数里面的功能逻辑改为doSomething了;

      void CCMouseLeaveDlg::OnMouseMove(UINT nFlags, CPoint point)
      {
             dosomething();
      }
    
      void CCMouseLeaveDlg::OnMouseLeave()
      {
             dosomething();
      }
    
      void CCMouseLeaveDlg::OnMouseHover(UINT nFlags, CPoint point)
      {
             dosomething();
      }
  4. 运行程序调试,看看是否会进入相应的鼠标消息函数

    运行之后发现什么都没有做,调试也发现里面的消息函数压根没有进去!What's the hell!

面向谷歌寻求原因

Windows does not automatically send a WM_MOUSELEAVE message. When the mouse enters the control, you need to call **_TrackMouseEvent** to get it to notify you when this occurs
也就是说,为窗口添加WM_MOUSEHOVER或WM_MOUSELEAVE消息并不会响应,需要自己手动做一些特殊化处理,例如使用
TRACKMOUSEEVENT

TRACKMOUSEEVENT 做什么

对于这个函数,直接在MSDN上看相关文档,就可以得到函数的大概,TrackMouseEvent函数说明

我看到里面有一条语句The function can post the following messages. 瞬间明白了为何这个函数可以用来出发MouseLeave消息以及MouseHover消息。这个函数可以触发的消息如下表所示,我这只是个搬运工哈哈^^

Message Description
WM_NCMOUSEHOVER The same meaning as WM_MOUSEHOVER except this is for the nonclient area of the window
WM_NCMOUSELEAVE The same meaning as WM_MOUSELEAVE except this is for the nonclient area of the window
WM_MOUSEHOVER The mouse hovered over the client area of the window for the period of time specified in a prior call to TrackMouseEvent
WM_MOUSELEAVE The mouse left the client area of the window specified in a prior call to TrackMouseEvent. All tracking requested by TrackMouseEvent is canceled when this message is generated.

TRACKMOUSEEVENT的 结构定义

这个结构体的具体定义参见官方文档TRACKMOUSEEVENT结构体

我个人觉得主要是dwFlagsdwHoverTime的设置,具体的参数可选项参考官方文档;下面给出我自己在使用的时候的一部分结构体设置代码实现

     TRACKMOUSEEVENT tme;
     tme.cbSize = sizeof(TRACKMOUSEEVENT);
     tme.dwFlags = TME_LEAVE | TME_HOVER;  
     tme.hwndTrack = m_hWnd;  
     tme.dwHoverTime = 10;
     m_bMouseTracking = _TrackMouseEvent(&tme);
     

# 正确的处理方法

 自己在类中定义一个BOOL变量用来记录 鼠标状态,初始值为FALSE,我自己取得变量为m_bMouseTracking,这个变量的目的是为了防止鼠标已经在窗口上,移动鼠标就会不断产生WM_MOUSEHOVER消息;

而对于TRACKMOUSEEVENT的使用则是在MouseMove函数里进行,进行结构体的相关信息的设置,具体的实现如下,主要是加了TRACKMOUSEEVENT,用于发送WM_MOUSELEAVEWM_MOUSEHOVER消息,从而执行相关的操作;

    void CCMouseLeaveDlg::OnMouseMove(UINT nFlags, CPoint point)
    {
            if(!m_bMouseTracking)
            {
                    TRACKMOUSEEVENT tme;
                    tme.cbSize = sizeof(TRACKMOUSEEVENT);
                    tme.dwFlags = TME_LEAVE | TME_HOVER;  
                    me.hwndTrack = m_hWnd;
                    tme.dwHoverTime = 10;
                    
                    m_bMouseTracking = _TrackMouseEvent(&tme);
            }
            
            maybeDoSomething();
    
    }
    
     void CCMouseLeaveDlg::OnMouseLeave()
     {
             m_bMouseTracking = FALSE;
             maybeDoSomethingElse();
     }
     
     void CCMouseLeaveDlg::OnMouseHover(UINT nFlags, CPoint point)
     {
            GetPositionOfToolTipControl();
            ShowToolTip();
     }
    

总结

自己一开始以为自己很快就能搞定,效果没出来的时候还以为是自己的写的代码有问题,导致自己调试代码调了好久,后来发现没有触发相应的消息之后,就直接面向谷歌了。这玩意一搜一堆,当时以为自己很快就有了解决办法,卧槽,当时自己也不明白这些参数和结构体是用来的干嘛的,直接全抄了,调试后发现依旧没用,直接导致怀疑人生。最后发现是dwFlags的参数选择了一个非客户区,导致不会再客户区发送相应的消息,直接GG。

最后面还是自己参考官方文档,了解每个参数的设置以及含义,才恍然大悟。最后,在遇到问题的时候不要慌,首先想想有什么解决方法没,没有的话在面向谷歌或者面向百度,这一步需要自己细心,不要生搬硬套,否则就会出现我上面那种傻子行为^^

              
              
              

猜你喜欢

转载自www.cnblogs.com/zuixime0515/p/12198201.html
今日推荐