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

VC++ MFC 串口資料即時繪圖:SetPixel/Ellipse + 多執行緒架構

     編輯:程式設計綜合問答

需求

透過串口接收資料 (每秒 1 點),在 MFC 對話框/視圖繪製軌跡圖 (圓形軌跡)。需解決繪圖效能、執行緒安全、UI 回應問題。

核心方案:工作執行緒收資料 + UI 執行緒畫圖

1. 繪圖原語選擇

  • 單點:`pDC->SetPixel(x, y, color)` — 最快,但點太小難看。
  • 微小圓/方:`pDC->Ellipse(x-r, y-r, x+r, y+r)` 或 `Rectangle` — 視覺佳,效能可接受 (每秒 1 點極輕鬆)。
  • 高效能大量點:`PolyLine`/`PolyPolyline` 批次繪製、記憶體 DC 雙緩衝、`CDC::SetPixelV` (不回傳顏色、較快)。

2. 多執行緒架構 (關鍵)


// Worker Thread 執行緒函數
UINT SerialReadThread(LPVOID pParam) {
    CMyView* pView = (CMyView*)pParam;
    BYTE buf[256];
    while (!pView->m_bStopThread) {
        DWORD dwRead;
        if (ReadFile(pView->m_hComm, buf, sizeof(buf), &dwRead, NULL) && dwRead > 0) {
            // 解析座標 (假設協定固定)
            int x = buf[0]; int y = buf[1]; 
            
            // 關鍵:PostMessage 送至 UI 執行緒,不可直接呼叫 UI 方法!
            pView->PostMessage(WM_USER_NEW_POINT, (WPARAM)x, (LPARAM)y);
        }
        Sleep(10); // 避免佔滿 CPU
    }
    return 0;
}

// UI 執行緒訊息處理
#define WM_USER_NEW_POINT (WM_USER + 1)

BEGIN_MESSAGE_MAP(CMyView, CView)
    ON_MESSAGE(WM_USER_NEW_POINT, OnNewPoint)
END_MESSAGE_MAP()

LRESULT CMyView::OnNewPoint(WPARAM wParam, LPARAM lParam) {
    int x = (int)wParam;
    int y = (int)lParam;
    m_points.Add(CPoint(x, y)); // 儲存歷史點 (CArray/CList)
    
    // 觸發重繪 (僅無效化最小區域)
    CRect rect(x-3, y-3, x+3, y+3); 
    InvalidateRect(rect, FALSE); 
    return 0;
}

void CMyView::OnDraw(CDC* pDC) {
    // 雙緩衝防閃爍
    CMemDC memDC(pDC, &rectClip); // 自定義雙緩衝類或用 CMemoryDC
    
    // 繪製所有歷史點
    CPen pen(PS_SOLID, 1, RGB(255,0,0));
    CPen* pOldPen = memDC.SelectObject(&pen);
    for (CPoint pt : m_points) {
        memDC.Ellipse(pt.x-2, pt.y-2, pt.x+2, pt.y+2);
    }
    memDC.SelectObject(pOldPen);
}

3. 關鍵點總結

  1. 絕不在工作執行緒呼叫 UI 方法 (如 `GetDC()`、`Invalidate()`、`Ellipse()`),必須 `PostMessage`/`SendMessage` 交給 UI 執行緒。
  2. 雙緩衝 (Double Buffering):`OnDraw` 使用記憶體 DC 繪製完畢再 BitBlt 到螢幕 DC,消除閃爍。
  3. 最小無效區域:`InvalidateRect(smallRect, FALSE)` 僅重繪新增點附近,而非整個視窗。
  4. 資料結構:用 `CArray` 或 `std::vector` 儲存歷史軌跡,支援縮放/平移/清除。
  5. 串口設定**:`DCB` 設定鮑率、資料位、停止位、奇偶校驗;`COMMTIMEOUTS` 設定讀取超時避免阻塞。

參考資源

MFC 繪圖雙緩衝完整範例:MFC 雙緩衝繪圖實戰

結論

MFC 即時繪圖核心是 **「工作執行緒收資料 → PostMessage → UI 執行緒儲存點 → InvalidateRect → OnDraw 雙緩衝繪製」**。`SetPixel`/`Ellipse` 效能足夠應付每秒幾十點;若上千點需優化,改用 `PolyLine` 批次繪製 + 虛擬清單只畫可視區域。

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