3

i am using the createdesktop api to create a desktop and i would like to take a screenshot or send input mouse/keyboard without dispalying the desktop to the user.any ideeas on how to implement this???

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
opc0de
  • 11,557
  • 14
  • 94
  • 187

2 Answers2

6

The short answer that I've found is that you can't. You can't take a screenshot of an inactive desktop because there are no paint calls because there are no visible windows to redraw.

You can do a SwitchDesktop() call, screen shot, then SwitchDesktop() back. The user won't notice it, but you likely won't get much in the screen shot because in this short time the windows haven't had time to redraw.

Another thing is, you have to make a new thread to call SetThreadDesktop(). If you use your main thread to do so, it will fail when using a GUI application. SetThreadDesktop() fails when you have a window in the current desktop.

SysInternals has an application to manage multiple desktops (like the linux desktop switch). When your about to pick a desktop to switch to it will show you a thumbnail of the desktop. This thumbnail is not live, it is captured by the last known full redraw when the user is in that desktop. In short, if SysInternals can't do a live screenshot I doubt any of us will.

This is of course based on my own research of this exact feature. If someone has actually gotten it to work I'd love to know so I can't use it too!

ThievingSix
  • 1,044
  • 1
  • 11
  • 23
  • [i have executed my program on `Default` desktop after switch to new](http://stackoverflow.com/questions/41029243/how-send-keys-and-mouse-inputs-to-default-desktop-when-new-desktop-created-is-vi) and i'm able to capture screenshot, but without sucess in mouse/keyboard interation. You have some suggesion for help me? –  Jan 17 '17 at 16:54
3

Edit: This won't work for invisible desktops, I've looked to my old code, and I see that I needed that for catching screenshot of active desktop (which was not 'WinSta0\Default'), to get handle of active user desktop I've used OpenInputDesktop.

+1 ThievingSix you are right.

Sorry everyone for my misunderstanding.


You need to use SetThreadDesktop (if you are creating desktop by CreateDestkop, then you have handle for it which you pass to SetThreadDesktop). After switching desktop for thread, you can catch screenshot. Good idea would be revert to previous desktop for thread (to not 'break' other/future code).

var
  lOldDesktop: HDESK;
begin
  lOldDesktop:= GetThreadDesktop(GetCurrentThreadId);
  try
    if not SetThreadDesktop(ADesktop) then // pass handle to your desktop, or dekstop handle obtained from OpenInputDesktop
      {error handle, like RaiseLastOSError or Exit(False)};

    // your screenshot/input/mouse code here

  finally
    if lOldDesktop<> 0 then // GetThreadDesktop can fail (I don't know condition when this GetThreadDesktop(GetCurrentThreadId) could fail)
      SetThreadDesktop(lOldDesktop); // revert thread to previous desktop
  end;
end;

This code should run in non-main thread, as ThievingSix pointed because SetThreadDesktop can fail in that case. Safe way is spawn thread to make screenshot.

PS. I'm not sure if this will work with "send input mouse/keyboard" (it should), but for screenshot works.

Edit:

Krystian Bigaj
  • 1,295
  • 8
  • 14
  • can you provide some code for taking a screen shot because i created a desktop i called setthreaddesktop but when i try to take a screen shot i only get the tray – opc0de Jan 03 '11 at 14:16
  • You don't need another "screenshot code", because it's corret. Your new desktop *won't* have StartMenu, each desktop have "own windows". You can try with http://technet.microsoft.com/en-us/sysinternals/cc817881 (SysInternals Desktop as ThievingSix said), when you create new desktop with this tool it will create new explorer.exe process that runs on new desktop. – Krystian Bigaj Jan 03 '11 at 18:42
  • 1
    I would love to see working code because the last time I tried this it would show a black screen with the screenshot (because no windows were redrawing). The fact that SysInternals isn't doing live thumbnails adds to that point. – ThievingSix Jan 03 '11 at 18:59
  • I've edited my answer (see top), and looks that you are right. Thanks again ThievingSix for correting me. – Krystian Bigaj Jan 03 '11 at 19:20
  • Aww! I was actually hoping that you were right so I could use it in one of my current projects. – ThievingSix Jan 03 '11 at 19:31