ImGUI 是一个无任何第三方依赖的图形化界面组件,其支持多种绘图引擎,ImGUI可用于绘制辅助菜单功能,注入游戏内部方便快捷。

ImGUI下载:https://github.com/ocornut/imgui/releases/tag/v1.60

下载好以后用户需自行配置ImGUI到项目中,并配置D3Dx9开发工具包,此处的IMGUI需要取出imgui-1.60\examples\directx9_example里面的imgui_impl_dx9并放入根目录。

并将其导入到项目目录下,添加现有项,导入所有的包。

注入测试代码如下:

#include <Windows.h>
#include <d3dx9.h>
#include "imgui.h"
#include "imgui_impl_dx9.h"
#include "imgui_internal.h"
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma pack(push)
#pragma pack(1)
#ifndef _WIN64// 配置使用UTF8
#pragma execution_character_set("utf-8")struct JmpCode
{
private:const BYTE jmp;DWORD address;public:JmpCode(DWORD srcAddr, DWORD dstAddr): jmp(0xE9){setAddress(srcAddr, dstAddr);}void setAddress(DWORD srcAddr, DWORD dstAddr){address = dstAddr - srcAddr - sizeof(JmpCode);}
};
#else
struct JmpCode
{
private:BYTE jmp[6];uintptr_t address;public:JmpCode(uintptr_t srcAddr, uintptr_t dstAddr){static const BYTE JMP[] = { 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00 };memcpy(jmp, JMP, sizeof(jmp));setAddress(srcAddr, dstAddr);}void setAddress(uintptr_t srcAddr, uintptr_t dstAddr){address = dstAddr;}
};
#endif
#pragma pack(pop)// 修改函数前面5个字节实现跳转
void hook(void* originalFunction, void* hookFunction, BYTE* oldCode)
{JmpCode code((uintptr_t)originalFunction, (uintptr_t)hookFunction);DWORD oldProtect, oldProtect2;VirtualProtect(originalFunction, sizeof(code), PAGE_EXECUTE_READWRITE, &oldProtect);memcpy(oldCode, originalFunction, sizeof(code));memcpy(originalFunction, &code, sizeof(code));VirtualProtect(originalFunction, sizeof(code), oldProtect, &oldProtect2);
}void unhook(void* originalFunction, BYTE* oldCode)
{DWORD oldProtect, oldProtect2;VirtualProtect(originalFunction, sizeof(JmpCode), PAGE_EXECUTE_READWRITE, &oldProtect);memcpy(originalFunction, oldCode, sizeof(JmpCode));VirtualProtect(originalFunction, sizeof(JmpCode), oldProtect, &oldProtect2);
}void* endSceneAddr = NULL;
BYTE endSceneOldCode[sizeof(JmpCode)];// 窗口句柄
WNDPROC oWndProc = nullptr;
HWND Window = nullptr;// 是否第一次初始化
BOOL is_init = FALSE;// 单选框设置状态
bool show_another_window = false;// imgui 窗体消息用的 extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);// Imgui窗体消息循环LRESULT CALLBACK hkWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){switch (uMsg){case WM_KEYDOWN:switch (wParam){// 按下F9弹窗case VK_F9:MessageBox(0, 0, 0, 0);break;}break;}//消息 操作imgui用的if (ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam)) return 1;return CallWindowProc(oWndProc, hWnd, uMsg, wParam, lParam);}HRESULT STDMETHODCALLTYPE MyEndScene(IDirect3DDevice9* thiz)
{// 是否第一次执行if (is_init == FALSE){// 初始化ImGUI字体is_init = TRUE;ImGuiIO& io = ImGui::GetIO();io.DeltaTime = 1.0f / 60.0f;D3DDEVICE_CREATION_PARAMETERS d3dcp{ 0 };thiz->GetCreationParameters(&d3dcp);ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\simkai.ttf", 14.0f, NULL, io.Fonts->GetGlyphRangesChinese());ImGui_ImplDX9_Init(d3dcp.hFocusWindow, thiz);ImGui::StyleColorsDark();// 挂钩EndScene函数unhook(endSceneAddr, endSceneOldCode);HRESULT hr = thiz->EndScene();hook(endSceneAddr, MyEndScene, endSceneOldCode);return hr;}// -------------------------------------------------------------// Imgui绘制过程// 定义静态变量static float f = 0.0f;static int counter = 0;static char sz[256] = { 0 };ImGui_ImplDX9_NewFrame();ImGui::Begin("LyShark.com 辅助GUI主菜单");ImGui::Checkbox("弹出子窗口", &show_another_window);ImGui::SliderFloat("浮点条", &f, 0.0f, 1.0f);ImGui::InputText("输入内容", sz, 256, 0, 0, 0);if (ImGui::Button("点我触发")){counter++;}ImGui::SameLine();ImGui::Text("触发次数 = %d", counter);ImGui::Text("当前FPS: %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);ImGui::End();// 子窗体菜单if (show_another_window){ImGui::Begin("我是子窗体", &show_another_window);ImGui::Text(" 您好,LyShark, 这是一个测试窗体 !");// 按钮状态if (ImGui::Button("关闭窗体")){show_another_window = false;}ImGui::End();}ImGui::EndFrame();// 把imgui东西刷新上去ImGui::Render();ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());// 结束绘制,取消hookunhook(endSceneAddr, endSceneOldCode);HRESULT hr = thiz->EndScene();hook(endSceneAddr, MyEndScene, endSceneOldCode);return hr;
}// 该函数作用是得到endSceneAddr地址
DWORD WINAPI initHookThread(LPVOID dllMainThread)
{WaitForSingleObject(dllMainThread, INFINITE);CloseHandle(dllMainThread);WNDCLASSEX wc = {};wc.cbSize = sizeof(wc);wc.style = CS_OWNDC;wc.hInstance = GetModuleHandle(NULL);wc.lpfnWndProc = DefWindowProc;wc.lpszClassName = L"Window";if (RegisterClassEx(&wc) == 0){return 0;}HWND hwnd = CreateWindowEx(0, wc.lpszClassName, L"", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, NULL, NULL, wc.hInstance, NULL);if (hwnd == NULL){return 0;}// 初始化D3DIDirect3D9* d3d9 = Direct3DCreate9(D3D_SDK_VERSION);if (d3d9 == NULL){DestroyWindow(hwnd);return 0;}D3DPRESENT_PARAMETERS pp = {};pp.Windowed = TRUE;pp.SwapEffect = D3DSWAPEFFECT_COPY;IDirect3DDevice9* device;if (FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &pp, &device))){d3d9->Release();DestroyWindow(hwnd);return 0;}// hook EndScene// EndScene是IDirect3DDevice9第43个函数endSceneAddr = (*(void***)device)[42];hook(endSceneAddr, MyEndScene, endSceneOldCode);// 释放d3d9->Release();device->Release();DestroyWindow(hwnd);return 0;
}BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{DWORD dwCurProcessId = *((DWORD*)lParam);DWORD dwProcessId = 0;GetWindowThreadProcessId(hwnd, &dwProcessId);if (dwProcessId == dwCurProcessId && GetParent(hwnd) == NULL){*((HWND *)lParam) = hwnd;return FALSE;}return TRUE;
}HWND GetMainWindow()
{DWORD dwCurrentProcessId = GetCurrentProcessId();if (!EnumWindows(EnumWindowsProc, (LPARAM)&dwCurrentProcessId)){return (HWND)dwCurrentProcessId;}return NULL;
}// dll 入口
BOOL APIENTRY DllMain(HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)
{switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:// 获取自身线程句柄HANDLE curThread;if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &curThread, SYNCHRONIZE, FALSE, 0))return FALSE;// 在另一个线程初始化COM组件CloseHandle(CreateThread(NULL, 0, initHookThread, curThread, 0, NULL));// 获取自身进程窗口句柄Window  = GetMainWindow();// 设置窗口循环消息oWndProc = (WNDPROC)SetWindowLongA(Window, GWL_WNDPROC, (LONG)hkWndProc);if (oWndProc == nullptr)return 1;// 创建IMGUI上下文ImGui::CreateContext();break;case DLL_PROCESS_DETACH:if (endSceneAddr != NULL)unhook(endSceneAddr, endSceneOldCode);break;break;case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:break;}return TRUE;
}

打开一个带有Dx9引擎的图形化界面,并将生成的DLL注入到游戏内,即可弹出内部GUI菜单。

C/C++ ImGUI劫持Dx9绘制窗体相关推荐

  1. ImGUI 1.87 绘制D3D外部菜单

    ImGUI 它是与平台无关的C++轻量级跨平台图形界面库,没有任何第三方依赖,可以将ImGUI的源码直接加到项目中使用,该框架通常会配合特定的D3Dx9等图形开发工具包一起使用,ImGUI常用来实现进 ...

  2. DX9绘制虚线抗锯齿线-------VB6编程学习DX9游戏编程DirectX9编程2D小游戏源码冷风引擎CoolWind2D游戏引擎(13)

    DX9绘制虚线抗锯齿线 划线扩展 绘制划线的实际效果图如下: 新建一个Form1,代码如下: Private Sub Form_Load()'新手注意:游戏编程中, '通常将窗体的 BorderSty ...

  3. c# 窗体控件上绘制跟随鼠标的十字线

    一.技术路线 (1)以自定义大小的image为画布,绘制窗体控件显示的主题内容 public Image img=new Bitmap(250,250);   //定义img Graphics gr ...

  4. swing 圆角按钮_JFrame实现圆角窗体

    现在开发一个窗体程序,经常要求用圆角窗体.而在Windows 经典外观下,直接写出来的窗体却是方型的.在windows 7.windows server2008 的外观下,就已经是圆角的了. 这里我们 ...

  5. 【转】【C#】C#重绘windows窗体标题栏和边框

    摘要 windows桌面应用程序都有标准的标题栏和边框,大部分程序也默认使用这些样式,一些对视觉效果要求较高的程序,如QQ, MSN,迅雷等聊天工具的样式则与传统的windows程序大不相同,其中迅雷 ...

  6. .NET 不规则、可改变大小、边框半透明窗体设计

    做.NET WinForm的开发也有一段时间了,对.NET的界面设计也有了一定的了解.自认为自己学的这些东西都是网上看高手们的东西后总结出来的,第一次把这些东西写出来. 不好的地方请大家多多指教. 大 ...

  7. 一种用户体验-显示对话框时灰化你的主窗体

    袁永福 ( http://www.xdesigner.cn ) 2007-8-10 程序全部源代码下载(工程文件使用VS.NET2003格式):/Files/xdesigner/DisableMask ...

  8. delphi 窗体透明详解TransparentColorValue,窗体透明控件不透明

    关于窗体透明的做法 来自:http://blog.csdn.net/shuaihj/article/details/8610343 关于窗体透明的做法 1.在Delphi中,设置窗体的AlphaBle ...

  9. java k线绘制,用Java绘制K线图[Java编程]

    赞助商链接 本文"用Java绘制K线图[Java编程]"是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具 ...

最新文章

  1. THE发布世界大学声誉排名,清华位居全球前10
  2. IOS15.0的适配
  3. 优秀工程师应该具备哪些素质_一名优秀工程师所需要具备的条件和素质[1]
  4. 使用Spring Data Redis进行缓存
  5. swift 滑动 iphone解锁_这10个iPhone隐藏功能,我就不信你全知道
  6. java集合进行排序的两种方式
  7. bzoj 2882: 工艺【SAM】
  8. python小测验3_python基础小测试
  9. SpringBoot酒店管理系统 hotel.liuyanzhao.com
  10. Word转PDF怎么转?三种方法快速学会
  11. 【微信小程序】体验版获取不到接口数据
  12. python判断图像是否为灰度图
  13. JQuery验证车牌号(含新能源车牌)
  14. 日记app怎么上传录制的视频
  15. 影集制作php源码_最新仿720全景在线制作云平台网站PHP源码
  16. 关于iPhone尺寸与分辨率
  17. 数学分析第一型曲面积分2021.6.5
  18. 6.6 在图表上显示最大值和最小值 [原创Excel教程]
  19. 北欧的Michael Learns To Rock的一首清澈见底的【Take Me To Your Heart】
  20. Three.js 后期处理-物体边界线条高亮处理-OutlinePass

热门文章

  1. ECE220生存指南[01]: MP6,从RGB到HSL
  2. PPT更改对象自定义动画出现的顺序
  3. 大家都是怎么样去做销售的
  4. P2345 奶牛集会
  5. html中背景条纹效果,css 条纹背景效果
  6. 乘着绘本的翅膀开启阅读之旅
  7. ECS搭建nginx服务器在阿里云
  8. ui字体 pt 和 前端字体 px 之间的转化
  9. 通过Python的列表、while循环,穷举法解决农夫过河问题
  10. 2022中国五金制品行业发展前景分析