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

C# 圖形中級篇:滑鼠選取邏輯與多格剪貼簿實作(第六講·中下)

     編輯:關於C語言

三階段滑鼠選取狀態機

private Point LastMousePosition = new Point(-1, -1); // -1 代表無效

protected override void OnMouseDown(MouseEventArgs e) {
    base.OnMouseDown(e);
    // 客戶區 → 視圖座標(折射修正)
    Point p = new Point(e.X, e.Y);
    p.Offset(-AutoScrollPosition.X, -AutoScrollPosition.Y);
    LastMousePosition = p;

    // 單點選取:檢查每個單元格邊界是否包含點
    foreach (var cell in myDocument.Cells) {
        bool select = cell.Bounds.Contains(p);
        if (cell.Selected != select) {
            InvalidateCell(cell);
            cell.Selected = select;
        }
    }
}

protected override void OnMouseMove(MouseEventArgs e) {
    base.OnMouseMove(e);
    if (LastMousePosition.X < 0) return; // 未按下

    // 目前點也轉視圖座標
    Point p = new Point(e.X, e.Y);
    p.Offset(-AutoScrollPosition.X, -AutoScrollPosition.Y);

    // 兩點構成選取矩形
    Rectangle selRect = Rectangle.Empty;
    selRect.X = Math.Min(p.X, LastMousePosition.X);
    selRect.Width = Math.Abs(p.X - LastMousePosition.X);
    selRect.Y = Math.Min(p.Y, LastMousePosition.Y);
    selRect.Height = Math.Abs(p.Y - LastMousePosition.Y);

    // 矩形與單元格相交即選取
    foreach (var cell in myDocument.Cells) {
        bool flag = selRect.IntersectsWith(cell.Bounds);
        if (cell.Selected != flag) {
            cell.Selected = flag;
            InvalidateCell(cell);
        }
    }
}

protected override void OnMouseUp(MouseEventArgs e) {
    base.OnMouseUp(e);
    LastMousePosition = new Point(-1, -1); // 重置
}

Copy 方法補充:DataObject 多格式封裝

同 81270,此處重點在於 DataObject.SetData 可疊加格式,Clipboard.SetDataObject(data, true) 第二參數 true 確保應用程式關閉後剪貼簿資料仍保留。

設計精華

  • 座標轉換集中化:所有滑鼠事件入口統一先 Offset(-AutoScrollPosition),消除折射干擾。
  • 選取狀態變更才失效:if (cell.Selected != flag) 避免重複 InvalidateCell,極大降低重繪開銷。
  • 矩形相交測試:Rectangle.IntersectsWith 以 O(1) 完成範圍選取判定。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved