【问题标题】:take a screenshot of a desktop created using createdesktop api截取使用 createdesktop api 创建的桌面的屏幕截图
【发布时间】:2016-11-24 03:29:07
【问题描述】:

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

【问题讨论】:

    标签: windows delphi winapi screenshot


    【解决方案1】:

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

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

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

    SysInternals 有一个管理多个桌面的应用程序(如 linux 桌面切换)。当您要选择要切换的桌面时,它将显示桌面的缩略图。此缩略图不是实时的,它是在用户位于该桌面时由最后一次已知的完整重绘捕获的。简而言之,如果 SysInternals 无法制作实时屏幕截图,我怀疑我们中的任何人都不会。

    这当然是基于我自己对这个确切功能的研究。如果有人真的让它工作了,我很想知道,所以我也不能使用它!

    【讨论】:

    【解决方案2】:

    编辑:这不适用于不可见的桌面,我查看了我的旧代码,发现我需要它来捕获活动桌面的屏幕截图(不是 'WinSta0\Default'),为了获得活动用户桌面的句柄,我使用了 OpenInputDesktop。

    +1 盗贼六你是对的

    给大家带来的误会很抱歉。


    您需要使用 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。我不确定这是否适用于“发送输入鼠标/键盘”(它应该),但对于屏幕截图有效。

    编辑

    【讨论】:

    • 您能否提供一些截屏代码,因为我创建了一个名为 setthreaddesktop 的桌面,但是当我尝试截屏时,我只能得到托盘
    • 您不需要另一个“屏幕截图代码”,因为它是正确的。您的新桌面不会有开始菜单,每个桌面都有“自己的窗口”。您可以尝试使用technet.microsoft.com/en-us/sysinternals/cc817881(如ThievingSix 所说的SysInternals Desktop),当您使用此工具创建新桌面时,它将创建在新桌面上运行的新explorer.exe 进程。
    • 我很想看到工作代码,因为上次我尝试这个时,它会在屏幕截图中显示一个黑屏(因为没有窗口正在重绘)。 SysInternals 不做实时缩略图的事实增加了这一点。
    • 我已经编辑了我的答案(见顶部),看起来你是对的。再次感谢 ThivingSix 纠正我。
    • 哇!我实际上希望你是对的,这样我就可以在我目前的一个项目中使用它。
    猜你喜欢
    • 2021-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 2017-05-10
    • 2012-08-17
    相关资源
    最近更新 更多