Delphi屏保程序截图异常:预览正常,自动运行时截图黑屏
Markdown格式示例及问题解决方案
一、格式规则示例
1. 标题
一级标题
二级标题
三级标题
2. 列表
- 普通列表项1
- 普通列表项2
- 嵌套列表项1
- 嵌套列表项2
3. 文本强调
这是斜体强调,这是粗体强调
4. 代码展示
单行代码:GetDC(GetDesktopWindow)
多行代码块:
function CaptureScreenToStream: TMemoryStream; var DesktopDC: HDC; begin // 代码逻辑 end;
5. 引用文本
这是一段引用内容
二、屏保截图黑屏问题解决
问题场景
Windows自动运行屏保时,用现有代码捕获的图像为黑色,但点击屏保预览功能时截图正常。原代码如下:
function CaptureScreenToStream: TMemoryStream; var DesktopDC: HDC; CaptureBitmap: TBitmap; Width, Height: Integer; begin DesktopDC := GetDC(GetDesktopWindow); try Width := round(GetDeviceCaps(DesktopDC, HORZRES) * strtoint(GetLastLoadedDPI) / 96); Height := round(GetDeviceCaps(DesktopDC, VERTRES) * strtoint(GetLastLoadedDPI) / 96); CaptureBitmap := TBitmap.Create; try CaptureBitmap.Width := Width; CaptureBitmap.Height := Height; BitBlt(CaptureBitmap.Canvas.Handle, 0, 0, Width, Height, DesktopDC, 0, 0, SRCCOPY); Result := TMemoryStream.Create; CaptureBitmap.SaveToStream(Result); Result.Position := 0; finally CaptureBitmap.Free; end; finally ReleaseDC(GetDesktopWindow, DesktopDC); end; end;
问题原因
屏保运行时是独立的顶层窗口,GetDesktopWindow获取的桌面DC不包含屏保画面;而预览模式下屏保是在桌面窗口内渲染,因此能正常捕获。
解决方案
修改代码,优先捕获屏保窗口的内容, fallback 到原桌面捕获逻辑:
function CaptureScreenToStream: TMemoryStream; var TargetDC: HDC; CaptureBitmap: TBitmap; Width, Height: Integer; ScreensaverWnd: HWND; begin // 查找屏保窗口(类名为WindowsScreenSaverClass) ScreensaverWnd := FindWindow('WindowsScreenSaverClass', nil); if ScreensaverWnd <> 0 then begin TargetDC := GetDC(ScreensaverWnd); try Width := GetDeviceCaps(TargetDC, HORZRES); Height := GetDeviceCaps(TargetDC, VERTRES); CaptureBitmap := TBitmap.Create; try CaptureBitmap.Width := Width; CaptureBitmap.Height := Height; // 使用PrintWindow捕获窗口内容,支持后台/顶层窗口 PrintWindow(ScreensaverWnd, CaptureBitmap.Canvas.Handle, PW_CLIENTONLY); Result := TMemoryStream.Create; CaptureBitmap.SaveToStream(Result); Result.Position := 0; finally CaptureBitmap.Free; end; finally ReleaseDC(ScreensaverWnd, TargetDC); end; end else begin // 原逻辑捕获桌面 TargetDC := GetDC(GetDesktopWindow); try Width := Round(GetDeviceCaps(TargetDC, HORZRES) * StrToInt(GetLastLoadedDPI) / 96); Height := Round(GetDeviceCaps(TargetDC, VERTRES) * StrToInt(GetLastLoadedDPI) / 96); CaptureBitmap := TBitmap.Create; try CaptureBitmap.Width := Width; CaptureBitmap.Height := Height; BitBlt(CaptureBitmap.Canvas.Handle, 0, 0, Width, Height, TargetDC, 0, 0, SRCCOPY); Result := TMemoryStream.Create; CaptureBitmap.SaveToStream(Result); Result.Position := 0; finally CaptureBitmap.Free; end; finally ReleaseDC(GetDesktopWindow, TargetDC); end; end; end;
内容的提问来源于stack exchange,提问作者MG1
相关产品推荐
相关产品推荐

