DwmGetDxSharedSurface函数,魔兽世界后台截图、热键截图 再找小图
Microsoft DirectX Graphics Infrastructure (DXGI) 处理枚举图形适配器、枚举显示模式、选择缓冲区格式、在进程 (之间共享资源,例如,在应用程序和桌面窗口管理器 (DWM) ) 之间共享资源,以及向窗口或监视器显示呈现的帧。可以使用 DXGI 向窗口、监视器或其他图形组件呈现帧,以便最终进行合成和显示。 还可以使用 DXGI 读取监视器上的内容。
|
|
DXGI 接口 | 本部分包含有关 DXGI 提供的接口的信息。 |
DXGI 的目的是与内核模式Driver和系统Hardware通信 |
| DXGI 函数 | 本部分包含有关 DXGI 提供的函数的信息。 | ||
| DXGI 结构 | 本部分包含有关 DXGI 提供的结构的信息。 | ||
| DXGI 枚举 | 本部分包含有关 DXGI 提供的枚举的信息。 | ||
| DXGI 常量 | 本部分包含有关 DXGI 提供的常量的信息。 |
DWM Window capture by DwmGetDxSharedSurface, background windows(excluding minimization) are supported, but some windows are not supported.
BOOL WINAPI DwmGetDxSharedSurface ( HWND hwnd,
HANDLE* phSurface,
LUID* pAdapterLuid,
ULONG* pFmtWindow,
ULONG* pPresentFlags,
ULONGLONG* pWin32kUpdateId
)
Parameters
hwnd:The window to investigate
phSurface:
资源句柄。A pointer that receives a shared handle to the windows' surface. This can be passed IDirect3DDevice9::CreateTexture to make a texture.
- pAdapterLuid:
- Pointer that receives the id of the adapter the window resides on
- pFmtWindow
- The D3DFMT_ format of the window surface
- pPresentFlags
- Pointer that receives the D3DPRESENT_ flags for the window/surface
- pWin32kUpdateId
- 不知道是什么东西
Return Value
Non-zero on success, zero on failure. Use GetLastError() for more information.
Remarks
Any output parameters not required can be set to NULL
按照这个 大神提供的方法 DX后台截图C++实现代码 实现截图,可后台窗口截图,相比较其他方式,这个窗口截图算是比较稳定有效,最接近我的需求的。
但在截取 魔兽世界 后台非最小化的窗口时 出现黑屏 白屏的几率非常多,基本都是!
查了许多资料认为,都说是DirectDraw硬件加速导致的,也尝试了许多查询到的解决办法,在WIN10,DirectX 12 下都没有成功实现截取后台 魔兽世界 窗口图像。
偶然间,后来发现将WOW里面可以选择使用 DirectX 的版本,将游戏内dx的版本设置由12改为11就OK了!!还有 窗口最小化 游戏是不再绘制图的,只是被遮挡才算后台,依然绘制。
这里对比下 DX11,DX12接口函数的差异!
HRESULT D3D11CreateDevice(
[in, optional] IDXGIAdapter *pAdapter,
D3D_DRIVER_TYPE DriverType,
HMODULE Software,
UINT Flags,
[in, optional] const D3D_FEATURE_LEVEL *pFeatureLevels,
UINT FeatureLevels,
UINT SDKVersion,
[out, optional] ID3D11Device **ppDevice,
[out, optional] D3D_FEATURE_LEVEL *pFeatureLevel,
[out, optional] ID3D11DeviceContext **ppImmediateContext
);
HRESULT D3D12CreateDevice(
[in, optional] IUnknown *pAdapter,
D3D_FEATURE_LEVEL MinimumFeatureLevel,
[in] REFIID riid,
[out, optional] void **ppDevice
);
HRESULT D3D11On12CreateDevice(
[in] IUnknown *pDevice,
UINT Flags,
[in, optional] const D3D_FEATURE_LEVEL *pFeatureLevels,
UINT FeatureLevels,
[in, optional] IUnknown * const *ppCommandQueues,
UINT NumQueues,
UINT NodeMask,
[out, optional] ID3D11Device **ppDevice,
[out, optional] ID3D11DeviceContext **ppImmediateContext,
[out, optional] D3D_FEATURE_LEVEL *pChosenFeatureLevel
);
还是有差异,暂且先不弄D3D12。
解决 硬件加速 的截图也先不弄了,我只想截取 魔兽世界 后台窗口,能弄好就OK了,以后再拓展(查了许多资料,觉得比较容易处理硬件加速的后台窗口截图的方法,Detours HOOK便捷,不晓得会不会激发HOOK对象的安全性审查机制)。
===2024-12-19===================
找小图:
先弄下傻瓜式的,使用的OpenCV的模板匹配函数 C++: void matchTemplate(InputArray image, InputArray templ, OutputArray result, int method),根据官方的介绍,大概意思是:比对 templ 划过 image 时,
使用给定的 method (
&amp;amp;nbsp;denotes&amp;amp;nbsp;&amp;lt;code class="docutils literal"&amp;gt;image&amp;lt;/code&amp;gt;,&amp;amp;nbsp;&amp;lt;img src="https://docs.opencv.org/2.4.13.7/_images/math/87804527283a4539e1e17c5861df8cb92a97fd6d.png" alt="T" class="math" /&amp;gt;&amp;amp;nbsp;&amp;lt;code class="docutils literal"&amp;gt;template&amp;lt;/code&amp;gt;,&amp;amp;nbsp;&amp;lt;img src="https://docs.opencv.org/2.4.13.7/_images/math/8fa391da5431a5d6eaba1325c3e7cb3da22812b5.png" alt="R" class="math" /&amp;gt;&amp;amp;nbsp;&amp;lt;code class="docutils literal"&amp;gt;result&amp;lt;/code&amp;gt;&amp;amp;nbsp;)&amp;lt;/strong&amp;gt;&amp;lt;/strong&amp;gt;方法,计算&amp;lt;strong&amp;gt;&amp;lt;strong&amp;gt;&amp;amp;nbsp;&amp;lt;strong&amp;gt;templ(0....x`-1,0-y`-1)&amp;lt;/strong&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;/strong&amp;gt;&amp;amp;nbsp;&lt;/strong&gt;&lt;/strong&gt;</strong></strong></strong></strong>与 下方 image 同尺寸区域image(x+templ.x,y+templ.y)的值,将这个值存储于 result 中。给出了 6 种method 。
局限性:不支持缩放,旋转
使用时碰到的问题和解决:1、我这里是函数调用后内存读取报错,原因:用3通道的 templ 与 4通道的 image 计算,转换下就OK 了;
2、单个通道使用较为合适;
1、method=CV_TM_SQDIFF
描述: templ(x1, y1) 与 image( x + x1, y + y1) 的差平方求和 结果放置于 result(x, y),所以 得到的值越小,templ 与 image 在 x, y 处的一致性越好;
2、method=CV_TM_SQDIFF_NORMED
描述:每个点对应 做差的平方 除以 平方积开方;同上面的方法一样,得到的值越小,templ 与 image 在 x, y 处的一致性越好;
3、method=CV_TM_CCORR

描述:每个点对应求积,感觉没有什么用,
4、method=CV_TM_CCORR_NORMED

描述:
5、method=CV_TM_CCOEFF

where

6、method=CV_TM_CCOEFF_NORMED

通常在本机上的截图,在本机大图中找小图,上面的一个模式下,都可以不错的成功率。
----2024-12-28-------------------------------------------------------------
定义一个热键,截取全屏图,扣出一个小图,保存(文件名、图像)
VS2019 有个一个 加速键表 :
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_IMAGEANALYSE));
在ID列中,为某个资源绑定一个 热键就OK了!程序窗口 最小化 后不能响应加速键。
消息处理函数中添加对应的代码:
case IDC_IMAGEANALYSE:
MessageBox(hWnd, L"加速键被按下", L"提示", MB_OK);
break;
全局系统热键怎么弄呢 ?如下可以实现。
程序创建窗口后添加:
RegisterHotKey(hWnd, 1009, MOD_SHIFT| MOD_CONTROL, VK_DELETE);
窗口消息处理函数 摧毁窗口 对应添加:
UnregisterHotKey(hWnd, 1009);
窗口消息处理函数 添加 事件:
case WM_HOTKEY:
if (wParam == 1009)
::SetForegroundWindow(hWnd); // 激活窗口到前台,或者干点别的什么事
MessageBox(hWnd, L"热键ctrl + shift + del 被按下", L"WM_HOTKEY", MB_OK);
break;
// 2025-1-11
通过 串口CH340 通讯 CH9329 可以实现 英雄联盟全屏模式 下鼠标,键盘的操作,结合后台截图,识图,可以自动战斗了// 2025-1-12
Microsoft DirectX 图形基础结构 (DXGI) 管理可独立于 Direct3D 图形运行时的低级别任务。 DXGI 为多个 Direct3D 版本提供通用框架。
IDXGIFactory 接口调用 IDXGIFactory::EnumAdapters 返回一组表示视频硬件的 IDXGIAdapter 接口来完成;
IDXGIFactory1* pFactory;
CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pFactory));
IDXGIAdapter1* pAdapter;
pFactory->EnumAdapters1(0, &pAdapter);


浙公网安备 33010602011771号