1

My code shows a black image when Windows runs the screensaver after a wait. But it works when I click preview.

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;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
MG1
  • 11
  • 1
  • Use [`BitBlt()`](https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-bitblt) properly by checking its result - if it is `FALSE` call `GetLastError()`. 101 of using WinAPI. If I'd program Windows then I would forbid screensavers to capture or record anything for security reasons. – AmigoJack Jun 19 '23 at 19:55
  • 1
    AFAIK you cannot capture user's desktop in recent Windows versions from screensaver for security reasons. I don't remember when this change was introduced. Probably around Windows 7 or 8. – Dalija Prasnikar Jun 19 '23 at 20:06
  • @DalijaPrasnikar Is it for security reasons or is perhaps rendering of other windows suspended in order to save on energy. – SilverWarior Jun 19 '23 at 22:09
  • @SilverWarior I am sure that using screen saver is in direct contradiction with saving energy. Also windows are not rendered unless there is something to be rendered. If the window is hidden behind screen saver window then there will be no rendering unless someone requests it. – Dalija Prasnikar Jun 20 '23 at 06:51

0 Answers0