Imported Dear ImGui

This commit is contained in:
2025-11-10 18:54:24 +08:00
parent cf3cbaead9
commit d7a3083816
261 changed files with 132529 additions and 206 deletions
+10
View File
@@ -0,0 +1,10 @@
#include "Global_Variables.hpp"
// D3D11 相关
ID3D11Device *g_pd3dDevice = nullptr; // D3D11 设备句柄
ID3D11DeviceContext *g_pd3dDeviceContext = nullptr; // D3D11 设备上下文句柄
IDXGISwapChain *g_pSwapChain = nullptr; // DXGI 交换链句柄
bool g_SwapChainOccluded = false; // 交换链是否阻塞
ID3D11RenderTargetView *g_mainRenderTargetView = nullptr; // D3D11 渲染目标
+351 -202
View File
@@ -1,213 +1,362 @@
#include "iostream"
// IMGUI相关库包含
#include "imgui.h"
#include "imgui_impl_win32.h"
#include "imgui_impl_dx11.h"
extern "C"
{
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
// Mingw 相关库
#include "d3d11.h"
#include "tchar.h"
#include "wchar.h"
// 自定义头文件
#include "Global_Variables.hpp"
}
#define SEGMENT_BUFF_LENTH 1024 * 20 // 20KB段缓冲区
#define BYTE_BEGIN 4 // Payload起始位置字节计数
// 辅助函数声明
bool CreateDeviceD3D(HWND hWnd); // 创建 Direct 3D 设备
void CleanupDeviceD3D(); // 清理 Direct3D 设备
void CreateRenderTarget(); // 创建渲染目标
void CleanupRenderTarget(); // 清理渲染目标
// 文件链表节点
typedef struct file_node_struct
{
const char *file_name_str = nullptr;
file_node_struct *p_next = nullptr;
} file_node;
// Windows窗体事件处理函数声明
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
// 读取文件一行
size_t f_getline(FILE *file, char *buffer, const size_t buffer_len)
// 重定义窗体消息处理函数 >> imgui_impl_win32.cpp
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
// 入口主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
if (buffer == nullptr || file == nullptr)
// 启用DPI响应并获取主显示器分辨率
ImGui_ImplWin32_EnableDpiAwareness();
float main_scale = ImGui_ImplWin32_GetDpiScaleForMonitor(MonitorFromPoint(POINT{0, 0}, MONITOR_DEFAULTTOPRIMARY));
// 窗体类结构体
WNDCLASSEXW wc; // Windows 扩展窗体类
wc.cbSize = sizeof(wc); // 类结构大小
wc.style = CS_CLASSDC; // 绘制样式使用类设备上下文 Class Device Context
wc.lpfnWndProc = WndProc; // 窗体事件处理回调函数
wc.cbClsExtra = 0L; // 为窗口类额外分配的字节数,通常为 0
wc.cbWndExtra = 0L; // 为窗口实例额外分配的字节数,通常为 0
wc.hInstance = hInstance; // 应用程序实例的句柄。
wc.hIcon = LoadIconW(hInstance, IDI_APPLICATION); // 应用图标样式
wc.hCursor = LoadCursorW(hInstance, IDC_ARROW); // 应用光标样式
wc.hbrBackground = (HBRUSH)COLOR_WINDOWFRAME; // 窗体背景颜色刷
wc.lpszMenuName = nullptr; // 窗体菜单名称
wc.lpszClassName = L"DLT_Splitter_Base_Window_Class"; // 窗体注册类名
wc.hIconSm = LoadIconW(hInstance, IDI_APPLICATION); // 应用小图标样式
// 注册窗体类
RegisterClassExW(&wc);
// 创建窗体
HWND hwnd = CreateWindowW(wc.lpszClassName, // 创建的窗体类名
L"DLT Splitter —— Dev by: LuChiChick", // 窗体标题
WS_OVERLAPPEDWINDOW, // 窗体风格为标准可重叠的顶层窗口
100, // 起始坐标x
100, // 起始坐标y
(int)(1280 * main_scale), // 窗体长
(int)(720 * main_scale), // 窗体宽
nullptr, // 父窗体句柄
nullptr, // 菜单句柄
wc.hInstance, // 创建实例句柄
nullptr); // 额外的事件参数指针
// 在窗体内创建 Direct 3D 设备
if (!CreateDeviceD3D(hwnd))
{
// 未创建完成时清理 Direct 3D 设备并清理窗体注册类
CleanupDeviceD3D();
UnregisterClassW(wc.lpszClassName, wc.hInstance);
// 返回错误代码
return -1;
}
// 显示窗体并强制更新一次窗体
ShowWindow(hwnd, SW_SHOWDEFAULT);
UpdateWindow(hwnd);
// 检查版本
IMGUI_CHECKVERSION();
// 建立 Dear ImGui 上下文
ImGui::CreateContext();
// 获取ImGui IO 设备配置结构体
ImGuiIO &io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
// io.ConfigViewportsNoAutoMerge = true;
// io.ConfigViewportsNoTaskBarIcon = true;
// io.ConfigDockingAlwaysTabBar = true;
// io.ConfigDockingTransparentPayload = true;
io.IniFilename = nullptr; // 不生成ini布局配置文件
// 主题为亮/暗
ImGui::StyleColorsLight();
// ImGui::StyleColorsDark();
// Setup scaling
// 获取风格渲染配置并整缩放比例
ImGuiStyle &style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
io.ConfigDpiScaleFonts = true; // [Experimental] Automatically overwrite style.FontScaleDpi in Begin() when Monitor DPI changes. This will scale fonts but _NOT_ scale sizes/padding for now.
io.ConfigDpiScaleViewports = true; // [Experimental] Scale Dear ImGui and Platform Windows when Monitor DPI changes.
// 调整视窗移动出主窗体范围外时的风格以匹配原生风格
// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
}
// 初始化渲染器后端(Renderer backends)
ImGui_ImplWin32_Init(hwnd);
ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
// 字体配置相关
{
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - Read 'docs/FONTS.md' for more instructions and details. If you like the default font but want it to scale better, consider using the 'ProggyVector' from the same author!
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
// style.FontSizeBase = 20.0f;
// io.Fonts->AddFontDefault();
// io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
// io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
// io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
// io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
// ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
// IM_ASSERT(font != nullptr);
}
// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// 主事件循环
bool done = false;
while (!done)
{
// 非阻塞式获取所有窗体消息,Pick消息后从消息队列删除,并转译和派发消息
MSG msg;
while (PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg); // 转译
DispatchMessageW(&msg); // 派发
// 窗体关闭事件
if (msg.message == WM_QUIT)
done = true;
}
if (done)
break;
// 处理窗体最小化或屏幕被锁定
if (g_SwapChainOccluded && g_pSwapChain->Present(0, DXGI_PRESENT_TEST) == DXGI_STATUS_OCCLUDED)
{
// 休眠10ms并跳过渲染
continue;
}
g_SwapChainOccluded = false;
// 开始创建当前绘制帧(创建顺序:DirectX -> Win32 -> ImGui)
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float *)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
ImGui::End();
}
// 3. Show another simple window.
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
// Rendering
ImGui::Render();
const float clear_color_with_alpha[4] = {clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w};
g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, nullptr);
g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha);
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
// Update and Render additional Platform Windows
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
}
// Present
HRESULT hr = g_pSwapChain->Present(1, 0); // Present with vsync
// HRESULT hr = g_pSwapChain->Present(0, 0); // Present without vsync
g_SwapChainOccluded = (hr == DXGI_STATUS_OCCLUDED);
}
// 收尾清理工作
ImGui_ImplDX11_Shutdown(); // 关闭 ImGui DX11 组件
ImGui_ImplWin32_Shutdown(); // 关闭 ImGui Win32 组件
ImGui::DestroyContext(); // 销毁 ImGui 上下文
CleanupDeviceD3D(); // 清理 Direct 3D 设备
DestroyWindow(hwnd); // 销毁窗体
UnregisterClassW(wc.lpszClassName, wc.hInstance); // 取消窗体注册类
return 0;
}
// 创建 Direct 3D 设备
bool CreateDeviceD3D(HWND hWnd)
{
// Setup swap chain
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 2;
sd.BufferDesc.Width = 0;
sd.BufferDesc.Height = 0;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
UINT createDeviceFlags = 0;
// createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
D3D_FEATURE_LEVEL featureLevel;
const D3D_FEATURE_LEVEL featureLevelArray[2] = {
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_0,
};
HRESULT res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
if (res == DXGI_ERROR_UNSUPPORTED) // Try high-performance WARP software driver if hardware is not available.
res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_WARP, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
if (res != S_OK)
return false;
// Disable DXGI's default Alt+Enter fullscreen behavior.
// - You are free to leave this enabled, but it will not work properly with multiple viewports.
// - This must be done for all windows associated to the device. Our DX11 backend does this automatically for secondary viewports that it creates.
IDXGIFactory *pSwapChainFactory;
if (SUCCEEDED(g_pSwapChain->GetParent(IID_PPV_ARGS(&pSwapChainFactory))))
pSwapChainFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER);
CreateRenderTarget();
return true;
}
// 清理 Direct3D 设备
void CleanupDeviceD3D()
{
CleanupRenderTarget();
if (g_pSwapChain)
{
g_pSwapChain->Release();
g_pSwapChain = nullptr;
}
if (g_pd3dDeviceContext)
{
g_pd3dDeviceContext->Release();
g_pd3dDeviceContext = nullptr;
}
if (g_pd3dDevice)
{
g_pd3dDevice->Release();
g_pd3dDevice = nullptr;
}
}
// 创建渲染目标
void CreateRenderTarget()
{
ID3D11Texture2D *pBackBuffer;
g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_mainRenderTargetView);
pBackBuffer->Release();
}
// 清理渲染目标
void CleanupRenderTarget()
{
if (g_mainRenderTargetView)
{
g_mainRenderTargetView->Release();
g_mainRenderTargetView = nullptr;
}
}
// Windows窗体事件处理函数
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// 优先让ImGui处理消息
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
return true;
// 筛查并处理余下的消息事件
switch (msg)
{
case WM_SIZE: // 窗体大小变事件
if (wParam != SIZE_MINIMIZED) // 窗体未处于最小化时进行重绘
{
// 清理渲染器并重新创建对应窗体大小的渲染器目标 低字为宽,高字为长
CleanupRenderTarget();
g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, 0);
CreateRenderTarget();
}
return 0;
memset(buffer, '\0', buffer_len);
size_t count = 0;
// 循环读取
while (true)
{
// 超长判定
if (count + 1 == buffer_len)
return buffer_len;
// 正常读取
char ch = fgetc(file);
// 仅文件结尾时
if (ch == EOF && count == 0)
case WM_SYSCOMMAND: // 系统指令事件
if ((wParam & 0xfff0) == SC_KEYMENU) // 禁用ALT键菜单响应,交给IMGUI实现 Disable ALT
return 0;
// 成功换行
if (ch == '\n')
{
buffer[count] = '\n';
return count + 1;
}
// 没有换行但是遇到了文件结尾
if (ch == EOF)
{
buffer[count] = '\n';
return count;
}
// 其它情况下正常复制
buffer[count] = ch;
count++;
break;
case WM_DESTROY: // 窗体销毁事件
PostQuitMessage(0); // 派发应用退出(Quit)消息
return 0;
}
// 剩余的消息交给默认的消息处理函数
return DefWindowProcW(hWnd, msg, wParam, lParam);
}
// 文件列表
file_node *file_list_head = nullptr;
int main(int argc, char *argv[])
{
// 处理指令输入
for (int count = 1; count < argc; count++)
{
static file_node *target_node = nullptr;
if (file_list_head == nullptr)
{
file_list_head = (file_node *)malloc(sizeof(file_node));
file_list_head->file_name_str = nullptr;
file_list_head->p_next = nullptr;
target_node = file_list_head;
}
else
{
target_node->p_next = (file_node *)malloc(sizeof(file_node));
target_node = target_node->p_next;
target_node->file_name_str = nullptr;
target_node->p_next = nullptr;
}
target_node->file_name_str = argv[count];
}
// 遍历文件
file_node *target_file_node = file_list_head;
while (target_file_node != nullptr)
{
// 打开相关文件
FILE *input_file = nullptr;
FILE *output_file = nullptr;
input_file = fopen(target_file_node->file_name_str, "rb");
if (input_file == nullptr)
printf("[-ERROR-] File \"%s\" open failed.\n", target_file_node->file_name_str);
else
{
// 拼接输出文件名及打开对应文件
char *buffer = (char *)malloc(strlen(target_file_node->file_name_str) + 100);
const char *file_name_do_dir = target_file_node->file_name_str + strlen(target_file_node->file_name_str);
while (file_name_do_dir != target_file_node->file_name_str)
{
if (*file_name_do_dir == '\\' || *file_name_do_dir == '/')
{
file_name_do_dir++;
break;
}
file_name_do_dir--;
}
for (int count = 0; count < file_name_do_dir - target_file_node->file_name_str; count++)
buffer[count] = target_file_node->file_name_str[count];
sprintf(buffer + (file_name_do_dir - target_file_node->file_name_str), "[Split]%s", file_name_do_dir);
output_file = fopen(buffer, "wb");
if (output_file == nullptr)
printf("[-ERROR-] File \"%s\" create failed.\n", buffer);
free(buffer);
}
// 处理文件
if (input_file != nullptr && output_file != nullptr)
{
char segment_buff[SEGMENT_BUFF_LENTH];
size_t byte_count_max = 0;
// 求解Payload最长有多少个字节
{
// 忽略标题
f_getline(input_file, segment_buff, sizeof(segment_buff));
// 循环处理每行
while (f_getline(input_file, segment_buff, sizeof(segment_buff)) != 0)
{
// 计数直到数据起始
const char *p_data_begin = segment_buff + strlen(segment_buff);
size_t byte_count = 0;
while (*(p_data_begin - 1) != '|')
{
if (*p_data_begin == ' ')
byte_count++;
p_data_begin--;
}
byte_count++;
if (byte_count > byte_count_max)
byte_count_max = byte_count; // 记录最大值
}
// 回到起始位置
fseek(input_file, 0, SEEK_SET);
}
// 处理标题部分
{
f_getline(input_file, segment_buff, sizeof(segment_buff));
const char *p_char = segment_buff;
const char *p_end = segment_buff + strlen(segment_buff);
while (*(p_end - 1) != '\"')
p_end--;
for (int count = p_end - segment_buff; count > 0; count--)
fputc(*p_char++, output_file);
// 打印Byte编号
for (size_t count = 0; count < byte_count_max; count++)
fprintf(output_file, ",\"B%u\"", count + BYTE_BEGIN);
fprintf(output_file, "\r\n");
}
int line_count;
// 循环处理每行
while (f_getline(input_file, segment_buff, sizeof(segment_buff)) != 0)
{
// 找到数据起始
const char *p_data_begin = segment_buff + strlen(segment_buff);
while (*(p_data_begin - 1) != '|')
p_data_begin--;
// 输出分段前内容
for (const char *p_target = segment_buff; p_target != p_data_begin; p_target++)
fputc(*p_target, output_file);
// 隔断
fprintf(output_file, "\",\"");
// 输出剩余Payload内容
for (int count = strlen(p_data_begin); count > 0; count--)
{
// 按空格分列
if (*p_data_begin == ' ')
fprintf(output_file, "\",\"");
else
fputc(*p_data_begin, output_file);
p_data_begin++;
}
// 记录行号
sscanf(segment_buff + 1, "%d", &line_count);
}
printf("[- OK -] [Total Line: %d] \"%s\"\n", line_count, target_file_node->file_name_str);
}
// 关闭文件及切换下一个文件节点
target_file_node = target_file_node->p_next;
fclose(input_file);
fclose(output_file);
}
}