捕获DirectX应用程序的可视输出 – 即使在后台?

我需要捕获DirectX窗口的视觉输出(如屏幕截图)。 目前,我使用这种方法 。
但是,当窗口在后台时,它会捕获前面的任何内容。

我看到即使在最小化或背景中也可以渲染DirectX窗口,因此这应该是可能的。
但是,怎么样? (它也需要很快,它也需要在Windows XP上运行,不幸的是……)

编辑 :这些天我很忙……别担心,如果它过期,我会把赏金放回去。

要捕获后台(或移出屏幕)的Direct3D窗口,我相信您有以下选择:

  1. 通过您已经发布的链接在目标应用程序中注入和挂钩Direct3D 或这个更新的示例 (EasyHook可能很难设置,但它确实工作得很好) – 您可以随时寻求帮助以使其正常工作。 我已经使用这种技术在没有问题的情况下捕获了许多游戏(最近一次用于一个ambilight-clone项目)。 这种方法的问题在于您对游戏保护造成禁令的担忧,但FRAP也使用挂钩来实现这一目标,所以您的担忧可能会被夸大? 我猜游戏玩家被禁止进行屏幕截图是一种昂贵的查找方式。

  2. 对于Vista / Win 7上的窗口应用程序 – 您可以注入并挂钩DWM并通过其共享表面发出捕获请求。 我已经在Vista上工作 ,但还没有完成它在Windows 7上工作,这是一个适用于Windows 7 http://www.youtube.com/watch?v=G75WKeXqXkc的示例。 这种方法的主要问题是使用未记录的API,这可能意味着您的应用程序在Windows补丁发布时没有任何警告而中断 – 您还必须为每种新的主要Windows风格重做该技术。 这也无法满足您在Windows XP中捕获的需要。

  3. 同样在DWM中,有一个缩略图API。 这有限制取决于您尝试做什么。 有关此API的一些信息以及其他DWM API,请访问http://blogs.msdn.com/b/greg_schechter/archive/2006/09/14/753605.aspx

  4. 还有其他技术可以在不使用EasyHook的情况下拦截Direct3D调用,例如用包装器替换各种DLL。 你会在这里找到各种其他游戏挂钩/拦截技术: http : //www.gamedeception.net/

  5. 只需将Direct3D应用程序带到前台(我认为在您的情况下这是不受欢迎的) – 除非您也移动窗口,否则这对于屏幕外窗口不起作用。

  6. 不幸的是,我能想到的唯一的Windows XP解决方案是以某种forms拦截Direct3D API。

只是在最小化的情况下澄清Direct3D渲染。 在我对这个问题的相当有限的测试中,我发现这是依赖于应用程序的; 通常不建议在应用程序最小化时(也就是此引用 )进行渲染,但它会在后台继续渲染。

更新 :为第1点提供了更多最新注射示例的附加链接。

快速谷歌和我发现这个与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/

您链接到(来自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 )。