需在自家視窗中即時鏡像顯示另一個應用程式視窗畫面(如媒體播放器預覽、監控畫面)。本文核心技術:GetDC 取得來源視窗 DC → CreateCompatibleDC/Bitmap 離屏複製 → StretchBlt 縮放繪製到目標視窗,配合 SetTimer 週期性刷新,並處理 WM_ERASEBKGND 消除閃爍。
Show_WindowDCBOOL 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,單一計時器驅動多目標。SendMessage/PostMessage 實現遠端操作。GDI BitBlt + 計時器是實現視窗畫面即時鏡像最簡單、相容性最廣 (Win98+) 的方案。現代專案若需高效能、支援硬體加速、捕獲 DirectX/全螢幕遊戲畫面,請改用 Desktop Duplication API (DXGI) 或 Windows.Graphics.Capture (UWP/WinUI 3)。
本文配套原始碼可供下載。