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

CRectTracker 橡皮筋選框:解決 WM_LBUTTONUP 被攔截無法響應的技巧

     編輯:關於VC++

問題現象

在 OnLButtonDown 中呼叫 TrackRubberBand() 繪製選框,但滑鼠釋放時 OnLButtonUp 完全不觸發。原因:TrackRubberBand 內部訊息迴圈以 WM_LBUTTONUP 作為結束條件,直接吞噬該訊息。

解決方案:手動發送 WM_LBUTTONUP

void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point) {
    CRectTracker tracker;
    tracker.TrackRubberBand(this, point, TRUE);
    tracker.m_rect.NormalizeRect();

    // 關鍵:TrackRubberBand 返回後,手動發送 WM_LBUTTONUP 給自己
    SendMessage(WM_LBUTTONUP, 0, 0);

    CDialog::OnLButtonDown(nFlags, point);
}

完整互動邏輯範例

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

void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point) {
    Invalidate(TRUE);
    if (m_tracker.HitTest(point) < 0) { // 點擊空白處:建立新選框
        m_bTracking = TRUE;
        CRectTracker tmp;
        tmp.TrackRubberBand(this, point, TRUE);
        tmp.m_rect.NormalizeRect();
        m_ptStart = point;
        GetCursorPos(&m_ptEnd);
        SendMessage(WM_LBUTTONUP, 0, 0); // 觸發 Up 邏輯
    } else { // 點擊現有選框:調整大小/位置
        m_tracker.Track(this, point, TRUE);
        m_tracker.m_rect.NormalizeRect();
        OnPaint();
    }
    CDialog::OnLButtonDown(nFlags, point);
}

void CMyDlg::OnLButtonUp(UINT nFlags, CPoint point) {
    if (m_bTracking) {
        ScreenToClient(&m_ptEnd);
        m_tracker.m_rect.SetRect(m_ptStart.x, m_ptStart.y,
                                 m_ptEnd.x, m_ptEnd.y);
        m_tracker.m_rect.NormalizeRect();
        OnPaint();
        m_bTracking = FALSE;
    }
    CDialog::OnLButtonUp(nFlags, point);
}

原理說明

TrackRubberBand 內部 GetMessage 迴圈捕獲 WM_LBUTTONUP 後直接 break,不派發給視窗程序。補發一個同樣參數的 WM_LBUTTONUP 讓訊息機制正常流轉,OnLButtonUp 即可正常執行。

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