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

C++Builder TCanvas 完全指南:繪圖畫布核心類、GDI 封裝、座標系統與高性能渲染實戰

     編輯:關於C++

C++Builder TCanvas 完全指南:繪圖畫布核心類、GDI 封裝、座標系統與高性能渲染實戰

TCanvas 是 VCL 繪圖子系統的抽象畫布,封裝 Windows GDI HDC,提供筆刷字體狀態管理、幾何圖元繪製、文本輸出、位圖操作、剪裁區域等完整能力。所有可視控件(TForm、TPaintBox、TBitmap、TMetafile、TPrinter)均通過 Canvas 屬性暴露繪圖介面。本文系統梳理核心屬性、繪圖方法分類、座標系統、狀態鎖定、事件模型與高性能渲染模式。

類層次與核心狀態

TObject
  └── TPersistent
        └── TCanvas
              ├── TControlCanvas      // 控件畫布(自動綁定控件 HDC)
              └── TMetafileCanvas     // 圖元檔錄製畫布

// 核心狀態屬性(均為物件包裝,賦值即 Assign,非替換指標)
__property TBrush*  Brush;   // 填充:顏色、風格、位圖
__property TPen*    Pen;     // 線條:顏色、寬度、風味、模式
__property TFont*   Font;    // 字體:名稱、大小、風格、字符集、顏色
__property TRect    ClipRect; // 唯讀,當前剪裁矩形
__property int      CopyMode; // 位圖複製模式(ROP2 代碼)
__property TPoint   PenPos;   // 當前筆位置(LineTo 終點)

繪圖方法分類速查

類別方法說明
幾何圖元MoveTo/LineTo移動/畫線到指定點
Polyline/Polygon多段線/閉合多邊形(自動填充)
Rectangle/RoundRect矩形/圓角矩形(筆畫框+刷填充)
Ellipse/Chord/Pie橢圓/弓形/扇形(筆畫框+刷填充)
Arc橢圓弧(需起止向量)
PolyBezier/PolyBezierTo貝茲曲線組(4 點一段)
FrameRect僅畫矩形框(1 像素寬,用 Brush)
FillRect/FloodFill矩形填充/區域漫水填充
文本輸出TextOut指定點輸出字串,更新 PenPos
TextRect剪裁矩形內輸出
TextWidth/TextHeight/TextExtent測量字串像素尺寸
位圖/圖像Draw/StretchDraw原尺寸/縮放繪製 TGraphic
CopyRect從另一 Canvas 複製矩形區
BrushCopy位圖透明色替換複製
狀態控制Lock/Unlock/TryLock多執行緒繪圖同步(LockCount 計數)
Refresh重置 HDC 筆刷字體選擇

座標系統與剪裁

  • 裝置座標:原點 (0,0) 位於客戶區左上角,X 右、Y 下,單位像素。
  • ClipRect:繪圖輸出被限制在此矩形內。OnPaint 時系統自動設為需重繪區域(InvalidateRect 累積)。
  • 手動設定:Canvas->ClipRect = Rect(10,10,200,200); 後續繪圖超出部分被剪裁。

筆刷字體:賦值語義陷阱

// 錯誤:以為替換物件,實為 Assign
Canvas->Brush = otherBrush;  // 實際執行 Canvas->Brush->Assign(otherBrush)

// 正確:直接操作屬性
Canvas->Brush->Color = clRed;
Canvas->Brush->Style = bsSolid;
Canvas->Pen->Width = 2;
Canvas->Font->Name = "Consolas";

原則:Brush/Pen/Font 屬性為包裝物件,生命週期由 Canvas 管理,切勿 delete 或 new 替換。

多執行緒繪圖同步

// 背景執行緒繪製位圖,再主執行緒 Blit 到螢幕
TBitmap* bmp = new TBitmap();
bmp->Width = 800; bmp->Height = 600;
// 背景執行緒
bmp->Canvas->Lock();  // 防止主執行緒同時訪問
try {
    // 大量繪圖操作...
} __finally {
    bmp->Canvas->Unlock();
}
// 主執行緒 Paint 事件
Form->Canvas->Draw(0, 0, bmp);

注意:TControlCanvas 擁有自有 HDC,不可 手動 Lock/Unlock,VCL 內部已處理。

事件模型

事件觸發時機用途
OnChanging繪圖方法調用前預處理、記錄 Dirty 區域
OnChange繪圖方法調用後觸發重繪通知、更新捲軸範圍

屬性變更(Pen->Color = ...)不觸發 Canvas 事件,僅觸發包裝物件自身事件。

高性能渲染模式

  1. 雙緩衝:TBitmap 離屏繪製 → Draw(0,0,bmp) 一次 Blit,消除閃爍。
  2. 批次繪圖:PolyLine/Polygon/PolyBezier 單次調用替代循環 LineTo,減少 GDI 呼叫開銷。
  3. 避免 GetPixel/SetPixel:極慢。需像素級操作鎖定 TBitmap->ScanLine[y] 直接操作記憶體。
  4. 字體快取:頻繁切換字體觸發 SelectObject 開銷大,預建 TFont 物件池複用。
  5. Metafile 錄製:複雜矢量圖錄製為 TMetafile,重複播放極快(GDI 播放優化)。

常見陷阱

現象原因對策
繪圖不顯示在 OnPaint 外繪製控件 Canvas僅在 OnPaint 或 TPaintBox::OnPaint 中繪製
線條寬度異常Pen->Width > 1 時風格必須 psSolid虛線/點線強制 1 像素寬
文字底色不透明Brush->Style != bsClear文本輸出前設 Canvas->Brush->Style = bsClear
高 DPI 模糊未啟用 Per-Monitor DPI AwareManifest + Application->Scaled = true

TCanvas 以極簡 API 隱藏了 GDI 的繁瑣細節,掌握其狀態管理語義、座標系統、剪裁機制與批次繪圖模式,即可在 VCL 應用中實現流暢、高性能的自定義繪圖。

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