图形编程丨图形绘制基础imgui篇—D3D9 HOOK 创建内部Imgui窗口

2023-11-13

作者:小阿栗

 

Imgui又称为Dear ImGui,它是与平台无关的C++轻量级跨平台图形界面库,没有任何第三方依赖,可以将Imgui的源码直接加到项目中使用,也可以编译成dll, Imgui使用DX或者OpenGL进行界面渲染,Imgui主要用于游戏行业。

这里我们需要用到两个工具Detours-master(微软的hook库)和imgui-master,主要讲D3D9HOOK。

我们先来创建一个DLL项目。步骤如下:

1.选择新建项目

2.选择Windows桌面->动态链接库(DLL)->D3D9HOOK,点击确定

3.删除framework.h、pch.h以及pch.cpp文件。添加一个dllmain.h头文件

4.dllmain.cpp中要包含头文件添加#include <Windows.h>

5. 配置

5.1 选择属性

5.2 修改运行库以及Spectre缓解,选择应用

5.3 配置include路径,点击“宏”,搜索DX,根据地址找到文件位置,将 $(DXSDK_DIR)include填入,应用

5.4 搜索DX,将$(DXSDK_DIR)Lib填入,搜索$(platformTarget),将$(DXSDK_DIR)lib\$(platformTarget)填入,应用

(图片注释:配置好会自动匹配x86/x64不需要再改)

5.5 新增d3d9.lib,d3dx9.lib这两个依赖项,应用

6. 配置好环境后,编译HOOK库(编译x86和x64两个版本)

X86:找到Visual Studio2017,打开“x86 Native Tools Prompt for VS 2017”,然后cd到路径里nmake进行编译

X64:找到Visual Studio2017,打开“适用于VS 2017的 x64 本机工具命令提示”,然后cd到路径里nmake进行编译

7.打开项目文件夹

8.新建一个目录Detours,将lib.x86、lib.x64和include复制过来(将lib.去掉方便后续识别)

9.新建筛选器,命名Detours

10.在Detours中添加现有项,选定两个头文件detours.h和detver.h

11.配置lib库

11.1选择属性

11.2 编辑包含目录,宏-包含目录-$(ProjectDir)Detours\include,应用

11.3编辑附加库目录,宏-附加库目录-$(ProjectDir)Detours\Lib\$(platformTarget),应用

11.4 编辑附加依赖项,添加detours.lib,应用

11.5 不使用预编译头

12.配置imgui

12.1在D3D9HOOK目录下,新建imgui文件夹,将imgui-master中backends里imgui_impl_dx9.cpp、imgui_impl_dx9.h和imgui_impl_win32.cpp、imgui_impl_win32.h;及主目录下所有.cpp和.h都复制到imgui文件夹中

12.2新建筛选器,命名imgui

12.3在imgui中添加现有项,选定目录下所有文件

12.4.dllmain.h中包含导进来的所有头文件

13.主线程imgui窗口的实现

typedef HRESULT (WINAPI * FuncReset)(IDirect3DDevice9 *pIDirect3DDevice9,D3DPRESENT_PARAMETERS *pPresentationParameters);

typedef HRESULT (WINAPI *  FuncEndScene)(IDirect3DDevice9 *pIDirect3DDevice9);

typedef LRESULT(WINAPI * FuncWndProc)(const HWND, UINT, WPARAM, LPARAM);

HWND g_hWnd = NULL;

IDirect3D9 * g_IDirect3D9;

D3DPRESENT_PARAMETERS g_d3dpp;

IDirect3DDevice9* g_pIDirect3DDevice9;

FuncReset OldReset;

FuncEndScene OldEndScene;

FuncWndProc OldWndProc;

DWORD * dwDeviceVirtualTable = NULL;

extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

LRESULT WINAPI GrkWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

if (ImGui_ImplWin32_WndProcHandler(hWnd, message, wParam, lParam))

{

    return TRUE;

}

return CallWindowProc(OldWndProc, hWnd, message, wParam, lParam);

}

VOID StartHook(PVOID * OldFunctionAddr, PVOID NewFunctionAddr)

{

DetourTransactionBegin();

DetourUpdateThread(GetCurrentThread());

DetourAttach(OldFunctionAddr, NewFunctionAddr);

DetourTransactionCommit();

}

VOID UnHook(PVOID * OldFunctionAddr, PVOID NewFunctionAddr)

{

DetourTransactionBegin();

DetourUpdateThread(GetCurrentThread());

DetourDetach(OldFunctionAddr, NewFunctionAddr);

DetourTransactionCommit();

}

HRESULT WINAPI GrkReset(IDirect3DDevice9 *pIDirect3DDevice9, D3DPRESENT_PARAMETERS *d3dpp)

{

UnHook((PVOID*)(&OldReset), GrkReset);

ImGui_ImplDX9_InvalidateDeviceObjects();

HRESULT bRet = pIDirect3DDevice9->Reset(d3dpp);

ImGui_ImplDX9_CreateDeviceObjects();

StartHook((PVOID*)(&OldReset), GrkReset);

return bRet;

}

HRESULT WINAPI GrkEndScene(IDirect3DDevice9 *pIDirect3DDevice9)

{

UnHook((PVOID*)(&OldEndScene), GrkEndScene);

static bool bFlag = TRUE;

if (bFlag)

{

    bFlag = FALSE;

    IMGUI_CHECKVERSION();

    ImGui::CreateContext();

    ImGuiIO & io = ImGui::GetIO();

    io.ConfigFlags = ImGuiConfigFlags_NoMouseCursorChange;

    io.WantSaveIniSettings = false;

    io.IniFilename = NULL;

    ImGui::StyleColorsClassic();

    ImFontConfig imfConfig;

    imfConfig.FontDataOwnedByAtlas = false;

    ImGui_ImplWin32_Init(g_hWnd);

    ImGui_ImplDX9_Init(pIDirect3DDevice9);

    OldWndProc = (WNDPROC)SetWindowLongPtr(g_hWnd, GWL_WNDPROC, (LONG_PTR)GrkWndProc);

}

HRESULT hRet = pIDirect3DDevice9->EndScene();

ImGui_ImplDX9_NewFrame();

ImGui_ImplWin32_NewFrame();

ImGui::NewFrame();

ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_FirstUseEver);

ImGui::SetNextWindowSize(ImVec2(300, 300));

ImGui::Begin("GrkTools");

ImGui::End();

ImGui::EndFrame();

ImGui::Render();

ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());

StartHook((PVOID*)(&OldEndScene), GrkEndScene);

return hRet;

}

DWORD WindowThreadCallBack(LPVOID lpBuffer)

{

g_hWnd = FindWindowA("Direct3DWindowClass", NULL);

g_IDirect3D9 = Direct3DCreate9(D3D_SDK_VERSION);

memset(&g_d3dpp, 0, sizeof(g_d3dpp));

g_d3dpp.Windowed = TRUE;

g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

g_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

g_d3dpp.EnableAutoDepthStencil = TRUE;

g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

HRESULT hRet = g_IDirect3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &g_d3dpp, &g_pIDirect3DDevice9);

dwDeviceVirtualTable = (DWORD *)*(DWORD *)g_pIDirect3DDevice9;

OldReset = (FuncReset)dwDeviceVirtualTable[16];

OldEndScene = (FuncEndScene)dwDeviceVirtualTable[42];

StartHook((PVOID*)(&OldReset), GrkReset);

StartHook((PVOID*)(&OldEndScene), GrkEndScene);

return 0;

}

BOOL APIENTRY DllMain( HMODULE hModule,

DWORD  ul_reason_for_call,

LPVOID lpReserved

)

{

switch (ul_reason_for_call)

{

case DLL_PROCESS_ATTACH:

    CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)WindowThreadCallBack, NULL, NULL, NULL);

    break;

case DLL_THREAD_ATTACH:

    break;

case DLL_THREAD_DETACH:

    break;

case DLL_PROCESS_DETACH:

break;

}

return TRUE;

}

14.测试

14.1打开文件夹,把动态链接库D3D9HOOK.dll粘贴到桌面上

14.2打开pick,启动代码注入器,将动态链接库D3D9HOOK.dll进行注入

测试成功:在pick左上角出现窗口<span

这样,就手动创建了一个基础的imgui的框架<span

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

图形编程丨图形绘制基础imgui篇—D3D9 HOOK 创建内部Imgui窗口 的相关文章

  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • SetCurrentDirectoryW 中的错误 206

    在我之后之前不清楚的问题 https stackoverflow com questions 44389617 long path name in setcurrentdirectoryw 我以某种方式能够创建一个具有长路径名的目录 但是
  • 类模板参数推导 - clang 和 gcc 不同

    下面的代码使用 gcc 编译 但不使用 clang 编译 https godbolt org z ttqGuL template
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 如何从 appsettings.json 文件中的对象数组读取值

    我的 appsettings json 文件 StudentBirthdays Anne 01 11 2000 Peter 29 07 2001 Jane 15 10 2001 John Not Mentioned 我有一个单独的配置类 p
  • 关于 C++ 转换:参数 1 从“[some_class]”到“[some_class]&”没有已知的转换

    我正在研究 C 并且遇到了一个错误 我不知道确切的原因 我已经找到了解决方案 但仍然想知道原因 class Base public void something Base b int main Base b b something Base
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • WPF/C# 将自定义对象列表数据绑定到列表框?

    我在将自定义对象列表的数据绑定到ListBox in WPF 这是自定义对象 public class FileItem public string Name get set public string Path get set 这是列表
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查
  • 混合 ExecutionContext.SuppressFlow 和任务时 AsyncLocal.Value 出现意外值

    在应用程序中 由于 AsyncLocal 的错误 意外值 我遇到了奇怪的行为 尽管我抑制了执行上下文的流程 但 AsyncLocal Value 属性有时不会在新生成的任务的执行范围内重置 下面我创建了一个最小的可重现示例来演示该问题 pr
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • C++ 中类级 new 删除运算符的线程安全

    我在我的一门课程中重新实现了新 删除运算符 现在我正在使我的代码成为多线程 并想了解这些运算符是否也需要线程安全 我在某处读到 Visual Studio 中默认的 new delete 运算符是线程安全的 但这对于我的类的自定义 new

随机推荐

  • 量子信息-学习记录13

    ch 13 量子计算机的物理实现 续 量子计算机的基本事实 定义 Q tau Q Q 是量子系统在抵抗量子噪声 并维持自身的量子特性时所能够持续的最短时间
  • kettle使用常见问题解决-03

    kettle使用常见问题解决 03 一 kettle资源库总是断开 报的错误信息如下 An error occured loading the directory tree from the repository Error comitti
  • 如何在屏幕上打印

    这是本人发的第一个博客 我想用写博客来回顾和复习本人学习c语言的过程 我们学习计算机语言是为让计算机完成一定的任务 而任务的结果是在屏幕上显示出来的 因此 我们要学习如何在屏幕上打印内容 include
  • SAP之FIORI(1)-绪论

    SAP之FIORI 1 绪论 web IDE的下载地址 https tools hana ondemand com sapui5 下载好运行之后orion exe之后登录网址 http localhost 8080 webide index
  • 全面解析JavaScript中对于字符串子串的查询方法

    一 基本应用场景 Q1 给定字符串a xxx 给定字符串b xxxxxx 判定a是否为b的子串 基础手写实现方法 function checkHas longStr shortStr for let i 0 i lt longStr len
  • 基于遗传算法GA算法优化BP神经网络(Python代码实现)

    一 概述 BP GA算法的设计 基于遗传算法的BP神经网络算法 以下简称BP GA 就是在BP神经网络的学习过程中 将权重和阀值描述为染色体 并选取适宜的适应函数 然后进行GA迭代 直到某种意义上的收敛 与普通BP学习算法相比 算法 BP一
  • redis 主从配置

    转 https blog csdn net github 26672553 article details 69568259 redis主从配置初步 2个节点主从 如果我们redis的压力很大 如果我们的并发高到我们读数据和写数据都有了很大
  • 二维码的生意几乎革掉了钱包的命

    刷脸支付无需结账台 无需手机 如果说说二维码让手机成为了钱包 那刷脸支付则索性让钱包这个东西都直接革掉 而这也点燃了国内的新零售浪潮 二维码 革命的祸首在移动支付普及 线上线下建立联系这件事上 二维码其实功不可没 在此之前 线上的归线上 线
  • Cmake 官方中文教程

    CMake官方教程 2018年04月03日 22 00 21 SoftGit 阅读数 23072 很好的一个官方教程翻译文档 CMake简介 CMake是一个跨平台的 开源的构建工具 cmake是makefile的上层工具 它们的目的正是为
  • Node js 项目启动报错,错误码,events.js:141,throw er; //Unhandled 'error' event,解决办法

    Node js 项目启动报错 错误码 events js 141 throw er Unhandled error event 解决办法 当我遇到这个问题的时候 我纠结了好半天 找了好多资料 都说是端口占用 必须杀死端口重新启动 确实是这样
  • 上架发布应用市场资料填写规则限制

    应用名称填写时 名字长度有没有限制呢 1 名称 1 字数限制 iOS 30 Android 64 2 应用市场显示的名称 2 副标题 1 字数限制 iOS 30 2 应用市场显示的副标题 宣传文本填写时 可以编写多少个字 1 字数限制 iO
  • 目标检测分块知识总结 2

    tags 目标检测 1 FSAF 论文题目 Feature Selective Anchor Free Module for Single Shot Object Detection 2019 文章主要解决在进行多尺度检测的时候 利用特征金
  • C语言数据类型32位和64位不同

    http blog csdn net kongdefei5000 article details 38866985 C语言编程需要注意的64位和32机器的区别 一 数据类型特别是int相关的类型在不同位数机器的平台下长度不同 C99标准并不
  • linux修改启动内核版本

    cd etc default sudo gedit grub 编辑grub文件 修改grub文件如下 GRUB DEFAULT 1 gt 9 其中 1 代表开机启动界面中 选择 Advancded options for Ubuntu 选项
  • 初学黑客攻防[1]--禁止其他电脑访问本地电脑的80端口

    首先 win10家庭版需添加 本地安全策略 后进行该练习 1 打开 记事本 输入以下代码 echo off pushd dp0 dir b SystemRoot servicing Packages Microsoft Windows Gr
  • xilinx axi_iic IP使用分享

    仿真环境 例化了两组axi iic 的IP 一个slv一个mst slv地址固定为0x33 7bit模式 iic总线速率为4000K 仿真发现每次只能发送3byte数据 和实际不符 仿真仅作参考 由于iic为双向端口 通过例化顶层将IO连接
  • rsync实时监控以及守护进程

    rsync守护进程模式 服务端的操作 1 安装 root backup yum install y rsync 2 修改配置文件 下面有配置文件详解 root m01 vim etc rsyncd conf uid rsync gid rs
  • 关于jax,tensorflow的安装详细教程

    jax在下面pycharm中有提示你在哪里下载 所以如果下次遇到有什么要下载的包都可以尝试这种方式去下载 在找找pycharm有没有提示 然后直接点网站看教程 这嘎是官网的教程 很详细 为了下载一个版本只有JAX的cpu 可能要用到当地的开
  • 第四章 云原生架构之Kubernetes基础知识

    1 K8S整体架构 1 1 概述 Kubernetes是一个可移植 可扩展的开源平台 用于管理容器化的工作负载和服务 简称 K8S K8S的本质是一组服务器集群 可以在对应服务器集群的每个节点上运行程序 来对节点中的容器进行管理 类似Mas
  • 图形编程丨图形绘制基础imgui篇—D3D9 HOOK 创建内部Imgui窗口

    作者 小阿栗 Imgui又称为Dear ImGui 它是与平台无关的C 轻量级跨平台图形界面库 没有任何第三方依赖 可以将Imgui的源码直接加到项目中使用 也可以编译成dll Imgui使用DX或者OpenGL进行界面渲染 Imgui主要