summaryrefslogtreecommitdiff
path: root/src/windows
diff options
context:
space:
mode:
authorAldrik Ramaekers <aldrikboy@gmail.com>2024-03-12 21:45:35 +0100
committerAldrik Ramaekers <aldrikboy@gmail.com>2024-03-12 21:45:35 +0100
commite72c327a84d1937c05cc14a5e2ab232584e2cb9d (patch)
tree96d58fa0f0065c577bcc87bc094498d2348b3ca3 /src/windows
parente4d2929604792b135cbf8dad22179a5dec60e365 (diff)
dragdrop file work
Diffstat (limited to 'src/windows')
-rw-r--r--src/windows/DropManager.h106
-rw-r--r--src/windows/main_windows.cpp10
2 files changed, 116 insertions, 0 deletions
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 <oleidl.h>
+
+// 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<IUnknown*> 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<HDROP> 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 <Shlobj.h>
#include <GL/GL.h>
#include <tchar.h>
+#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;