From e72c327a84d1937c05cc14a5e2ab232584e2cb9d Mon Sep 17 00:00:00 2001 From: Aldrik Ramaekers Date: Tue, 12 Mar 2024 21:45:35 +0100 Subject: dragdrop file work --- src/main.cpp | 20 +++++++- src/platform.h | 10 ++++ src/windows/DropManager.h | 106 +++++++++++++++++++++++++++++++++++++++++++ src/windows/main_windows.cpp | 10 ++++ 4 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 src/windows/DropManager.h diff --git a/src/main.cpp b/src/main.cpp index 4520d9c..4365f2a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -500,7 +500,25 @@ void ts_create_gui(int window_w, int window_h) { } pos_y += textbox_area_height + 7; - if (current_search_result) + if (dragdrop_data.did_drop) { + printf("Do loading..\n"); + dragdrop_data.did_drop = false; + } + + if (dragdrop_data.is_dragging_file) + { + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceExtern)) // we use an external source (i.e. not ImGui-created) + { + ImGui::SetDragDropPayload("FILES", nullptr, 0); + ImGui::BeginTooltip(); + ImGui::Text("Drop to load file"); + ImGui::EndTooltip(); + ImGui::EndDragDropSource(); + } + + ImGui::Text("Drag test"); + } + else if (current_search_result) { // Results ImGui::SetNextWindowPos({5, pos_y}); diff --git a/src/platform.h b/src/platform.h index 3f41e4f..5926aeb 100644 --- a/src/platform.h +++ b/src/platform.h @@ -4,6 +4,7 @@ #include "array.h" #include "memory_bucket.h" #include "search.h" +#include "config.h" #include "../utf8.h" typedef struct t_ts_file_content @@ -29,7 +30,16 @@ typedef enum t_ts_file_open_error FILE_ERROR_TOO_BIG = 11, } ts_file_open_error; +typedef struct t_ts_dragdrop_data +{ + bool did_drop; + utf8_int8_t path[MAX_INPUT_LENGTH]; + bool is_dragging_file; +} ts_dragdrop_data; + + extern bool program_running; +extern ts_dragdrop_data dragdrop_data; bool ts_platform_dir_exists(utf8_int8_t* dir); ts_file_content ts_platform_read_file(char *path, const char *mode); diff --git a/src/windows/DropManager.h b/src/windows/DropManager.h new file mode 100644 index 0000000..32b6922 --- /dev/null +++ b/src/windows/DropManager.h @@ -0,0 +1,106 @@ +#pragma once + +#include "platform.h" + +#include + +// create a class inheriting from IDropTarget +class DropManager : public IDropTarget +{ +public: + //--- implement the IUnknown parts + // you could do this the proper way with InterlockedIncrement etc, + // but I've left out stuff that's not exactly necessary for brevity + ULONG AddRef() { return 1; } + ULONG Release() { return 0; } + + // we handle drop targets, let others know + HRESULT QueryInterface(REFIID riid, void **ppvObject) + { + if (riid == IID_IDropTarget) + { + *ppvObject = this; // or static_cast if preferred + // AddRef() if doing things properly + // but then you should probably handle IID_IUnknown as well; + return S_OK; + } + + *ppvObject = NULL; + return E_NOINTERFACE; + }; + + + //--- implement the IDropTarget parts + + // occurs when we drag files into our applications view + HRESULT DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) + { + // TODO: check whether we can handle this type of object at all and set *pdwEffect &= DROPEFFECT_NONE if not; + + // do something useful to flag to our application that files have been dragged from the OS into our application + //... + dragdrop_data.is_dragging_file = true; + + // trigger MouseDown for button 1 within ImGui + //... + + *pdwEffect &= DROPEFFECT_COPY; + return S_OK; + } + + // occurs when we drag files out from our applications view + HRESULT DragLeave() { + dragdrop_data.is_dragging_file = false; + return S_OK; + } + + // occurs when we drag the mouse over our applications view whilst carrying files (post Enter, pre Leave) + HRESULT DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) + { + // trigger MouseMove within ImGui, position is within pt.x and pt.y + // grfKeyState contains flags for control, alt, shift etc + //... + + *pdwEffect &= DROPEFFECT_COPY; + return S_OK; + } + + // occurs when we release the mouse button to finish the drag-drop operation + HRESULT Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) + { + dragdrop_data.is_dragging_file = false; + // grfKeyState contains flags for control, alt, shift etc + + // render the data into stgm using the data description in fmte + FORMATETC fmte = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + STGMEDIUM stgm; + + if (SUCCEEDED(pDataObj->GetData(&fmte, &stgm))) + { + HDROP hdrop = (HDROP)stgm.hGlobal; // or reinterpret_cast if preferred + UINT file_count = DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0); + + // We only accept 1 file for now.. + for (UINT i = 0; i < 1; i++) + { + TCHAR szFile[MAX_PATH]; + UINT cch = DragQueryFile(hdrop, i, szFile, MAX_PATH); + if (cch > 0 && cch < MAX_PATH) + { + WideCharToMultiByte(CP_UTF8,0,szFile,-1,(LPSTR)dragdrop_data.path, MAX_INPUT_LENGTH, NULL, NULL); + } + } + + // we have to release the data when we're done with it + ReleaseStgMedium(&stgm); + + dragdrop_data.did_drop = true; + } + + // trigger MouseUp for button 1 within ImGui + //... + + *pdwEffect &= DROPEFFECT_COPY; + return S_OK; + } +}; \ No newline at end of file diff --git a/src/windows/main_windows.cpp b/src/windows/main_windows.cpp index fa55d9c..00a8bc2 100644 --- a/src/windows/main_windows.cpp +++ b/src/windows/main_windows.cpp @@ -19,6 +19,7 @@ #include #include #include +#include "DropManager.h" #ifdef TS_RELEASE #pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup") @@ -27,6 +28,7 @@ #define IDI_LOGO 123 char config_path[MAX_INPUT_LENGTH]; +ts_dragdrop_data dragdrop_data = {0}; void ts_create_gui(int window_w, int window_h); void ts_load_images(); @@ -108,7 +110,9 @@ void ts_platform_set_window_title(utf8_int8_t* str) { int main(int, char**) { + OleInitialize(NULL); CoInitializeEx(0, COINIT_MULTITHREADED|COINIT_DISABLE_OLE1DDE); + ts_init(); // Create application window @@ -157,6 +161,9 @@ int main(int, char**) ts_load_images(); ts_load_config(); + DropManager dm; + RegisterDragDrop(hwnd, &dm); + while (program_running) { MSG msg; @@ -177,11 +184,14 @@ int main(int, char**) ImGui_ImplWin32_Shutdown(); ImGui::DestroyContext(); + RevokeDragDrop(hwnd); + CleanupDeviceWGL(hwnd, &g_MainWindow); wglDeleteContext(g_hRC); ::DestroyWindow(hwnd); ::UnregisterClassW(wc.lpszClassName, wc.hInstance); + OleUninitialize(); CoUninitialize(); return 0; -- cgit v1.2.3-70-g09d2