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

VC++ 實現無閃爍波形動態繪圖技術詳解

     編輯:關於VC++

前言

在信號處理與實時監控系統中,將採集到的信號波形即時顯示在界面上是常見需求。然而,若直接在螢幕裝置上繪圖,畫面會因頻繁重繪產生明顯閃爍,嚴重影響觀測體驗。本文介紹一種經典的「雙緩衝繪圖」技術:先在記憶體裝置上下文(Memory DC)完成所有繪圖操作,再一次性將位圖拷貝至螢幕裝置上下文(Screen DC),從而實現流暢無閃爍的動態波形顯示。

效果演示

程式執行時的波形動畫效果如下:

核心原理:雙緩衝繪圖

Windows GDI 繪圖本質上是對裝置上下文(DC)的操作。螢幕 DC 直接對應顯示器輸出,每次繪圖指令都會立即觸發畫面更新,導致閃爍。解決方案是引入記憶體 DC 作為中介:

  1. 建立與螢幕 DC 相容的記憶體 DC 及位圖
  2. 在記憶體 DC 上完成清背景、繪波形、畫座標軸等所有操作
  3. 呼叫 BitBlt 將記憶體位圖一次性複製到螢幕 DC

由於螢幕只經歷一次完整畫面更新,人眼無法察覺中間過程,即消除了閃爍。

關鍵程式碼實現

1. 類別成員變數宣告(頭文件)

private:
    CDC *pDC;           // 螢幕繪圖裝置指標
    CDC memDC;          // 記憶體繪圖裝置
    int m_High;         // 繪圖區域上邊界
    int m_Low;          // 繪圖區域下邊界
    int m_lCount[1024]; // 波形資料緩衝區
    int m_now;          // 當前寫入索引

2. 初始化與定時器設置(OnInitDialog)

BOOL CDrawTest::OnInitDialog()
{
    CDialog::OnInitDialog();

    m_Low = 0;
    m_High = 1024;
    m_now = 0;
    SetTimer(1, 100, NULL); // 100ms 觸發一次重繪

    return TRUE;
}

3. 定時器響應與繪圖邏輯(OnTimer)

void CDrawTest::OnTimer(UINT nIDEvent)
{
    CRect rect;
    CWnd* pWnd = GetDlgItem(IDC_COORD); // 取得 Picture 控制項
    pWnd->GetClientRect(&rect);         // 取得繪圖區域大小
    pDC = pWnd->GetDC();                // 取得螢幕 DC
    pWnd->Invalidate();
    pWnd->UpdateWindow();

    // --- 建立記憶體 DC 與位圖 ---
    CBitmap memBitmap;
    CBitmap* pOldBmp = NULL;
    memDC.CreateCompatibleDC(pDC);
    memBitmap.CreateCompatibleBitmap(pDC, rect.right, rect.bottom);
    pOldBmp = memDC.SelectObject(&memBitmap);

    // 先將螢幕當前內容拷貝到記憶體(保留靜態背景)
    memDC.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY);

    // --- 自定義波形繪圖函數 ---
    DrawWave(&memDC); // 具體實現見原始碼:繪製網格、坐標軸、波形曲線等

    // --- 將記憶體位圖一次性輸出到螢幕 ---
    pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);

    // --- 清理資源 ---
    memDC.SelectObject(pOldBmp);
    memDC.DeleteDC();
    memBitmap.DeleteObject();

    CDialog::OnTimer(nIDEvent);
}

關鍵技術點總結

  • CreateCompatibleDC / CreateCompatibleBitmap:建立與目標 DC 格式相容的記憶體繪圖表面,確保 BitBlt 高速傳輸無格式轉換開銷。
  • SelectObject / DeleteObject:GDI 物件選入/選出與釋放必須成對出現,避免資源洩漏。
  • BitBlt(SRCCOPY):光柵操作碼 SRCCOPY 直接複製像素,速度最快。
  • 定時器間隔:100ms(10 FPS)適合一般監控波形;若需更高幀率可縮短間隔,但需評估繪圖耗時是否小於間隔。

延伸應用建議

  • 若波形點數極大(如 >10 萬點),建議採用「多邊形繪製 Polyline」或「分段繪製」優化 DrawWave 內部邏輯。
  • 支援縮放、平移時,可在 DrawWave 中引入座標轉換矩陣。
  • 現代專案可考慮使用 Direct2D / GDI+ 進一步提升繪圖效能與抗鋸齒品質。

本文配套完整原始碼可供下載參考。

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