首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

CRectTracker 橡皮筋選框應用難點:WM_LBUTTONUP 被截獲的解決方案

     編輯:VC 教學

問題現場

在對話框 OnLButtonDown 呼叫 temp.TrackRubberBand(this, point, TRUE) 繪製橡皮筋框。但 OnLButtonUp 完全不觸發——TrackRubberBand 內部以滑鼠左鍵放開為結束條件,提前截獲了 WM_LBUTTONUP 訊息。

解決思路:手動重發 WM_LBUTTONUP

TrackRubberBand 返回後,主動 SendMessage(WM_LBUTTONUP, 0, 0) 讓自身訊息迴路再處理一次放開事件。

完整實作代碼

void CMyDialog::OnLButtonDown(UINT nFlags, CPoint point) {
    Invalidate(TRUE);
    if(m_tracker.HitTest(point) < 0) { // 新建選框
        m_bLBtnDown = TRUE;
        CRectTracker temp;
        temp.TrackRubberBand(this, point, TRUE);
        temp.m_rect.NormalizeRect();

        m_ptStart = point;
        GetCursorPos(&m_ptEnd); // 螢幕座標
        SendMessage(WM_LBUTTONUP, 0, 0); // 關鍵:重發放開訊息
    } else { // 調整既有框
        m_tracker.Track(this, point, TRUE);
        m_tracker.m_rect.NormalizeRect();
        OnPaint();
    }
    CDialog::OnLButtonDown(nFlags, point);
}

void CMyDialog::OnLButtonUp(UINT nFlags, CPoint point) {
    if(m_bLBtnDown) { // 僅新建模式處理
        // 螢幕座標轉客戶區
        CRect rect; rect.right = m_ptEnd.x; rect.bottom = m_ptEnd.y;
        ScreenToClient(&rect);
        m_ptEnd = rect.BottomRight();

        m_tracker.m_rect.SetRect(m_ptStart.x, m_ptStart.y, m_ptEnd.x, m_ptEnd.y);
        m_tracker.m_rect.NormalizeRect();
        OnPaint();
        m_bLBtnDown = FALSE;
    }
    CDialog::OnLButtonUp(nFlags, point);
}

void CMyDialog::OnLButtonDblClk(UINT nFlags, CPoint point) {
    AfxMessageBox(_T("雙擊測試")); // 驗證雙擊不受影響
    CDialog::OnLButtonDblClk(nFlags, point);
}

輔助:游標形狀隨 HitTest 變化

BOOL CMyDialog::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT msg) {
    if(pWnd == this && m_tracker.SetCursor(this, nHitTest)) return TRUE;
    return CDialog::OnSetCursor(pWnd, nHitTest, msg);
}

原理總結

  • TrackRubberBand 內部跑自己的訊息迴圈,直接處理 WM_MOUSEMOVE/WM_LBUTTONUP
  • 返回後原本的 WM_LBUTTONUP 已被消費,需手動補發
  • 旗標 m_bLBtnDown 區分「新建」與「調整/雙擊」模式,避免誤觸發

結語

此技巧同樣適用於 Track、DragRect 等 MFC 內建追蹤函式,掌握「訊息被內部迴圈截獲 → 手動重發」模式即可舉一反三。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved