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

C++Builder 雙緩衝繪圖技術:消除閃爍、提升大量資料曲線渲染效能

     編輯:VC 教學

問題背景

在 TPaintBox、TPanel 或表單 OnPaint 中直接繪製大量資料點(數萬筆),會導致:

  • 繪圖耗時數秒,UI 凍結。
  • 頻繁的 Invalidate()/Repaint() 引發嚴重閃爍。

雙緩衝原理

在記憶體建立一個與螢幕繪圖區域大小相同的離屏位圖(TBitmap),所有繪圖操作先在該位圖上完成,最後一次性用 BitBlt 或 Canvas->Draw 複製到螢幕裝置環境(DC)。這樣:

  • 螢幕只更新一次,無閃爍。
  • 記憶體繪圖速度遠快於螢幕 DC(無 GDI 同步開銷)。

標準實作步驟

// 1. 建立離屏位圖(通常在 FormCreate 或 Resize 時)
Graphics::TBitmap* BufferBmp = new Graphics::TBitmap();
BufferBmp->Width  = ClientWidth;   // 或 PaintBox 寬高
BufferBmp->Height = ClientHeight;

// 2. 離屏繪圖
BufferBmp->Canvas->Brush->Color = clBtnFace;
BufferBmp->Canvas->FillRect(Rect(0, 0, Width, Height));

// 繪製座標軸、網格、曲線...
BufferBmp->Canvas->MoveTo(x0, y0);
BufferBmp->Canvas->LineTo(x1, y1);
// ... 大量 LineTo / Polyline

// 3. 一次性複製到螢幕
BitBlt(Canvas->Handle, 0, 0, Width, Height,
       BufferBmp->Canvas->Handle, 0, 0, SRCCOPY);
// 或 Canvas->Draw(0, 0, BufferBmp);

// 4. 釋放(通常在 FormDestroy)
delete BufferBmp;

進階優化技巧

  • 複用 Buffer:不要每次重新 new/delete,建立一次,Resize 時調整大小。
  • 部分更新:僅重繪變化區域(髒矩形),再 BitBlt 對應矩形。
  • 使用 TPaintBox + OnPaint:在 OnPaint 中直接 BitBlt Buffer,避免重入問題。
  • 高效曲線繪製:預先計算所有點座標存入陣列,一次呼叫 Polyline 或 PolyPolyline,避免逐點 MoveTo/LineTo。
  • GDI+ / Direct2D:對於極高效能需求,考慮使用 GDI+ Graphics 繪製到 Bitmap,或 Direct2D 硬體加速。

完整範例:即時波形顯示

// Form.h
private:
    Graphics::TBitmap* FBuffer;
    std::vector FWavePoints;
    void __fastcall DrawWaveForm();
    void __fastcall UpdateBufferSize();

// Form.cpp
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {
    FBuffer = new Graphics::TBitmap();
    DoubleBuffered = true;  // VCL 雙緩衝(僅對控件有效,自繪仍需手動)
}

void __fastcall TForm1::FormResize(TObject *Sender) {
    UpdateBufferSize();
    Invalidate();
}

void __fastcall TForm1::UpdateBufferSize() {
    FBuffer->Width  = ClientWidth;
    FBuffer->Height = ClientHeight;
}

void __fastcall TForm1::DrawWaveForm() {
    // 離屏繪製
    FBuffer->Canvas->Brush->Color = clBlack;
    FBuffer->Canvas->FillRect(Rect(0,0,ClientWidth,ClientHeight));
    FBuffer->Canvas->Pen->Color = clLime;
    FBuffer->Canvas->Pen->Width = 1;
    if (FWavePoints.size() > 1)
        FBuffer->Canvas->Polyline(&FWavePoints[0], FWavePoints.size()-1);
}

void __fastcall TForm1::PaintBox1Paint(TObject *Sender) {
    DrawWaveForm();
    BitBlt(PaintBox1->Canvas->Handle, 0, 0, ClientWidth, ClientHeight,
           FBuffer->Canvas->Handle, 0, 0, SRCCOPY);
}

__fastcall TForm1::~TForm1() { delete FBuffer; }

總結

雙緩衝是 Windows GDI 繪圖消除閃爍、提升效能的基石技術。掌握「離屏繪圖 → 一次性 Blit」模式,並結合 Polyline、髒矩形、GDI+ 等進階手段,可輕鬆應對萬級資料點的即時曲線渲染需求。

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