使用CreateDesktop API创建桌面后如何截屏?

3

我正在使用CreateDesktop API创建桌面,并且希望在不向用户显示桌面的情况下,能够截取屏幕或发送鼠标/键盘输入信号。有没有什么好的实现方法?

2个回答

6
我发现的简短答案是你不能。因为没有可见的窗口需要重绘,所以在非活动桌面上无法进行屏幕截图。
你可以使用SwitchDesktop()调用,在截屏后再使用SwitchDesktop()返回原来的桌面。用户不会注意到这一点,但是由于在这段时间内窗口没有重新绘制,因此您可能无法获得很多屏幕截图。
另外,您必须创建一个新线程来调用SetThreadDesktop()。如果使用主线程来执行此操作,则在使用GUI应用程序时将失败。当当前桌面中有窗口时,SetThreadDesktop()会失败。
SysInternals有一个应用程序来管理多个桌面(类似于Linux桌面切换)。当您要选择要切换到的桌面时,它将显示该桌面的缩略图。此缩略图不是实时的,而是在用户进入该桌面时通过最后已知的完全重绘捕获的。简而言之,如果SysInternals无法进行实时截图,我怀疑我们中的任何人都无法做到。
当然,这是基于我对这个功能的研究。如果有人真的让它起作用,我很想知道,这样我也可以使用它!

我已经在“默认”桌面上执行了我的程序,然后切换到新的桌面。我能够捕获屏幕截图,但是鼠标/键盘交互没有成功。你有什么建议可以帮助我吗? - user6828073

3

编辑: 对于不可见的桌面,这种方法行不通。我查看了我的旧代码,发现我需要它来捕获活动桌面(不是“WinSta0\Default”),为了获取活动用户桌面的句柄,我使用了OpenInputDesktop。

+1 ThievingSix 你是对的

抱歉,我误解了。


如果您使用CreateDestkop创建桌面,则需要使用SetThreadDesktop(然后将其句柄传递给SetThreadDesktop)。在为线程切换桌面后,您可以捕获屏幕截图。一个好主意是为线程恢复先前的桌面(以免'破坏'其他/未来的代码)。

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;

这段代码应该在非主线程中运行,正如ThievingSix所指出的那样,因为SetThreadDesktop在这种情况下可能会失败。安全的方式是生成线程进行截图。

PS. 我不确定这是否适用于“发送输入鼠标/键盘”(应该可以),但对于截屏有效。

编辑


你能提供一些截屏的代码吗?因为我创建了一个名为setthreaddesktop的桌面,但是当我尝试截屏时,我只能得到托盘。 - opc0de
你不需要另一个“截图代码”,因为它是正确的。你的新桌面将没有开始菜单,每个桌面都有“自己的窗口”。你可以尝试使用http://technet.microsoft.com/en-us/sysinternals/cc817881(如ThievingSix所说的SysInternals Desktop),当你使用这个工具创建新桌面时,它会创建一个在新桌面上运行的新explorer.exe进程。 - Krystian Bigaj
1
我很想看到可工作的代码,因为上次我尝试时它只会显示一个黑屏幕和截图(因为没有窗口在重绘)。SysInternals没有实时缩略图也加剧了这一点。 - ThievingSix
我已经编辑了我的回答(请参见顶部),看起来你是正确的。再次感谢ThievingSix纠正我。 - Krystian Bigaj
啊哦!我真的希望你是正确的,这样我就可以在我的一个当前项目中使用它。 - ThievingSix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接