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

動態捕獲視窗 DC 並即時顯示:BitBlt + 計時器實現遠端桌面預覽效果

     編輯:關於VC++

前言

需在自家視窗中即時鏡像顯示另一個應用程式視窗畫面(如媒體播放器預覽、監控畫面)。本文核心技術:GetDC 取得來源視窗 DC → CreateCompatibleDC/Bitmap 離屏複製 → StretchBlt 縮放繪製到目標視窗,配合 SetTimer 週期性刷新,並處理 WM_ERASEBKGND 消除閃爍。

核心函式 Show_WindowDC

BOOL CShowWindowDCView::Show_WindowDC(CWnd* pDest, CWnd* pSrc)
{
    if (!pDest || !pSrc) return FALSE;

    CRect srcRect; pSrc->GetWindowRect(&srcRect);
    int w = srcRect.Width(), h = srcRect.Height();

    // 1. 取得來源 DC 並建立相容記憶體 DC/位圖
    HDC hSrcDC = pSrc->GetDC()->m_hDC;
    HDC hMemDC = CreateCompatibleDC(hSrcDC);
    HBITMAP hBmp = CreateCompatibleBitmap(hSrcDC, w, h);
    HBITMAP hOld = (HBITMAP)SelectObject(hMemDC, hBmp);

    // 2. 將來源視窗畫面複製到記憶體位圖
    BitBlt(hMemDC, 0, 0, w, h, hSrcDC, 0, 0, SRCCOPY);

    // 3. 取回位圖句柄
    hBmp = (HBITMAP)SelectObject(hMemDC, hOld);

    // 4. 縮放繪製到目標視窗
    CRect destRect; pDest->GetWindowRect(&destRect);
    CDC dcMem; dcMem.CreateCompatibleDC(pDest->GetDC());
    HBITMAP pOldBmp = (HBITMAP)SelectObject(dcMem.m_hDC, hBmp);

    pDest->GetDC()->StretchBlt(0, 0, destRect.Width(), destRect.Height(),
                               &dcMem, 0, 0, w, h, SRCCOPY);

    // 5. 清理資源
    dcMem.SelectObject(pOldBmp); dcMem.DeleteDC();
    DeleteDC(hMemDC);
    // 注意:hSrcDC 為 GetDC 取得,不應 DeleteDC,由系統管理
    return TRUE;
}

動態刷新機制

// OnInitialUpdate 或 OnCreate
SetTimer(1, 100, NULL); // 100ms 刷新一次 (10 FPS)

void CShowWindowDCView::OnTimer(UINT nID)
{
    Invalidate(); // 觸發 OnDraw
    CView::OnTimer(nID);
}

// 消除閃爍:禁止系統擦除背景
BOOL CShowWindowDCView::OnEraseBkgnd(CDC* pDC)
{
    return TRUE; // 由 OnDraw 完全繪製
}

// OnDraw 執行捕獲與繪製
void CShowWindowDCView::OnDraw(CDC* pDC)
{
    CWnd* pSrc = FindWindow(_T("GeminiWindowClass"), NULL); // 目標視窗類別名
    if (pSrc) Show_WindowDC(this, pSrc);
}

效果展示

動態捕獲視窗畫面示意

關鍵優化與注意事項

議題處理方式
來源視窗最小化/遮蓋無法捕獲可見區域外畫面;需確保來源視窗可見且非最小化
高 DPI / 縮放StretchBlt 自動處理縮放;若需像素完美可配合 SetProcessDPIAware
效能瓶頸100ms 間隔適中;若來源畫面變化少可加長間隔;大面積高頻更新建議改用 DirectX/DWM API
視窗查找硬編碼實際專案應結合 EnumWindows + 標題/類別/進程 ID 多條件查找,參考「Spy++ 風格搜尋視窗」文章
資源洩漏風險範例中 hSrcDC 來自 GetDC 不可 DeleteDC,已修正

擴充應用

  • 多視窗監控面板:陣列化 Show_WindowDC,單一計時器驅動多目標。
  • 截圖/錄製工具:將記憶體位圖編碼為 JPEG/H.264 寫入檔案。
  • 跨進程 UI 自動化:配合 SendMessage/PostMessage 實現遠端操作。

結語

GDI BitBlt + 計時器是實現視窗畫面即時鏡像最簡單、相容性最廣 (Win98+) 的方案。現代專案若需高效能、支援硬體加速、捕獲 DirectX/全螢幕遊戲畫面,請改用 Desktop Duplication API (DXGI) 或 Windows.Graphics.Capture (UWP/WinUI 3)。

本文配套原始碼可供下載。

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