获取使用createdesktop api创建的桌面的屏幕截图

时间:2011-01-02 21:07:21

标签: windows delphi winapi screenshot

我正在使用createdesktop api创建一个桌面,我想截取屏幕截图或发送输入鼠标/键盘而不会将桌面显示给用户。如何实现这一点的任何想法?

2 个答案:

答案 0 :(得分:6)

我发现的简短答案是你不能。您无法截取非活动桌面的屏幕截图,因为没有可见的绘图,因为没有可见的窗口可以重绘。

您可以进行SwitchDesktop()调用,屏幕截图,然后返回SwitchDesktop()。用户不会注意到它,但你可能不会在屏幕截图中获得太多,因为在这么短的时间内窗口没有时间重绘。

另一件事是,你必须创建一个新线程来调用SetThreadDesktop()。如果使用主线程执行此操作,则在使用GUI应用程序时将失败。当前桌面上有一个窗口时,SetThreadDesktop()会失败。

SysInternals有一个管理多个桌面的应用程序(如Linux桌面交换机)。当您即将选择要切换到桌面的桌面时,将显示桌面的缩略图。此缩略图不是实时的,当用户在该桌面中时,它会被上次已知的完全重绘捕获。简而言之,如果SysInternals无法进行实时截图,我怀疑我们中的任何人都会。

这当然是基于我对这个确切特征的研究。如果有人真的让它上班,我很想知道,所以我也不能使用它!

答案 1 :(得分:3)

修改:这对隐形桌面不起作用,我查看了我的旧代码,我发现我需要用它来捕获活动桌面的屏幕截图(这是'WinSta0 \ Default'),以获得我使用OpenInputDesktop的活动用户桌面的处理。

+1 ThievingSix你是对的

很抱歉所有人都误解了我。


您需要使用SetThreadDesktop(如果您通过CreateDestkop创建桌面,那么您可以使用它来处理它传递给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。我不确定这是否适用于“发送输入鼠标/键盘”(它应该),但是对于截图工作。

修改