From 0814aaaf17e3f1b8dda94aef1dc13a4c99d4a630 Mon Sep 17 00:00:00 2001 From: LuChiChick <1084116302@qq.com> Date: Thu, 27 Nov 2025 21:56:32 +0800 Subject: [PATCH] Implement Win32 drag drop file and change main window size --- Inc/Config.hpp | 4 ++ Inc/Global_Variables.hpp | 6 +++ Inc/Type_Descriptions.hpp | 11 +++++ Src/Global_Variables.cpp | 6 ++- Src/Main.cpp | 87 ++++++++++++++++++++++++++++++++++----- 5 files changed, 102 insertions(+), 12 deletions(-) create mode 100644 Inc/Type_Descriptions.hpp diff --git a/Inc/Config.hpp b/Inc/Config.hpp index fac0ce2..3555fe6 100644 --- a/Inc/Config.hpp +++ b/Inc/Config.hpp @@ -4,4 +4,8 @@ // 主窗体标题 #define MAIN_FRAME_TITTLE L"DLT Splitter —— Dev by : LuChiChick" +// 主窗体最小面积 +#define MAIN_FRAME_SIZE_WIDTH_MIN 350 +#define MAIN_FRAME_SIZE_HEIGHT_MIN 350 * 1.5 + #endif \ No newline at end of file diff --git a/Inc/Global_Variables.hpp b/Inc/Global_Variables.hpp index 4653a02..975d900 100644 --- a/Inc/Global_Variables.hpp +++ b/Inc/Global_Variables.hpp @@ -11,6 +11,8 @@ extern "C" #include "d3d11.h" } +#include "Type_Descriptions.hpp" + // D3D11 相关 extern ID3D11Device *g_pd3dDevice; // D3D11 设备句柄 extern ID3D11DeviceContext *g_pd3dDeviceContext; // D3D11 设备上下文句柄 @@ -20,4 +22,8 @@ extern bool g_SwapChainOccluded; // 交换链是否阻塞 extern ID3D11RenderTargetView *g_mainRenderTargetView; // D3D11 渲染目标 +// 文件输入相关 +extern Input_File_Node *input_dlt_file_list_head; +extern size_t input_dlt_file_count; + #endif \ No newline at end of file diff --git a/Inc/Type_Descriptions.hpp b/Inc/Type_Descriptions.hpp new file mode 100644 index 0000000..5cf07f9 --- /dev/null +++ b/Inc/Type_Descriptions.hpp @@ -0,0 +1,11 @@ +#ifndef __TYPE_DESCRIPTIONS_HPP__ +#define __TYPE_DESCRIPTIONS_HPP__ + +// 文件节点 +typedef struct Input_File_Node +{ + char *file_name_str; + Input_File_Node *p_next; +} Input_File_Node; + +#endif \ No newline at end of file diff --git a/Src/Global_Variables.cpp b/Src/Global_Variables.cpp index 381d29f..4027b43 100644 --- a/Src/Global_Variables.cpp +++ b/Src/Global_Variables.cpp @@ -7,4 +7,8 @@ ID3D11DeviceContext *g_pd3dDeviceContext = nullptr; // D3D11 设备上下文句 IDXGISwapChain *g_pSwapChain = nullptr; // DXGI 交换链句柄 bool g_SwapChainOccluded = false; // 交换链是否阻塞 -ID3D11RenderTargetView *g_mainRenderTargetView = nullptr; // D3D11 渲染目标 \ No newline at end of file +ID3D11RenderTargetView *g_mainRenderTargetView = nullptr; // D3D11 渲染目标 + +// 文件输入相关 +Input_File_Node *input_dlt_file_list_head; +size_t input_dlt_file_count; \ No newline at end of file diff --git a/Src/Main.cpp b/Src/Main.cpp index 40e91e1..f2d10ce 100644 --- a/Src/Main.cpp +++ b/Src/Main.cpp @@ -61,17 +61,17 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine RegisterClassExW(&wc); // 创建窗体 - HWND hwnd = CreateWindowW(wc.lpszClassName, // 创建的窗体类名 - MAIN_FRAME_TITTLE, // 窗体标题 - WS_OVERLAPPEDWINDOW, // 窗体风格为标准可重叠的顶层窗口 - 100, // 起始坐标x - 100, // 起始坐标y - (int)(1280 * main_scale), // 窗体长 - (int)(720 * main_scale), // 窗体宽 - nullptr, // 父窗体句柄 - nullptr, // 菜单句柄 - wc.hInstance, // 创建实例句柄 - nullptr); // 额外的事件参数指针 + HWND hwnd = CreateWindowW(wc.lpszClassName, // 创建的窗体类名 + MAIN_FRAME_TITTLE, // 窗体标题 + WS_OVERLAPPEDWINDOW, // 窗体风格为标准可重叠的顶层窗口 + 100, // 起始坐标x + 100, // 起始坐标y + (int)(MAIN_FRAME_SIZE_WIDTH_MIN * main_scale), // 窗体长 + (int)(MAIN_FRAME_SIZE_HEIGHT_MIN * main_scale), // 窗体宽 + nullptr, // 父窗体句柄 + nullptr, // 菜单句柄 + wc.hInstance, // 创建实例句柄 + nullptr); // 额外的事件参数指针 // 在窗体内创建 Direct 3D 设备 if (!CreateDeviceD3D(hwnd)) @@ -84,6 +84,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine return -1; } + // 启用文件拖拽输入 + DragAcceptFiles(hwnd, TRUE); + // 显示窗体并强制更新一次窗体 ShowWindow(hwnd, SW_SHOWDEFAULT); UpdateWindow(hwnd); @@ -333,6 +336,68 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) // 筛查并处理余下的消息事件 switch (msg) { + case WM_DROPFILES: // 文件拖拽事件 + { + HDROP hDrop = (HDROP)wParam; // 拖拽数据句柄 + // 获取拖拽的文件总数 + UINT fileCount = DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0); + + // 添加到文件列表 + for (UINT count = 0; count < fileCount; count++) + { + wchar_t filePath[MAX_PATH] = {L'\0'}; + DragQueryFileW( + hDrop, // 拖拽句柄 + count, // 文件索引(0 表示第一个文件) + filePath, // 存储路径的缓冲区 + MAX_PATH // 缓冲区大小 + ); + + char file_path_multi_byte[MAX_PATH] = {'\0'}; + int size_needed = WideCharToMultiByte(CP_UTF8, 0, filePath, -1, NULL, 0, NULL, NULL); + WideCharToMultiByte(CP_UTF8, 0, filePath, -1, file_path_multi_byte, size_needed, NULL, NULL); + + /** + * @todo 文件类型筛选 + */ + + // 重复文件剔除 + bool duplicated = false; + for (Input_File_Node *p_file_node = input_dlt_file_list_head; p_file_node != nullptr; p_file_node = p_file_node->p_next) + if (!strcmp(p_file_node->file_name_str, file_path_multi_byte)) + { + duplicated = true; + break; + } + if (duplicated) + continue; + + // 开辟新文件节点 + Input_File_Node *p_new_file_node = (Input_File_Node *)malloc(sizeof(Input_File_Node)); + p_new_file_node->file_name_str = (char *)malloc(strlen(file_path_multi_byte) + 1); + memset(p_new_file_node->file_name_str, '\0', strlen(file_path_multi_byte) + 1); + memcpy(p_new_file_node->file_name_str, file_path_multi_byte, strlen(file_path_multi_byte)); + p_new_file_node->p_next = nullptr; + + // 插入文件列表 + if (input_dlt_file_list_head == nullptr) + input_dlt_file_list_head = p_new_file_node; + else + { + Input_File_Node *p_target_node = input_dlt_file_list_head; + for (size_t count = 1; count < input_dlt_file_count; count++) + p_target_node = p_target_node->p_next; + + p_target_node->p_next = p_new_file_node; + } + + input_dlt_file_count++; + } + + // 释放拖拽资源(必须调用,否则内存泄漏) + DragFinish(hDrop); + return 0; + } case WM_SIZE: // 窗体大小变事件 if (wParam != SIZE_MINIMIZED) // 窗体未处于最小化时进行重绘 {