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  ( I&amp;amp;amp;nbsp;denotes&amp;amp;amp;nbsp;&amp;amp;lt;code class="docutils literal"&amp;amp;gt;image&amp;amp;lt;/code&amp;amp;gt;,&amp;amp;amp;nbsp;&amp;amp;lt;img src="https://docs.opencv.org/2.4.13.7/_images/math/87804527283a4539e1e17c5861df8cb92a97fd6d.png" alt="T" class="math" /&amp;amp;gt;&amp;amp;amp;nbsp;&amp;amp;lt;code class="docutils literal"&amp;amp;gt;template&amp;amp;lt;/code&amp;amp;gt;,&amp;amp;amp;nbsp;&amp;amp;lt;img src="https://docs.opencv.org/2.4.13.7/_images/math/8fa391da5431a5d6eaba1325c3e7cb3da22812b5.png" alt="R" class="math" /&amp;amp;gt;&amp;amp;amp;nbsp;&amp;amp;lt;code class="docutils literal"&amp;amp;gt;result&amp;amp;lt;/code&amp;amp;gt;&amp;amp;amp;nbsp;)&amp;amp;lt;/strong&amp;amp;gt;&amp;amp;lt;/strong&amp;amp;gt;方法,计算&amp;amp;lt;strong&amp;amp;gt;&amp;amp;lt;strong&amp;amp;gt;&amp;amp;amp;nbsp;&amp;amp;lt;strong&amp;amp;gt;templ(0....x`-1,0-y`-1)&amp;amp;lt;/strong&amp;amp;gt;&amp;amp;lt;/strong&amp;amp;gt;&amp;amp;lt;/strong&amp;amp;gt;&amp;amp;amp;nbsp;&amp;lt;/strong&amp;gt;&amp;lt;/strong&amp;gt;&lt;/strong&gt;&lt;/strong&gt;</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 

               R(x,y)= \sum _{x',y'} (T(x',y')-I(x+x',y+y'))^2 

                描述: templ(x1, y1)  与  image( x + x1,  y + y1)  的差平方求和 结果放置于 result(x, y),所以 得到的值越小,templ  image 在 x,  y 处的一致性越好;

2、method=CV_TM_SQDIFF_NORMED      

                  R(x,y)= \frac{\sum_{x',y'} (T(x',y')-I(x+x',y+y'))^2}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}    

                描述:每个点对应 做差的平方 除以 平方积开方;同上面的方法一样,得到的值越小,templ  image 在 x, y 处的一致性越好;

3、method=CV_TM_CCORR  

                  R(x,y)= \sum _{x',y'} (T(x',y')  \cdot I(x+x',y+y'))

                描述:每个点对应求积,感觉没有什么用,

4、method=CV_TM_CCORR_NORMED

                  R(x,y)= \frac{\sum_{x',y'} (T(x',y') \cdot I(x+x',y+y'))}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}

                描述:

5、method=CV_TM_CCOEFF

                  R(x,y)= \sum _{x',y'} (T'(x',y')  \cdot I'(x+x',y+y'))

                where

                  \begin{array}{l} T'(x',y')=T(x',y') - 1/(w  \cdot h)  \cdot \sum _{x'',y''} T(x'',y'') \\ I'(x+x',y+y')=I(x+x',y+y') - 1/(w  \cdot h)  \cdot \sum _{x'',y''} I(x+x'',y+y'') \end{array}

6、method=CV_TM_CCOEFF_NORMED

                  R(x,y)= \frac{ \sum_{x',y'} (T'(x',y') \cdot I'(x+x',y+y')) }{ \sqrt{\sum_{x',y'}T'(x',y')^2 \cdot \sum_{x',y'} I'(x+x',y+y')^2} }

   通常在本机上的截图,在本机大图中找小图,上面的一个模式下,都可以不错的成功率。

----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);

 

posted @ 2024-04-05 21:49  O-Y  阅读(610)  评论(0)    收藏  举报