MFC 鼠標去留


題目不醒目,特解

  win32編程中,有兩個消息比較特別,WM_MOUSEHOVER和WM_MOUSELEAVE。系統不會想應用程序發送這兩個消息,MSDN中規定要用到TrackMouseEvent方法來向程序投遞這兩個消息。

去留分析

  去WM_MOUSELEAVE,留WM_MOUSEHOVER。打個比方,調用TrackMouseEvent就向在消息隊列中設置了一個哨兵,當發現WM_MOUSEHOVER或者WM_MOUSELEAVE的時候,就將其放入消息隊列,而此時如果這個消息是WM_MOUSELEAVE這個哨兵會消失,而如果這個消息是WM_MOUSEHOVER,這個哨兵會暫留,但是他只能檢測WM_MOUSELEAVE。

  (參看MSDN中的原話,對於WM_MOUSEHOVER,“Hover tracking stops when this message is generated. The application must call TrackMouseEvent again if it requires further tracking of mouse hover behavior.”;而對於WM_MOUSELEAVE,“All tracking requested by TrackMouseEvent is canceled when this message is generated.”)。因此可以利用這個規定特點,來設計判斷“鼠標去留”的方法。

  按照以往的習慣,應該在WM_MOUSEMOVE的處理函數當中放置哨兵TrackMouseEvent,在類中添加BOOL變量m_bTrack標志,用來判斷是否要進行放置哨兵。

  為了方便理解,畫成如下圖:

如此這般,可以用懸停標志來決定處理過程。在鼠標懸停和鼠標離去處理函數中,做想做的事情。

具體實現

  1. 添加WM_MOUSEMOVE,WM_MOUSEHOVER,WM_MOUSELEAVE消息的處理函數。VS2008可以在類的屬性當中自動添加,但是VC6中,WM_MOUSEHOVER,WM_MOUSELEAVE需要手動添加。
  2. 在WM_MOUSEMOVE處理函數中,放置哨兵。
    if(m_bTrack)
    {
        TRACKMOUSEEVENT tme;
        tme.cbSize =  sizeof(TRACKMOUSEEVENT);
        tme.dwFlags = TME_HOVER | TME_LEAVE;
        tme.hwndTrack =  this->GetSafeHwnd();
        tme.dwHoverTime = HOVER_DEFAULT;   // 懸停多少時間之后產生WM_MOUSEHOVER
        ::_TrackMouseEvent(&tme);
        m_bTrack =  false;
    }
  3. 在WM_MOUSELEAVE處理函數中,因為TRACKMOUSEEVENT完全作廢,所以需要允許追蹤鼠標;並且更新Hover標志變量。
    m_bHover =  false;
    m_bTrack =  true;
  4. 在WM_MOUSEHOVER處理函數中,更新Hover標志變量。
    m_bHover =  true;
     

面是詳細的代碼,是核心代碼,沒有實現什么功能,可以自行添加。

void CDLEdit::OnMouseHover(UINT nFlags, CPoint point)
{
     //  TODO: 在此添加消息處理程序代碼和/或調用默認值
    m_bHover =  true;
    CEdit::OnMouseHover(nFlags, point);
}

void CDLEdit::OnMouseLeave()
{
     //  TODO: 在此添加消息處理程序代碼和/或調用默認值
    m_bHover =  false;
    m_bTrack =  true;
    CEdit::OnMouseLeave();
}

void CDLEdit::OnMouseMove(UINT nFlags, CPoint point)
{
     //  TODO: 在此添加消息處理程序代碼和/或調用默認值
     if(m_bTrack)
    {
        TRACKMOUSEEVENT tme;
        tme.cbSize =  sizeof(TRACKMOUSEEVENT);
        tme.dwFlags = TME_HOVER | TME_LEAVE;
        tme.hwndTrack =  this->GetSafeHwnd();
        tme.dwHoverTime = HOVER_DEFAULT;         // 懸停多少時間之后產生WM_MOUSEHOVER
        ::_TrackMouseEvent(&tme);
        m_bTrack =  false;
    }
    CEdit::OnMouseMove(nFlags, point);
}

 

收獲與感受

鼠標去留技術不難,但是用處很廣,屬於技術細節,就拿QQ產品來說,很多地方都有體現。

 

搗亂小子 2012年2月4日星期六

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM