【发布时间】:2016-11-24 03:29:07
【问题描述】:
我正在使用 createdesktop api 创建一个桌面,我想截屏或发送输入鼠标/键盘而不向用户显示桌面。关于如何实现这个的任何想法???
【问题讨论】:
标签: windows delphi winapi screenshot
我正在使用 createdesktop api 创建一个桌面,我想截屏或发送输入鼠标/键盘而不向用户显示桌面。关于如何实现这个的任何想法???
【问题讨论】:
标签: windows delphi winapi screenshot
我发现的简短答案是您不能。您无法截取非活动桌面的屏幕截图,因为没有绘制调用,因为没有可重绘的可见窗口。
您可以调用 SwitchDesktop()、截屏,然后返回 SwitchDesktop()。用户不会注意到它,但您可能不会在屏幕截图中获得太多信息,因为在这么短的时间内窗口还没有时间重绘。
另一件事是,您必须创建一个新线程来调用 SetThreadDesktop()。如果您使用主线程来执行此操作,则在使用 GUI 应用程序时它将失败。当前桌面中有窗口时,SetThreadDesktop() 失败。
SysInternals 有一个管理多个桌面的应用程序(如 linux 桌面切换)。当您要选择要切换的桌面时,它将显示桌面的缩略图。此缩略图不是实时的,它是在用户位于该桌面时由最后一次已知的完整重绘捕获的。简而言之,如果 SysInternals 无法制作实时屏幕截图,我怀疑我们中的任何人都不会。
这当然是基于我自己对这个确切功能的研究。如果有人真的让它工作了,我很想知道,所以我也不能使用它!
【讨论】:
Default desktop after switch to new 并且我能够捕获屏幕截图,但鼠标/键盘交互没有成功。你有什么建议可以帮助我吗?
编辑:这不适用于不可见的桌面,我查看了我的旧代码,发现我需要它来捕获活动桌面的屏幕截图(不是 '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。我不确定这是否适用于“发送输入鼠标/键盘”(它应该),但对于屏幕截图有效。
编辑:
【讨论】: