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

MFC CRectTracker 類別深度解析:橡皮筋選取、邊框追蹤與縮放實作全攻略

     編輯:關於VC++

認識 CRectTracker:「橡皮筋」類別的多面向應用

CRectTracker 是 MFC 提供的強大類別,俗稱「橡皮筋類別」。它能實現:矩形邊框顯示、八個控制點縮放、框選區域 (Rubber Band) 等功能,廣泛用於繪圖編輯器、圖片裁剪工具等場合。本文透過建立一個單文檔專案 Rect,循序漸進示範其核心功能。

專案建立與基礎架構

  1. 建立單文檔 MFC 專案,命名 Rect
  2. 在 CRectDoc 加入公有成員:CRectTracker m_rectTracker;
  3. 建構函數初始化:
CRectDoc::CRectDoc() {
    m_rectTracker.m_rect.SetRect(0, 0, 100, 100); // 初始矩形 (View 座標)
    m_rectTracker.m_nStyle = CRectTracker::resizeInside | CRectTracker::dottedLine;
}

樣式說明:

  • resizeInside/Outside:控制點在矩形內/外
  • dottedLine/solidLine:虛線/實線邊框 (互斥)
  • hatchedBorder:斜紋邊框
  • hatchInside:內部斜紋填充

視圖繪製與互動實作

1. 基本繪製 (OnDraw)

void CRectView::OnDraw(CDC* pDC) {
    CRectDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    CBrush brush(RGB(0, 0, 255)); // 藍色筆刷
    CBrush* oldBrush = pDC->SelectObject(&brush);

    CRect rect;
    pDoc->m_rectTracker.GetTrueRect(&rect); // 取得追蹤矩形
    pDC->Ellipse(rect);                     // 畫橢圓

    pDoc->m_rectTracker.Draw(pDC);          // 畫追蹤邊框與控制點

    pDC->SelectObject(oldBrush);
}

2. 滑鼠游標自動變換 (OnSetCursor)

BOOL CRectView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) {
    CRectDoc* pDoc = GetDocument();
    if (pWnd == this && pDoc->m_rectTracker.SetCursor(this, nHitTest))
        return TRUE;
    return CView::OnSetCursor(pWnd, nHitTest, message);
}

3. 橡皮筋框選功能 (OnLButtonDown - 第一版)

void CRectView::OnLButtonDown(UINT nFlags, CPoint point) {
    CRectTracker temp;
    temp.TrackRubberBand(this, point, TRUE); // TRUE 允許反向拖曳
    temp.m_rect.NormalizeRect();             // 正規化座標 (左<右, 上<下)
    CView::OnLButtonDown(nFlags, point);
}

關鍵點:TrackRubberBand 以右鍵釋放結束,期間不觸發 MouseMove,結果存於 temp.m_rect。

4. 進階:點擊判斷與縮放追蹤 (OnLButtonDown - 完整版)

新增 CRectView::bDraw 控制是否繪製橢圓。

void CRectView::OnLButtonDown(UINT nFlags, CPoint point) {
    int nIn = GetDocument()->m_rectTracker.HitTest(point);

    if (nIn < 0) { // 點擊在追蹤矩形外部 → 框選模式
        CRectTracker temp;
        temp.TrackRubberBand(this, point, TRUE);
        temp.m_rect.NormalizeRect();

        CRectTracker interRect;
        if (interRect.m_rect.IntersectRect(temp.m_rect, GetDocument()->m_rectTracker.m_rect))
            bDraw = TRUE; // 有交集 → 選中物件
        else
            bDraw = FALSE;
        Invalidate();
    }
    else { // 點擊在追蹤矩形內部 → 縮放/移動模式
        CClientDC dc(this);
        GetDocument()->m_rectTracker.Draw(&dc);
        GetDocument()->m_rectTracker.Track(this, point, TRUE); // 核心:即時追蹤縮放
        bDraw = TRUE;
        Invalidate();
    }
    CView::OnLButtonDown(nFlags, point);
}

HitTest 回傳值對照表

回傳值意義
-1矩形外部
0,1,2,3左上、右上、右下、左下角 (順時針)
4,5,6,7上、右、下、左邊緣 (順時針)
8內部 (非控制點)

核心函式解析

  • TrackRubberBand:框選模式,回傳選取區域
  • Track:縮放/移動模式,內部處理滑鼠移動與重繪,無需自行處理 MouseMove
  • HitTest:判斷滑鼠位置,決定互動模式
  • GetTrueRect:取得邏輯座標下的實際矩形
  • NormalizeRect:確保 left<right, top<bottom

擴充建議

  1. 加入旋轉功能:結合 CPoint 三角函數計算
  2. 多物件選取:維護 CArray<CRectTracker*>
  3. 撤銷/重做:記錄 m_rect 狀態歷史
  4. 磁吸對齊:在 Track 過程中修正座標
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved