我想在第三方全屏Windows应用程序之上显示一些自定义图形。
你玩过任何Steam游戏吗?它有一个可执行的GameOverlayUI.exe,可以让你从游戏中访问Steam窗口。 (GUI元素看起来是自定义绘制的,我不知道这是否是必要的;但它们在游戏中看起来与在桌面上看起来完全相同。)它甚至可以在游戏图形中“黯淡”背景。
我想知道如何编写这样的应用程序。
我也想知道解决方案的范围有多广。你能为所有OpenGL应用程序使用一种方法吗?对于所有Direct3D减去DirectDraw应用程序?对于所有全屏Windows应用程序?
我正在寻找更多“现代”和通用解决方案 - 覆盖命令提示符或320x240索引颜色应用程序不是问题。
编辑:一些澄清:全屏应用程序不是我的。它可以是任何东西。最有可能的是,它将是一款3D游戏。我希望在游戏图形的顶部显示屏幕右下角的数字时钟。如果可能的话,我想避免诸如注入代码或调试过程等技巧。
答案 0 :(得分:23)
嗯,这是另一个例子。 Xfire是一个聊天程序,它将界面覆盖到游戏中,因此您可以在播放时接收消息。他们这样做的方法是在进程内存级别编辑d3d / opengl DLL,就像注入程序集跳转一样。我知道这是因为他们的方法导致我的mod崩溃,我实际上看到了他们注入d3d9.dll的奇怪的汇编代码。
所以这就是Xfire如何做到这一点:
由于您需要劫持属于该游戏的图形设备,因此没有其他可想到的方法。我愿意打赌Steam和Xfire一样。所以是的,没有简单的方法可以做到这一点,除非有人创建了一个有用的库来完成你需要做的所有事情。
您还询问了在叠加层下调整游戏图形的方法。这只是一个简单的DrawPrimitive
调用,用于在屏幕上绘制一个填充的透明矩形。
答案 1 :(得分:21)
使用完整代码here
创建了一个Gist这是一个非常深奥的艺术,有几种方法可以做到这一点。我更喜欢所谓的 Direct3D Wrapper 。我做完这个已经很多年了,但是我曾经做过一次游戏。我可能遗漏了一些细节,但我只是想说明这个想法。
所有Direct3D9游戏都需要在渲染屏幕并准备好绘制后调用IDirect3DDevice9::EndScene。所以从理论上讲,我们可以将自定义代码放在EndScene
中,以便在游戏中绘制我们想要的内容。我们通过在游戏中创建一个看起来像IDirect3DDevice9的类来实现这一点,但它实际上只是一个将所有函数调用转发给真实类的包装器。现在,在我们的自定义类中,EndScene
的包装函数如下所示:
HRESULT IDirect3DDevice9::EndScene()
{
// draw overlays here
realDevice.EndScene();
}
然后我们将它编译成一个名为d3d9.dll的DLL,并将其放入游戏可执行文件的目录中。真正的d3d9.dll应该在/ system32文件夹中,但游戏首先查看当前目录,而是加载我们的。一旦游戏加载,它就会使用我们的DLL来创建包装类的实例。现在,每次调用EndScene
时,我们的代码都会执行,以便在屏幕上绘制我们想要的内容。
我认为你可以尝试使用OpenGL相同的原理。但是为了防止篡改,我认为一些现代游戏试图阻止这种情况。
答案 2 :(得分:2)
有一个免费软件项目,它的名字是taksi link text。我不确定这个应用程序如何覆盖该过程因为我正在检查代码但是检查我认为这是一个很好的项目
答案 3 :(得分:0)
我一直在想这个。对于OpenGL,我将WGL的SwapBuffers与Detours挂钩,在游戏后绘制我的东西,然后自己交换缓冲区。
答案 4 :(得分:-1)
我已经完成了DirectX和EX的覆盖。 WPF视口(同样的,真的),使用叠加在3D可视化上绘制一些不错的2D GDI +东西。
我通过在“实际”可视化上使用面板进行管理,将颜色设置为透明,除了我想要覆盖的位。工作得很好,但通过“绘图”图层向3D控件传递点击,拖动和其他事件有点痛苦。