首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> C# 入門

C# 繪圖進階:ControlPaint.DrawReversibleFrame 實作橡皮筋選取框效果

     編輯:C# 入門

前言:可逆繪圖與選取框視覺回饋

在圖形編輯器中,滑鼠拖曳選取區域時的「橡皮筋框」效果,需在滑鼠移動時即時繪製、刪除前一幀框線。ControlPaint.DrawReversibleFrame 使用 XOR 光柵運算,重複呼叫同一座標即可切換顯示/隱藏,無需重繪背景,是實作選取框的高效方案。本文解析其在矩形繪製類別中的應用。

核心類別架構


public class Rectangle : Shape
{
    protected Point m_Start;
    protected Point m_End;
    protected Color m_Color;

    public Rectangle(Point start, Point end, Color fgColor)
    {
        m_Start = start;
        m_End = end;
        m_Color = fgColor;
    }

    public override void Draw(Form canvas)
    {
        if (canvas == null) return;
        
        InitializeGraphics(canvas); // 繼承自 Shape 基底類別
        
        // 將用戶端座標轉換為螢幕座標
        Point startPoint = canvas.PointToScreen(m_Start);
        Point endPoint = canvas.PointToScreen(m_End);
        
        MainForm mainForm = (MainForm)canvas;
        Color bgColor = GetBackgroundColor(m_Color); // 取得反相顏色
        
        // 計算矩形尺寸
        Size rectSize = new Size(m_End.X - m_Start.X, m_End.Y - m_Start.Y);
        System.Drawing.Rectangle rectToDraw = new System.Drawing.Rectangle(startPoint, rectSize);
        
        // 關鍵:可逆框線繪製
        ControlPaint.DrawReversibleFrame(rectToDraw, bgColor, FrameStyle.Thick);
    }
}

關鍵方法解析

ControlPaint.DrawReversibleFrame


public static void DrawReversibleFrame(
    Rectangle rectangle,  // 螢幕座標矩形
    Color backColor,      // 背景色(用於 XOR 運算)
    FrameStyle style      // 框線樣式
);
  • XOR 運算特性:對同一區域呼叫兩次即還原原狀,適合拖曳過程中反覆繪製/清除
  • 座標系統:參數必須為螢幕座標,故需 PointToScreen 轉換
  • FrameStyle:Thick(粗框)、Dashed(虛線)

反相顏色計算


private Color GetBackgroundColor(Color foreground)
{
    // 簡單反相:255 - R/G/B
    return Color.FromArgb(255 - foreground.R, 255 - foreground.G, 255 - foreground.B);
}

確保框線在任何背景下可見。

完整選取框互動流程


public class SelectionTool
{
    private Point _startPoint;
    private Rectangle _currentRect;
    private bool _isDragging;
    private Form _canvas;

    public void OnMouseDown(Point clientPoint)
    {
        _startPoint = clientPoint;
        _isDragging = true;
    }

    public void OnMouseMove(Point clientPoint)
    {
        if (!_isDragging) return;
        
        // 刪除舊框(再次呼叫 XOR 刪除)
        if (_currentRect != Rectangle.Empty)
            DrawReversibleFrame(_currentRect);
        
        // 計算新框
        _currentRect = GetScreenRect(_startPoint, clientPoint);
        
        // 繪製新框
        DrawReversibleFrame(_currentRect);
    }

    public void OnMouseUp(Point clientPoint)
    {
        if (!_isDragging) return;
        
        // 刪除最後一幀框
        if (_currentRect != Rectangle.Empty)
            DrawReversibleFrame(_currentRect);
        
        _isDragging = false;
        _currentRect = Rectangle.Empty;
        
        // 此處處理最終選取邏輯
        ProcessSelection(GetClientRect(_startPoint, clientPoint));
    }

    private void DrawReversibleFrame(Rectangle screenRect)
    {
        Color bgColor = GetBackgroundColor(Color.Red);
        ControlPaint.DrawReversibleFrame(screenRect, bgColor, FrameStyle.Thick);
    }

    private Rectangle GetScreenRect(Point start, Point end)
    {
        Point screenStart = _canvas.PointToScreen(start);
        Point screenEnd = _canvas.PointToScreen(end);
        return new Rectangle(
            Math.Min(screenStart.X, screenEnd.X),
            Math.Min(screenStart.Y, screenEnd.Y),
            Math.Abs(screenStart.X - screenEnd.X),
            Math.Abs(screenStart.Y - screenEnd.Y)
        );
    }
}

進階替代方案比較

方案優點缺點適用場景
DrawReversibleFrame無需重繪背景、效能極佳、API 簡單僅支援矩形框線、顏色受 XOR 限制簡單選取框、裁剪框
雙重緩衝 + OnPaint完整控制繪圖內容、支援任意形狀需管理繪圖狀態、重繪開銷大複雜編輯器、多圖層
Overlay 透明視窗獨立視窗層級、不干擾主視窗視窗管理複雜、跨螢幕問題跨應用程式選取、螢幕截圖

注意事項與最佳實務

  • 座標轉換:務必使用 PointToScreen,Client 座標會導致位置錯誤
  • 多螢幕:跨螢幕拖曳時螢幕座標仍正確,但需測試 DPI 縮放影響
  • 高 DPI:啟用 Per-Monitor DPI Awareness,確保座標對應正確
  • 清理保證:MouseUp、MouseLeave、表單失去焦點時必須清除殘留框線
  • 效能:極高頻率呼叫(>60fps)可能造成閃爍,考慮節流或改用雙重緩衝

結語

ControlPaint.DrawReversibleFrame 是實作橡皮筋選取框的經典高效方案,利用 XOR 光柵運算特性實現無殘留的即時視覺回饋。掌握螢幕座標轉換、反相顏色計算、拖曳生命週期管理三大關鍵,即可在圖形編輯器、表單設計器、截圖工具中建立專業級選取體驗。

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