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

Delphi 獲取 Canvas 對象:TControl.Canvas、GetDC、TCanvas.Create 實戰

     編輯:Delphi

三種獲取 Canvas 繪圖表面的方法與適用場景

在 Delphi 中繪圖首先需要 TCanvas 實例。除表單/控件自帶 Canvas 屬性外,還可透過 GetDC 獲取裝置上下文並包裝為 TCanvas,或針對無 Canvas 屬性的控件 (如 TPanel) 間接繪圖。本文詳解三種方法的適用場景與資源管理要點。

方法 1:控件自帶 Canvas 屬性 (最直接)


// TForm, TPaintBox, TImage, TCustomControl 等直接擁有
Form1.Canvas.TextOut(10, 10, 'Hello');
PaintBox1.Canvas.FillRect(PaintBox1.ClientRect);

方法 2:TCanvas.Create + GetDC (通用、適用於無 Canvas 控件)


procedure TForm1.Button1Click(Sender: TObject);
var
  Cvs: TCanvas;
begin
  // TPanel 無 Canvas 屬性,但有 Handle
  Cvs := TCanvas.Create;
  try
    Cvs.Handle := GetDC(Panel1.Handle);  // 獲取裝置上下文
    Cvs.Brush.Color := clBlue;
    Cvs.FillRect(Panel1.ClientRect);     // 在 Panel 上繪圖
  finally
    ReleaseDC(Panel1.Handle, Cvs.Handle); // 必須釋放 DC
    Cvs.Free;                             // 釋放 TCanvas 包裝器
  end;
end;

方法 3:PaintBox 控件 (專為繪圖設計)


// TPaintBox 類似 TForm,直接擁有 Canvas
PaintBox1.Canvas.Brush.Color := clRed;
PaintBox1.Canvas.FillRect(PaintBox1.ClientRect);

完整對比範例:Button 點擊在 Panel 與 PaintBox 繪圖


procedure TForm1.Button1Click(Sender: TObject);
var
  Cvs: TCanvas;
begin
  // PaintBox1 直接使用 Canvas
  PaintBox1.Canvas.Brush.Color := clRed;
  PaintBox1.Canvas.FillRect(PaintBox1.ClientRect);

  // Panel1 間接獲取 Canvas
  Cvs := TCanvas.Create;
  try
    Cvs.Handle := GetDC(Panel1.Handle);
    Cvs.Brush.Color := clBlue;
    Cvs.FillRect(Panel1.ClientRect);
  finally
    ReleaseDC(Panel1.Handle, Cvs.Handle);
    Cvs.Free;
  end;
end;

關鍵資源管理規則

GetDC / ReleaseDC 關鍵細節

  • GetDC(hwnd):獲取客戶區 DC,需配對 ReleaseDC(hwnd, hdc)
  • GetWindowDC(hwnd):獲取整個視窗 DC (含非客戶區),同樣需 ReleaseDC
  • GetDCEx:進階標誌控制 (剪裁、父視窗剪裁等)
  • DC 不可跨執行緒共享:每執行緒獨立獲取/釋放
  • DC 洩漏後果:系統 DC 池耗盡,導致全系統繪圖失敗

進階:自定義控件繼承 TGraphicControl (擁有 Canvas)


type
  TMyGraphic = class(TGraphicControl)
  protected
    procedure Paint; override;
  end;

procedure TMyGraphic.Paint;
begin
  // 直接使用繼承的 Canvas
  Canvas.Brush.Color := clGreen;
  Canvas.FillRect(ClientRect);
  Canvas.TextOut(10, 10, 'Custom Paint');
end;

常見陷阱與避坑

  1. 忘記 ReleaseDC:導致 DC 洩漏,必須在 try/finally 中釋放
  2. 在 OnPaint 外使用 GetDC:可能與系統繪製衝突,優先用 Canvas 屬性或 Invalidate 觸發重繪
  3. TCanvas.Handle := 0 後未 Free:TCanvas 本身是包裝器,需 Free
  4. 跨進程 Handle 傳遞:DC 句柄進程隔離,不可直接傳遞
  5. 高 DPI 下座標縮放:GetDC 返回物理像素 DC,邏輯座標需手動換算

效能建議

  • 高頻繪圖:重用 TCanvas 實例,避免頻繁 Create/Free
  • 大面積填充:FillRect 比逐像素快數量級
  • 複雜場景:雙緩衝 TBitmap 後一次 Draw 到目標 DC

根據「控件類型、繪圖頻率、生命週期」選擇獲取 Canvas 的方式,並嚴格遵守 GetDC/ReleaseDC 配對原則,是穩定繪圖的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方法建立責任釋放責任DC 所有權
控件.Canvas控件內部控件銷毀時自動控件管理
TCanvas.Create + GetDC開發者開發者 (try/finally)開發者必須 ReleaseDC
TCanvas.Create + SetWindowDC開發者開發者視窗類管理 (較少用)