草庐IT

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

极安御信安全研究院 2023-07-30 原文

作者:小阿栗

 

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

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

  1. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  2. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  3. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  4. [Vuforia]二.3D物体识别 - 2

    之前说过10之后的版本没有3dScan了,所以还是9.8的版本或者之前更早的版本。 3d物体扫描需要先下载扫描的APK进行扫面。首先要在手机上装一个扫描程序,扫描现实中的三维物体,然后上传高通官网,在下载成UnityPackage类型让Unity能够使用这个扫描程序可以从高通官网上进行下载,是一个安卓程序。点到Tools往下滑,找到VuforiaObjectScanner下载后解压数据线连接手机,将apk文件拷入手机安装然后刚才解压文件中的Media文件夹打开,两个PDF图打印第一张A4-ObjectScanningTarget.pdf,主要是用来辅助扫描的。好了,接下来就是扫描三维物体。将瓶

  5. ruby-on-rails - 在所有延迟的作业之前 Hook - 2

    是否可以在所有delayed_job任务之前运行一个方法?基本上,我们试图确保每个运行delayed_job的服务器都有我们代码的最新实例,所以我们想运行一个方法来在每个作业运行之前检查它。(我们已经有了“check”方法并在别处使用它。问题只是关于如何从delayed_job中调用它。) 最佳答案 现在有一种官方方法可以通过插件来做到这一点。这篇博文通过示例清楚地描述了如何执行此操作http://www.salsify.com/blog/delayed-jobs-callbacks-and-hooks-in-rails(本文中描述

  6. ruby - 刚刚分配的变量是否有 ruby 钩子(Hook)? - 2

    这是我理想中想要的。用户做:a="hello"输出为Youjustallocated"a"!=>"Hello"顺序无关紧要,只要我能实现该消息即可。 最佳答案 不,没有直接的方法可以做到这一点,因为在执行代码之前,Ruby字节码编译器会丢弃局部变量名。YARV(MRI1.9.2中使用的RubyVM)提供的关于局部变量的唯一指令是getlocal和setlocal,它们都对整数索引进行操作,而不是变量名。以下是1.9.2源代码中insns.def的摘录:/****************************************

  7. python - Ruby 或 Python 的 3d 游戏引擎? - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于StackOverflow来说是偏离主题的,因为它们往往会吸引自以为是的答案和垃圾邮件。相反,describetheproblem以及迄今为止为解决该问题所做的工作。关闭9年前。Improvethisquestion是否有适用于这些的3d游戏引擎?

  8. ruby - 图形与 Prawn - 2

    寻找一个gem为prawn添加gtraphing功能,我找到了thisone但它似乎有点过时了。有没有更活跃的gem? 最佳答案 直接在Prawn内部绘图没有什么非常活跃的,但是Gruff是一个高度可配置的活跃gem,可以让你制作各种图表。事实上,prawn-graph基本上是gruff的包装器!我的建议是使用gruff生成所需的图表和图形,然后将它们作为图像嵌入到Prawn文档中。所以代码看起来像这样:g=Gruff::Line.new(400)g.title="TransparentBackground"g.theme={:co

  9. 【自动驾驶环境感知项目】——基于Paddle3D的点云障碍物检测 - 2

    文章目录1.自动驾驶实战:基于Paddle3D的点云障碍物检测1.1环境信息1.2准备点云数据1.3安装Paddle3D1.4模型训练1.5模型评估1.6模型导出1.7模型部署效果附录show_lidar_pred_on_image.py1.自动驾驶实战:基于Paddle3D的点云障碍物检测项目地址——自动驾驶实战:基于Paddle3D的点云障碍物检测课程地址——自动驾驶感知系统揭秘1.1环境信息硬件信息CPU:2核AI加速卡:v100总显存:16GB总内存:16GB总硬盘:100GB环境配置Python:3.7.4框架信息框架版本:PaddlePaddle2.4.0(项目默认框架版本为2.3

  10. ruby - 如何将 (pre/post)_install_hook 添加到 ruby​​ gems - 2

    我想在安装前使用geminstallsome-gem命令从ruby​​gems.org安装gem时执行一些代码。文档指出您可以使用http://docs.ruby-lang.org/en/2.2.0/Gem.htmlpre_installHook,如下所示:#Filelib/rubygems.rb,line724defself.pre_install(&hook)@pre_install_hooks文档进一步说明:RubyGemsdefaultsarestoredinrubygems/defaults.rb.Ifyou'repackagingRubyGemsorimplementing

随机推荐