zoukankan      html  css  js  c++  java
  • 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。

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

  • 相关阅读:
    测试文件报告
    Bug Variations
    阶段一 问答题2
    阶段一 问答题1
    HeapSort
    Git系列 (01):git clone 速度太慢解决方法
    ES6系列 (03):链判断运算符和Null 判断运算符
    ES6系列 (02):解构赋值
    ES6系列 (01):箭头函数this指向问题
    我忘却了所有,抛却了信仰,舍弃了轮回,只为,那曾在佛前哭泣的玫瑰,早已失去旧日的光泽。
  • 原文地址:https://www.cnblogs.com/zuixime0515/p/12198201.html
Copyright © 2011-2022 走看看