基于DirectX11+ImGui的Win32桌面程序开发

打印 上一主题 下一主题

主题 918|帖子 918|积分 2754

一、常见图形界面框架(DirectUI、GUI)

1.题外话,纯属扯O

举两个常用的开发框架,MFC和Qt Widget里面每个控件都是Window,这是和DirectUI最大的区别。下面简单梳理下这个DirectUI与GUI之前错综复杂的爱恨情仇:
① 在侏罗纪时期,传统的Handle式GUI框架,是由操作系统内核(win32k.sys)直接提供的接口(GDI),采用消息驱动的机制。窗口在Windows 操作系统中可以分为两种类型:一般窗口(Top-level Window)和子窗口(Child Window)。每一个窗口都会有一个系统全局标识符,也就是所谓的窗口句柄,由系统管理,每个窗口都会有独立的操作流程,用于处理消息的消息队列,循环处理系统发过来的窗口消息,例如当鼠标点击一个按钮的时候,操作系统会捕获鼠标消息,发送给对应窗口,通知窗口依据对应操作做出相对应的改变,重新绘制外观,发送一个按钮被点击的事件,也就是到了此时,用户才介入这个过程,进行按钮被点击之后的业务处理,窗口之间经过消息传递,然后经过一系列接口调用,最终反馈给用户呈现,窗口最终归属还是系统资源,用户层面无法窥探内部细节,仅仅是通过提供的接口进行调用操作,主打陪伴。
② 随着第四次科技革命的崛起,某岛核泄漏事件的发展,人们不再满足于单纯的功能界面,一群追求高颜值、高性能、高DIY的用户呐喊 "Please help me",微软推出了DirectUI框架,采用DirectUI开发的应用程序,简单总结来说,就是除了顶级父窗口由操作系统负责,其余所有窗口全部由自己绘制,自己处理消息事件,窗口仅仅相当于一个容器,界面上的元素都属于一个逻辑区域,你问我什么是DirectUI?系统管得了的我要管,系统管不了的我也要管,先绘后渲,随心所欲,这就是DirectUI思想。
二、ImGui基本情况

1.什么是ImGui?

① ImGUI又称为Dear ImGui,它是一个跨平台、无第三方依赖的C++轻量级跨平台图形界面库,在项目中,可以直接引用ImGUI的源码,也可以编译成lib、dll等, ImGUI常使用DirectX或者OpenGL进行界面渲染,优点:性能高,快,实现简单等。缺点:布局有点复杂、字体支持不友好,不能动态加载等.
② 初步总结上面的话,可以大概理解为性能很好,入门简单,精通很难.需要非常熟悉DirectX或者OpenGL.但基础已经可以满足大多数人的需求了.
闲聊:谈谈ImGui与DirectUI之间,有部分相同点,比如依赖DirectX渲染绘制等,但不同点也很明显,ImGui 并不直接依赖于特定的操作系统或图形API,而是通过底层的图形渲染接口来绘制图形。这意味着 ImGui 可以在多个平台(如Windows、Linux、Mac等)和多个图形API(如DirectX、OpenGL、Vulkan等)上使用。在IMGUI中,用户界面每帧都是从代码中绘制的,而不是通过构建和维护UI元素的树形结构。这种即时模式的方法提供了更直接、更灵活的控制权,尤其适用于需要频繁更新和自定义的应用程序。
2.DirectX又是什么东西?

① DirectX 是微软公司开发的一套多媒体编程接口,用于在 Windows 平台上实现硬件加速的图形和音频功能。DirectX 提供了多个组件,其中包括了 Direct2D、Direct3D、DirectSound、DirectInput 等。它们分别用于2D图形渲染、3D图形渲染、音频处理和输入设备管理等领域。...  官话我也就不重复描述了,并非三言两语解释清除,详细了解的可以深度学习这个。
三、简单程序开发

1.开发前的小准备

① 下载 docking imgui 地址: https://github.com/ocornut/imgui/tree/docking
② 使用Visual Studio X创建一个空项目,打开解决方案根目录,创建文件夹,ImGui,Directx,如图所示

③ 打开下载的ImGui-docking压缩包,拷贝根目录如图所示文件,到刚才项目创建的文件夹"ImGui"下;

 ④ 拷贝***\imgui-docking\backends文件夹下的如图所示文件,至项目根目录文件夹Directx下;
(1

(2

⑤ 拷贝完成后,现有文件夹下文件如下图所示:

2.开始开发,撸起来.

① 创建main.cpp文件,创建基础测试代码,下面代码已经经过初步修改,修改范围:
(1.初始化屏蔽控制台,添加#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" ) 
  (2屏蔽Win32窗口,修改::ShowWindow(hwnd, SW_HIDE);
  (3.分离绘制,修改,io.ConfigViewportsNoAutoMerge = true;
  (4.关闭垂直同步,g_pSwapChain->Present(0, 0);
  (5.增加ImGui对汉字的支持,添加 io.Fonts->AddFontFromFileTTF("C:/Windows/Fonts/SimHei.ttf", 14.0f, NULL, io.Fonts->GetGlyphRangesChineseFull());由于ImGui不支持动态加载,由此会引发内存异常的大....
下面代码里面包含了一些常见组件的使用,官方里面也有例子,具体还需要参照Demo程序慢慢学习.
  1.   1 #include "imgui.h"
  2.   2 #include "imgui_impl_win32.h"
  3.   3 #include "imgui_impl_dx11.h"
  4.   4 #include <d3d11.h>
  5.   5 #include <tchar.h>
  6.   6 #include <random>
  7.   7 #include <ctime>
  8.   8 #include <iostream>
  9.   9 using namespace std;
  10. 10
  11. 11 #pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )//屏蔽控制台显示,编译后生效.
  12. 12
  13. 13 // Data
  14. 14 static ID3D11Device* g_pd3dDevice = nullptr;
  15. 15 static ID3D11DeviceContext* g_pd3dDeviceContext = nullptr;
  16. 16 static IDXGISwapChain* g_pSwapChain = nullptr;
  17. 17 static UINT                     g_ResizeWidth = 0, g_ResizeHeight = 0;
  18. 18 static ID3D11RenderTargetView* g_mainRenderTargetView = nullptr;
  19. 19
  20. 20 // 助手函数的声明
  21. 21 bool CreateDeviceD3D(HWND hWnd);
  22. 22 void CleanupDeviceD3D();
  23. 23 void CreateRenderTarget();
  24. 24 void CleanupRenderTarget();
  25. 25 LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
  26. 26
  27. 27 std::string string_to_utf8(const std::string& str)
  28. 28 {
  29. 29     int nwLen = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
  30. 30     wchar_t* pwBuf = new wchar_t[nwLen + 1];
  31. 31     memset(pwBuf, 0, nwLen * 2 + 2);
  32. 32     MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), pwBuf, nwLen);
  33. 33
  34. 34     int nLen = WideCharToMultiByte(CP_UTF8, 0, pwBuf, -1, NULL, NULL, NULL, NULL);
  35. 35     char* pBuf = new char[nLen + 1];
  36. 36     memset(pBuf, 0, nLen + 1);
  37. 37     WideCharToMultiByte(CP_UTF8, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);
  38. 38
  39. 39     std::string ret = pBuf;
  40. 40     delete[]pwBuf;
  41. 41     delete[]pBuf;
  42. 42
  43. 43     return ret;
  44. 44 }
  45. 45
  46. 46 int main(int, char**)
  47. 47 {
  48. 48     // 创建应用程序窗口
  49. 49     //ImGui_ImplWin32_EnableDpiAwareness();
  50. 50     WNDCLASSEXW wc = { sizeof(wc), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, L"demo", nullptr };
  51. 51     ::RegisterClassExW(&wc);
  52. 52     HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"demo", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, nullptr, nullptr, wc.hInstance, nullptr);
  53. 53
  54. 54     // 初始化 Direct3D
  55. 55     if (!CreateDeviceD3D(hwnd))
  56. 56     {
  57. 57         CleanupDeviceD3D();
  58. 58         ::UnregisterClassW(wc.lpszClassName, wc.hInstance);
  59. 59         return 1;
  60. 60     }
  61. 61
  62. 62     // 设置窗口显示模式
  63. 63     ::ShowWindow(hwnd, SW_HIDE);
  64. 64     ::UpdateWindow(hwnd);
  65. 65
  66. 66     // 设置ImGui上下文
  67. 67     IMGUI_CHECKVERSION();
  68. 68     ImGui::CreateContext();
  69. 69     ImGuiIO& io = ImGui::GetIO(); (void)io;
  70. 70     //取消生成ini文件
  71. 71     io.IniFilename = NULL;
  72. 72     io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // 启用键盘控制
  73. 73     io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // 启用游戏板控制
  74. 74     io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;         // 启用停靠
  75. 75     io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;       // 启用多视口/平台窗口
  76. 76     io.ConfigViewportsNoAutoMerge = true;
  77. 77     //io.ConfigViewportsNoTaskBarIcon = true;
  78. 78     //io.ConfigViewportsNoDefaultParent = true;
  79. 79     //io.ConfigDockingAlwaysTabBar = true;
  80. 80     //io.ConfigDockingTransparentPayload = true;
  81. 81     //io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleFonts;     // FIXME-DPI:实验。这目前没有按预期工作。不要使用用户内应用程序!
  82. 82     //io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleViewports; // FIXME-DPI:实验。
  83. 83
  84. 84     // 设置ImGui风格
  85. 85     ImGui::StyleColorsLight();
  86. 86
  87. 87     // 启用视口后,我们调整WindowRounding/WindowBg,使平台窗口看起来与常规窗口相同。
  88. 88
  89. 89     ImGuiStyle& style = ImGui::GetStyle();
  90. 90     if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
  91. 91     {
  92. 92         style.WindowMinSize = ImVec2(700, 180);
  93. 93
  94. 94         style.WindowRounding = 10.0f;
  95. 95         style.Colors[ImGuiCol_WindowBg].w = 1.0f;
  96. 96
  97. 97         style.WindowBorderSize = 1.0f;
  98. 98         style.FrameBorderSize = 1.0f;
  99. 99         style.PopupBorderSize = 1.0f;
  100. 100
  101. 101         style.WindowPadding = ImVec2(8.0f, 8.0f);
  102. 102         style.FramePadding = ImVec2(4.0f, 8.0f);
  103. 103         style.PopupBorderSize = 1.0f;
  104. 104
  105. 105     }
  106. 106
  107. 107     // 设置平台/渲染器后端
  108. 108     ImGui_ImplWin32_Init(hwnd);
  109. 109     ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
  110. 110
  111. 111     //加载字体
  112. 112     //-如果没有加载字体,imgui将使用默认字体。您还可以加载多种字体,并使用ImGui::PushFont()/PopFont 选择它们
  113. 113     //-AddFontFromFileTTF()将返回ImFont*,因此如果需要在多个字体中选择字体,则可以存储它。
  114. 114     //-如果无法加载文件,则函数将返回一个nullptr。请处理应用程序中的这些错误(例如,使用断言,或显示错误并退出)。
  115. 115     //-当调用ImFontAtlas::Build()/GetTexDataAsXXXXX()时,字体将以给定的大小光栅化(w/过采样)并存储到纹理中,下面的ImGui_ImplXXXX_NewFrame将调用该纹理。
  116. 116     //-在您的imconfig文件中使用“#define IMGUI_ABLE_FREETYPE”可以使用FREETYPE进行更高质量的字体渲染。
  117. 117     //-有关更多说明和详细信息,请阅读“docs/FONTS.md”。
  118. 118     //-请记住,在C/C++中,如果要在字符串文字中包含反斜杠,则需要写一个双反斜杠\\
  119. 119     io.Fonts->AddFontFromFileTTF("C:/Windows/Fonts/SimHei.ttf", 14.0f, NULL, io.Fonts->GetGlyphRangesChineseFull());//支持汉字,单目前Ingui不支持动态,所以在调试模式下启动会变慢,改字体也会占用大量内存.
  120. 120
  121. 121     // 窗口设置
  122. 122     bool show_main_windows = true;
  123. 123     bool WindowShouldClose = false;
  124. 124
  125. 125     ImGui::SetNextWindowSize(ImVec2(700, 180), ImGuiCond_Appearing);
  126. 126
  127. 127     // 创建计时器变量
  128. 128     auto startTime = std::chrono::steady_clock::now();
  129. 129     while (!WindowShouldClose)
  130. 130     {
  131. 131         //轮询和处理消息(输入、窗口大小调整等)
  132. 132         //请参阅下面的WndProc()函数,了解如何将事件调度到Win32后端。
  133. 133         MSG msg;
  134. 134         while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE))
  135. 135         {
  136. 136             ::TranslateMessage(&msg);
  137. 137             ::DispatchMessage(&msg);
  138. 138             if (msg.message == WM_QUIT)
  139. 139                 WindowShouldClose = true;
  140. 140         }
  141. 141         if (WindowShouldClose)
  142. 142             break;
  143. 143
  144. 144         //处理窗口大小调整(我们不直接在WM_SIZE处理程序中调整大小)
  145. 145         if (g_ResizeWidth != 0 && g_ResizeHeight != 0)
  146. 146         {
  147. 147             CleanupRenderTarget();
  148. 148             g_pSwapChain->ResizeBuffers(0, g_ResizeWidth, g_ResizeHeight, DXGI_FORMAT_UNKNOWN, 0);
  149. 149             g_ResizeWidth = g_ResizeHeight = 0;
  150. 150             CreateRenderTarget();
  151. 151         }
  152. 152
  153. 153         // 启动ImGui框架
  154. 154         ImGui_ImplDX11_NewFrame();
  155. 155         ImGui_ImplWin32_NewFrame();
  156. 156         ImGui::NewFrame();
  157. 157
  158. 158         if (show_main_windows)
  159. 159         {
  160. 160             ImGui::Begin(u8"测试基础客户端", &show_main_windows);
  161. 161             std::random_device rd;
  162. 162             std::mt19937 gen(rd());
  163. 163             std::uniform_real_distribution<float> dis(0.0f, 1.0f);
  164. 164             ImVec4 randomColor(dis(gen), dis(gen), dis(gen), 1.0f);
  165. 165             ImGui::TextWrapped(u8"****");
  166. 166             ImGui::SameLine();
  167. 167             ImGui::PushStyleColor(ImGuiCol_Text, randomColor);
  168. 168             ImGui::SetCursorPosX((ImGui::GetCursorPosX() + ImGui::GetColumnWidth() - ImGui::CalcTextSize(u8"模拟客户端(特效)").x) / 2);
  169. 169             ImGui::TextWrapped(u8"模拟客户端(特效)");
  170. 170             ImGui::PopStyleColor();
  171. 171             ImGui::SameLine();
  172. 172             ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetColumnWidth() - ImGui::CalcTextSize(u8"****").x);
  173. 173             ImGui::TextWrapped(u8"****");
  174. 174             ImGui::SeparatorText(u8"画一条分界线");
  175. 175
  176. 176             ImGui::Text("");
  177. 177
  178. 178             randomColor.x = 1.0f;
  179. 179             randomColor.y = 0.0f;
  180. 180             randomColor.z = 1.0f;
  181. 181             ImGui::PushStyleColor(ImGuiCol_Text, randomColor);
  182. 182             if (GetDriverState())
  183. 183             {
  184. 184                 ImGui::SetCursorPosX((ImGui::GetCursorPosX() + ImGui::GetColumnWidth() - ImGui::CalcTextSize(u8"换个颜色").x) / 2);
  185. 185                 ImGui::TextWrapped(u8"换个颜色");
  186. 186             }
  187. 187             else
  188. 188             {
  189. 189                 ImGui::SetCursorPosX((ImGui::GetCursorPosX() + ImGui::GetColumnWidth() - ImGui::CalcTextSize(u8"再换个颜色·").x) / 2);
  190. 190                 ImGui::TextWrapped(u8"再换个颜色·");
  191. 191             }
  192. 192             ImGui::PopStyleColor();
  193. 193             ImGui::SeparatorText(u8"");
  194. 194
  195. 195             // 计算运行时间
  196. 196             auto currentTime = std::chrono::steady_clock::now();
  197. 197             std::chrono::duration<float> elapsedTime = currentTime - startTime;
  198. 198             float runtime = elapsedTime.count();
  199. 199
  200. 200             // 获取当前时间
  201. 201             std::time_t now = std::time(nullptr);
  202. 202             std::tm* current_time = std::localtime(&now);
  203. 203             static char time_string[64] = { 0 };
  204. 204             std::strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", current_time);
  205. 205
  206. 206             ImGui::TextColored(ImVec4(0.45f, 0.0f, 1.0f, 1.0f), u8"当前时间:%s,软件已运行: %.2f秒.", time_string, runtime);
  207. 207             ImGui::End();
  208. 208         }
  209. 209         else
  210. 210         {
  211. 211             WindowShouldClose = TRUE;
  212. 212         }
  213. 213
  214. 214         // 渲染页面
  215. 215         ImGui::Render();
  216. 216         ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
  217. 217
  218. 218         // 更新和渲染其他平台窗口
  219. 219         if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
  220. 220         {
  221. 221             ImGui::UpdatePlatformWindows();
  222. 222             ImGui::RenderPlatformWindowsDefault();
  223. 223         }
  224. 224
  225. 225         //g_pSwapChain->Present(1, 0); // 与vsync一起演示
  226. 226         g_pSwapChain->Present(0, 0); // 存在但不带vsync
  227. 227     }
  228. 228
  229. 229
  230. 230     ImGui_ImplDX11_Shutdown();
  231. 231     ImGui_ImplWin32_Shutdown();
  232. 232     ImGui::DestroyContext();
  233. 233
  234. 234     CleanupDeviceD3D();
  235. 235     ::DestroyWindow(hwnd);
  236. 236     ::UnregisterClassW(wc.lpszClassName, wc.hInstance);
  237. 237
  238. 238     return 0;
  239. 239 }
  240. 240
  241. 241 // 帮助函数
  242. 242 bool CreateDeviceD3D(HWND hWnd)
  243. 243 {
  244. 244     // 设置交换链
  245. 245     DXGI_SWAP_CHAIN_DESC sd;
  246. 246     ZeroMemory(&sd, sizeof(sd));
  247. 247     sd.BufferCount = 2;
  248. 248     sd.BufferDesc.Width = 0;
  249. 249     sd.BufferDesc.Height = 0;
  250. 250     sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
  251. 251     sd.BufferDesc.RefreshRate.Numerator = 60;
  252. 252     sd.BufferDesc.RefreshRate.Denominator = 1;
  253. 253     sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
  254. 254     sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  255. 255     sd.OutputWindow = hWnd;
  256. 256     sd.SampleDesc.Count = 1;
  257. 257     sd.SampleDesc.Quality = 0;
  258. 258     sd.Windowed = TRUE;
  259. 259     sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
  260. 260
  261. 261     UINT createDeviceFlags = 0;
  262. 262     //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
  263. 263     D3D_FEATURE_LEVEL featureLevel;
  264. 264     const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
  265. 265     HRESULT res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
  266. 266     if (res == DXGI_ERROR_UNSUPPORTED) // 如果硬件不可用,请尝试高性能的WARP软件驱动程序。
  267. 267         res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_WARP, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
  268. 268     if (res != S_OK)
  269. 269         return false;
  270. 270
  271. 271     CreateRenderTarget();
  272. 272     return true;
  273. 273 }
  274. 274
  275. 275 void CleanupDeviceD3D()
  276. 276 {
  277. 277     CleanupRenderTarget();
  278. 278     if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = nullptr; }
  279. 279     if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = nullptr; }
  280. 280     if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = nullptr; }
  281. 281 }
  282. 282
  283. 283 void CreateRenderTarget()
  284. 284 {
  285. 285     ID3D11Texture2D* pBackBuffer;
  286. 286     g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
  287. 287     g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_mainRenderTargetView);
  288. 288     pBackBuffer->Release();
  289. 289 }
  290. 290
  291. 291 void CleanupRenderTarget()
  292. 292 {
  293. 293     if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = nullptr; }
  294. 294 }
  295. 295
  296. 296 #ifndef WM_DPICHANGED
  297. 297 #define WM_DPICHANGED 0x02E0 // From Windows SDK 8.1+ headers
  298. 298 #endif
  299. 299
  300. 300 // 从imgui_impl_win32.cpp转发声明消息处理程序
  301. 301 extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
  302. 302
  303. 303 //Win32消息处理程序
  304. 304 //你可以阅读io.WantCaptureMouse,io.WantCaptureKeyboard标志来判断imgui是否想使用你的输入。
  305. 305 //-当io.WantCaptureMouse为true时,不要将鼠标输入数据发送到主应用程序,也不要清除/覆盖鼠标数据的副本。
  306. 306 //-当io.WantCaptureKeyboard为true时,不要将键盘输入数据发送到主应用程序,也不要清除/覆盖键盘数据的副本。
  307. 307 //通常情况下,您可能总是将所有输入传递给imgui,并根据这两个标志对应用程序隐藏它们。
  308. 308 LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  309. 309 {
  310. 310     if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
  311. 311         return true;
  312. 312
  313. 313     switch (msg)
  314. 314     {
  315. 315     case WM_SIZE:
  316. 316         if (wParam == SIZE_MINIMIZED)
  317. 317             return 0;
  318. 318         g_ResizeWidth = (UINT)LOWORD(lParam); // 调整队列大小
  319. 319         g_ResizeHeight = (UINT)HIWORD(lParam);
  320. 320         return 0;
  321. 321     case WM_SYSCOMMAND:
  322. 322         if ((wParam & 0xfff0) == SC_KEYMENU) // 禁用ALT应用程序菜单
  323. 323             return 0;
  324. 324         break;
  325. 325     case WM_DESTROY:
  326. 326         ::PostQuitMessage(0);
  327. 327         return 0;
  328. 328     case WM_DPICHANGED:
  329. 329         if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_DpiEnableScaleViewports)
  330. 330         {
  331. 331             //const int dpi = HIWORD(wParam);
  332. 332             //printf("WM_DPICHANGED to %d (%.0f%%)\n", dpi, (float)dpi / 96.0f * 100.0f);
  333. 333             const RECT* suggested_rect = (RECT*)lParam;
  334. 334             ::SetWindowPos(hWnd, nullptr, suggested_rect->left, suggested_rect->top, suggested_rect->right - suggested_rect->left, suggested_rect->bottom - suggested_rect->top, SWP_NOZORDER | SWP_NOACTIVATE);
  335. 335         }
  336. 336         break;
  337. 337     }
  338. 338     return ::DefWindowProcW(hWnd, msg, wParam, lParam);
  339. 339 }
复制代码
 ② 补齐环境引用,VS右键项目属性:
(1.C++\常规\附加包含目录 添加 .\Imgui;.\Directx;
(2.链接器\输入\依赖性  添加 d3d11.lib;d3dcompiler.lib;dxgi.lib;
3.开发完跑跑试试

 ① 编译运行,附上效果图(自己改改文字即可实现.):

 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

乌市泽哥

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表