自動化測試中截取 WPF Popup 視窗失敗,引發對三種截圖方案的深入探索。本文記錄從 GDI → PrintWindow → 模擬鍵盤的嘗試歷程與失敗原因分析。
BitBlt(hdcDest, 0, 0, width, height, hdcSrc, left, top, SRCCOPY);
現象:截取 Popup 只得到背景,Popup 內容透明。
原因:WPF 使用 DirectX 渲染,不繪製到 GDI DC。BitBlt 僅能捕捉 GDI 繪製內容。
IntPtr hdc = GetWindowDC(hwnd);
IntPtr hdcMem = CreateCompatibleDC(hdc);
IntPtr hBmp = CreateCompatibleBitmap(hdc, w, h);
SelectObject(hdcMem, hBmp);
PrintWindow(hwnd, hdcMem, 0); // 關鍵調用
// ... 取得位圖並儲存
現象:視窗框架 (MFC 部分) 正常,但所有 WPF 區域 (按鈕、文字、圖表) 均為純黑。
原因:PrintWindow 發送 WM_PRINT/WM_PRINTCLIENT 訊息要求視窗繪製到指定 DC,但 WPF 視覺樹不處理此訊息進行 DirectX→GDI 回繪。
WPF (Windows Presentation Foundation) 採用保留模式繪圖,透過 DirectX (Milcore) 直接與 GPU 交互,繞過傳統 GDI/GDI+ 堆疊。因此:
HDC/BitBlt/PrintWindow 的傳統截圖手段,**無法**捕捉 WPF 視覺內容。系統級 PrintScreen 由 Windows 視窗管理器 (DWM) 協助完成畫面合成,包含 DirectX 表面。下一篇將實測模擬鍵盤事件 + 剪貼簿讀取方案。
Windows Vista 引入 Desktop Window Manager (DWM),所有視窗 (含 WPF、Win32) 以紋理形式提交給 DWM 合成最終桌面影像。PrintScreen 實際讀取的是這張合成後的桌面紋理,故能包含 WPF 內容。