我需要捕获DirectX窗口的视觉输出(如屏幕截图)。 目前,我使用this approach 但是,当窗口处于后台时,它会捕获前面的任何内容。
我看到即使在最小化或背景中也会渲染DirectX窗口,因此这应该是可能的 但是,怎么样? (它还需要很快,它也需要在Windows XP上运行,不幸的是......)
编辑:这些天我很忙......别担心,如果它过期,我会把赏金退回。
答案 0 :(得分:20)
要捕获后台(或移出屏幕)的Direct3D窗口,我相信您有以下选择:
通过您已发布的链接or this more up-to-date example在目标应用程序中注入并挂钩Direct3D(EasyHook可能很难设置,但确实很有效) - 您可以随时寻求帮助它工作。我已经使用这种技术在没有问题的情况下捕获了许多游戏(最近一次用于环境影城克隆项目)。这种方法的问题在于您对游戏保护造成禁令的担忧,但FRAP也使用挂钩来实现这一目标,所以您的担忧可能会被夸大?我猜游戏玩家被禁止进行屏幕截图是一种昂贵的查找方式。
对于Vista / Win 7上的窗口化应用程序 - 您可以注入并挂钩DWM并通过其共享表面发出捕获请求。我有这个working on Vista,但还没有完成它在Windows 7上工作,这是一个适用于Windows 7 http://www.youtube.com/watch?v=G75WKeXqXkc的例子。这种方法的主要问题是使用未记录的API,这可能意味着您的应用程序在Windows补丁发布时没有任何警告而中断 - 您还必须为每种新的主要Windows风格重做该技术。这也无法满足您在Windows XP中捕获的需要。
同样在DWM中,有一个缩略图API。这有限制取决于您尝试做什么。此API上有一些信息以及其他DWM API http://blogs.msdn.com/b/greg_schechter/archive/2006/09/14/753605.aspx
还有其他技术可以在不使用EasyHook的情况下拦截Direct3D调用,例如用包装器替换各种DLL。你会在这里找到各种其他游戏挂钩/拦截技巧:http://www.gamedeception.net/
只需将Direct3D应用程序带到前台(我认为在您的情况下这是不受欢迎的) - 除非您也移动窗口,否则这对于屏幕外窗口不起作用。
不幸的是,我能想到的唯一的Windows XP解决方案是以某种形式拦截Direct3D API。
在最小化的同时澄清Direct3D渲染。在我对这个问题的相当有限的测试中,我发现这是依赖于应用程序的;通常not recommended渲染发生在应用程序最小化时(也就是reference),然而它会在后台继续渲染。
更新:为第1点提供了更多最新注入示例的附加链接。
答案 1 :(得分:5)
快速谷歌和我发现这个与Windows XP有关的代码项目。我不知道你是否可以将这些知识应用到Windows Vista和7 ??
http://www.codeproject.com/Articles/5051/Various-methods-for-capturing-the-screen
修改强>
我也发现了这篇文章:
http://www.codeproject.com/Articles/20651/Capturing-Minimized-Window-A-Kid-s-Trick
这是来自Justins博客文章的评论链接。他似乎正在与某人合作(我看到你的链接)。
http://spazzarama.com/2009/02/07/screencapture-with-direct3d/
答案 2 :(得分:1)
您在项目中使用的链接代码(来自spazzarama)捕获了DirectX设备的前端缓冲区。您是否尝试过捕获后备缓冲区?从链接网站上的代码开始,您将从
更改第90行device.GetFrontBufferData(0, surface);
到
Surface backbuffer = device.GetBackBuffer(0, 0, BackBufferType.Mono);
SurfaceLoader.Save("Screenshot.bmp", ImageFileFormat.Bmp, backbuffer);
这还涉及删除链接示例中的第96-98行。可以在没有阻碍窗口的情况下生成后备缓冲器。
修改强>
没关系所有这一切。我刚刚意识到你的链接示例代码正在使用窗口句柄来定义屏幕区域,而实际上并没有使用DirectX窗口做任何事情。您的示例代码将无法在障碍物周围工作,因为您的区域在您访问它之前已经使用其前面的另一个窗口绘制。
挽救应用程序的最佳选择可能是在运行代码捕获图像之前将DirectX窗口置于屏幕顶部。您可以使用Wind32API
BringWindowToTop
函数执行此操作(http://msdn.microsoft.com/en-us/library/ms632673%28VS.85%29.aspx)。