mirror of
https://github.com/glfw/glfw.git
synced 2024-12-03 23:37:12 +00:00
Win32: Implement drag & drop via IDropTarget
This commit is contained in:
parent
735f31454e
commit
d2763ec2a1
@ -167,6 +167,19 @@ static GLFWbool loadLibraries(void)
|
|||||||
_glfwPlatformGetModuleSymbol(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo");
|
_glfwPlatformGetModuleSymbol(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_glfw.win32.ole32.instance = _glfwPlatformLoadModule("ole32.dll");
|
||||||
|
if (_glfw.win32.ole32.instance)
|
||||||
|
{
|
||||||
|
_glfw.win32.ole32.OleInitialize_ = (PFN_OleInitialize)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.win32.ole32.instance, "OleInitialize");
|
||||||
|
_glfw.win32.ole32.OleUninitialize_ = (PFN_OleUninitialize)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.win32.ole32.instance, "OleUninitialize");
|
||||||
|
_glfw.win32.ole32.RegisterDragDrop_ = (PFN_RegisterDragDrop)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.win32.ole32.instance, "RegisterDragDrop");
|
||||||
|
_glfw.win32.ole32.RevokeDragDrop_ = (PFN_RevokeDragDrop)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.win32.ole32.instance, "RevokeDragDrop");
|
||||||
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,6 +204,9 @@ static void freeLibraries(void)
|
|||||||
|
|
||||||
if (_glfw.win32.ntdll.instance)
|
if (_glfw.win32.ntdll.instance)
|
||||||
_glfwPlatformFreeModule(_glfw.win32.ntdll.instance);
|
_glfwPlatformFreeModule(_glfw.win32.ntdll.instance);
|
||||||
|
|
||||||
|
if (_glfw.win32.ole32.instance)
|
||||||
|
_glfwPlatformFreeModule(_glfw.win32.ole32.instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create key code translation tables
|
// Create key code translation tables
|
||||||
@ -430,6 +446,27 @@ static GLFWbool createHelperWindow(void)
|
|||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize OLE as well as the IDropTarget vtable
|
||||||
|
//
|
||||||
|
static GLFWbool initDragDrop()
|
||||||
|
{
|
||||||
|
if (FAILED(OleInitialize(NULL)))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to initialize OLE");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//_glfw.win32.dropTargetVtbl.QueryInterface = _glfwDropTarget_QueryInterface;
|
||||||
|
_glfw.win32.dropTargetVtbl.AddRef = (PFN_IDropTarget_AddRef)_glfwDropTarget_AddRef;
|
||||||
|
_glfw.win32.dropTargetVtbl.Release = (PFN_IDropTarget_Release)_glfwDropTarget_Release;
|
||||||
|
_glfw.win32.dropTargetVtbl.DragEnter = (PFN_IDropTarget_DragEnter)_glfwDropTarget_DragEnter;
|
||||||
|
_glfw.win32.dropTargetVtbl.DragOver = (PFN_IDropTarget_DragOver)_glfwDropTarget_DragOver;
|
||||||
|
_glfw.win32.dropTargetVtbl.DragLeave = (PFN_IDropTarget_DragLeave)_glfwDropTarget_DragLeave;
|
||||||
|
_glfw.win32.dropTargetVtbl.Drop = (PFN_IDropTarget_Drop)_glfwDropTarget_Drop;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
@ -699,6 +736,9 @@ int _glfwInitWin32(void)
|
|||||||
if (!createHelperWindow())
|
if (!createHelperWindow())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (!initDragDrop())
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
_glfwPollMonitorsWin32();
|
_glfwPollMonitorsWin32();
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
@ -708,6 +748,8 @@ void _glfwTerminateWin32(void)
|
|||||||
if (_glfw.win32.deviceNotificationHandle)
|
if (_glfw.win32.deviceNotificationHandle)
|
||||||
UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
|
UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
|
||||||
|
|
||||||
|
OleUninitialize();
|
||||||
|
|
||||||
if (_glfw.win32.helperWindowHandle)
|
if (_glfw.win32.helperWindowHandle)
|
||||||
DestroyWindow(_glfw.win32.helperWindowHandle);
|
DestroyWindow(_glfw.win32.helperWindowHandle);
|
||||||
if (_glfw.win32.helperWindowClass)
|
if (_glfw.win32.helperWindowClass)
|
||||||
|
@ -64,11 +64,15 @@
|
|||||||
// GLFW uses OEM cursor resources
|
// GLFW uses OEM cursor resources
|
||||||
#define OEMRESOURCE
|
#define OEMRESOURCE
|
||||||
|
|
||||||
|
// define COM C object macros
|
||||||
|
#define COBJMACROS
|
||||||
|
|
||||||
#include <wctype.h>
|
#include <wctype.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <dinput.h>
|
#include <dinput.h>
|
||||||
#include <xinput.h>
|
#include <xinput.h>
|
||||||
#include <dbt.h>
|
#include <dbt.h>
|
||||||
|
#include <ole2.h>
|
||||||
|
|
||||||
// HACK: Define macros that some windows.h variants don't
|
// HACK: Define macros that some windows.h variants don't
|
||||||
#ifndef WM_MOUSEHWHEEL
|
#ifndef WM_MOUSEHWHEEL
|
||||||
@ -316,6 +320,22 @@ typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,
|
|||||||
typedef LONG (WINAPI * PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*,ULONG,ULONGLONG);
|
typedef LONG (WINAPI * PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*,ULONG,ULONGLONG);
|
||||||
#define RtlVerifyVersionInfo _glfw.win32.ntdll.RtlVerifyVersionInfo_
|
#define RtlVerifyVersionInfo _glfw.win32.ntdll.RtlVerifyVersionInfo_
|
||||||
|
|
||||||
|
// ole32.dll function pointer typedefs
|
||||||
|
typedef HRESULT (WINAPI * PFN_OleInitialize)(LPVOID);
|
||||||
|
typedef VOID (WINAPI * PFN_OleUninitialize)(VOID);
|
||||||
|
typedef HRESULT (WINAPI * PFN_RegisterDragDrop)(HWND,LPDROPTARGET);
|
||||||
|
typedef HRESULT (WINAPI * PFN_RevokeDragDrop)(HWND);
|
||||||
|
typedef ULONG (STDMETHODCALLTYPE * PFN_IDropTarget_AddRef)(LPDROPTARGET);
|
||||||
|
typedef ULONG (STDMETHODCALLTYPE * PFN_IDropTarget_Release)(LPDROPTARGET);
|
||||||
|
typedef HRESULT (STDMETHODCALLTYPE * PFN_IDropTarget_DragEnter)(LPDROPTARGET,IDataObject*,DWORD,POINTL,DWORD*);
|
||||||
|
typedef HRESULT (STDMETHODCALLTYPE * PFN_IDropTarget_DragOver)(LPDROPTARGET,DWORD,POINTL,DWORD*);
|
||||||
|
typedef HRESULT (STDMETHODCALLTYPE * PFN_IDropTarget_DragLeave)(LPDROPTARGET);
|
||||||
|
typedef HRESULT (STDMETHODCALLTYPE * PFN_IDropTarget_Drop)(LPDROPTARGET,IDataObject*,DWORD,POINTL,DWORD*);
|
||||||
|
#define OleInitialize _glfw.win32.ole32.OleInitialize_
|
||||||
|
#define OleUninitialize _glfw.win32.ole32.OleUninitialize_
|
||||||
|
#define RegisterDragDrop _glfw.win32.ole32.RegisterDragDrop_
|
||||||
|
#define RevokeDragDrop _glfw.win32.ole32.RevokeDragDrop_
|
||||||
|
|
||||||
// WGL extension pointer typedefs
|
// WGL extension pointer typedefs
|
||||||
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
|
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
|
||||||
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);
|
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);
|
||||||
@ -408,6 +428,13 @@ typedef struct _GLFWlibraryWGL
|
|||||||
GLFWbool ARB_context_flush_control;
|
GLFWbool ARB_context_flush_control;
|
||||||
} _GLFWlibraryWGL;
|
} _GLFWlibraryWGL;
|
||||||
|
|
||||||
|
typedef struct _GLFWdropTarget
|
||||||
|
{
|
||||||
|
IDropTargetVtbl* lpVtbl;
|
||||||
|
ULONG cRefCount;
|
||||||
|
_GLFWwindow* window;
|
||||||
|
} _GLFWdropTarget;
|
||||||
|
|
||||||
// Win32-specific per-window data
|
// Win32-specific per-window data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWwindowWin32
|
typedef struct _GLFWwindowWin32
|
||||||
@ -432,6 +459,8 @@ typedef struct _GLFWwindowWin32
|
|||||||
int lastCursorPosX, lastCursorPosY;
|
int lastCursorPosX, lastCursorPosY;
|
||||||
// The last received high surrogate when decoding pairs of UTF-16 messages
|
// The last received high surrogate when decoding pairs of UTF-16 messages
|
||||||
WCHAR highSurrogate;
|
WCHAR highSurrogate;
|
||||||
|
|
||||||
|
_GLFWdropTarget dropTarget;
|
||||||
} _GLFWwindowWin32;
|
} _GLFWwindowWin32;
|
||||||
|
|
||||||
// Win32-specific global data
|
// Win32-specific global data
|
||||||
@ -455,6 +484,7 @@ typedef struct _GLFWlibraryWin32
|
|||||||
RAWINPUT* rawInput;
|
RAWINPUT* rawInput;
|
||||||
int rawInputSize;
|
int rawInputSize;
|
||||||
UINT mouseTrailSize;
|
UINT mouseTrailSize;
|
||||||
|
IDropTargetVtbl dropTargetVtbl;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
@ -497,6 +527,15 @@ typedef struct _GLFWlibraryWin32
|
|||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_;
|
PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_;
|
||||||
} ntdll;
|
} ntdll;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HINSTANCE instance;
|
||||||
|
|
||||||
|
PFN_OleInitialize OleInitialize_;
|
||||||
|
PFN_OleUninitialize OleUninitialize_;
|
||||||
|
PFN_RegisterDragDrop RegisterDragDrop_;
|
||||||
|
PFN_RevokeDragDrop RevokeDragDrop_;
|
||||||
|
} ole32;
|
||||||
} _GLFWlibraryWin32;
|
} _GLFWlibraryWin32;
|
||||||
|
|
||||||
// Win32-specific per-monitor data
|
// Win32-specific per-monitor data
|
||||||
@ -620,3 +659,11 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig);
|
const _GLFWfbconfig* fbconfig);
|
||||||
|
|
||||||
|
// IDropTarget vtable functions
|
||||||
|
//HRESULT STDMETHODCALLTYPE _glfwDropTarget_QueryInterface(_GLFWdropTarget *This, REFIID riid, void **ppvObject);
|
||||||
|
ULONG STDMETHODCALLTYPE _glfwDropTarget_AddRef(_GLFWdropTarget *This);
|
||||||
|
ULONG STDMETHODCALLTYPE _glfwDropTarget_Release(_GLFWdropTarget *This);
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragEnter(_GLFWdropTarget *This, IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragOver(_GLFWdropTarget *This, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragLeave(_GLFWdropTarget *This);
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_Drop(_GLFWdropTarget *This, IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <stdio.h> // TODO remove
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
@ -1407,7 +1408,15 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DragAcceptFiles(window->win32.handle, TRUE);
|
//DragAcceptFiles(window->win32.handle, TRUE);
|
||||||
|
window->win32.dropTarget.lpVtbl = &_glfw.win32.dropTargetVtbl;
|
||||||
|
window->win32.dropTarget.window = window;
|
||||||
|
if (FAILED(RegisterDragDrop(window->win32.handle, (LPDROPTARGET)&window->win32.dropTarget)))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to register window for drag & drop");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (fbconfig->transparent)
|
if (fbconfig->transparent)
|
||||||
{
|
{
|
||||||
@ -1493,6 +1502,8 @@ void _glfwDestroyWindowWin32(_GLFWwindow* window)
|
|||||||
if (_glfw.win32.disabledCursorWindow == window)
|
if (_glfw.win32.disabledCursorWindow == window)
|
||||||
_glfw.win32.disabledCursorWindow = NULL;
|
_glfw.win32.disabledCursorWindow = NULL;
|
||||||
|
|
||||||
|
RevokeDragDrop(window->win32.handle);
|
||||||
|
|
||||||
if (window->win32.handle)
|
if (window->win32.handle)
|
||||||
{
|
{
|
||||||
RemovePropW(window->win32.handle, L"GLFW");
|
RemovePropW(window->win32.handle, L"GLFW");
|
||||||
@ -2452,3 +2463,119 @@ GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle)
|
|||||||
return window->win32.handle;
|
return window->win32.handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*static GLFWbool _glfwIsEqualIID(REFIID riid1, REFIID riid2)
|
||||||
|
{
|
||||||
|
return riid1->Data1 == riid2->Data1
|
||||||
|
&& riid1->Data2 == riid2->Data2
|
||||||
|
&& riid1->Data3 == riid2->Data3
|
||||||
|
&& (memcmp(riid1->Data4, riid2->Data4, sizeof(riid1->Data4)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IDropTarget vtable functions
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_QueryInterface(_GLFWdropTarget *This, REFIID riid, void **ppvObject)
|
||||||
|
{
|
||||||
|
printf("DropTarget_QueryInterface\n");
|
||||||
|
if(!ppvObject)
|
||||||
|
return E_POINTER;
|
||||||
|
|
||||||
|
if (_glfwIsEqualIID(riid, &IID_IUnknown) || _glfwIsEqualIID(riid, &IID_IDropTarget))
|
||||||
|
{
|
||||||
|
*ppvObject = This;
|
||||||
|
This->lpVtbl->AddRef(This);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ppvObject = 0;
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// IDropTarget vtable functions
|
||||||
|
ULONG STDMETHODCALLTYPE _glfwDropTarget_AddRef(_GLFWdropTarget *This)
|
||||||
|
{
|
||||||
|
printf("DropTarget_AddRef\n");
|
||||||
|
return ++This->cRefCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE _glfwDropTarget_Release(_GLFWdropTarget *This)
|
||||||
|
{
|
||||||
|
printf("DropTarget_Release\n");
|
||||||
|
return --This->cRefCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragEnter(_GLFWdropTarget *This, IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
|
||||||
|
{
|
||||||
|
FORMATETC fmt = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||||
|
|
||||||
|
printf("DropTarget_DragEnter\n");
|
||||||
|
if(SUCCEEDED(IDataObject_QueryGetData(pDataObj, &fmt)))
|
||||||
|
{
|
||||||
|
printf("QueryGetData OK\n");
|
||||||
|
*pdwEffect = DROPEFFECT_COPY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*pdwEffect = DROPEFFECT_NONE;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragOver(_GLFWdropTarget *This, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
|
||||||
|
{
|
||||||
|
printf("DropTarget_DragOver\n");
|
||||||
|
*pdwEffect = DROPEFFECT_COPY;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_DragLeave(_GLFWdropTarget *This)
|
||||||
|
{
|
||||||
|
printf("DropTarget_DragLeave\n");
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE _glfwDropTarget_Drop(_GLFWdropTarget *This, IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
|
||||||
|
{
|
||||||
|
FORMATETC fmt = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||||
|
STGMEDIUM stgmed;
|
||||||
|
|
||||||
|
printf("DropTarget_Drop\n");
|
||||||
|
*pdwEffect = DROPEFFECT_NONE;
|
||||||
|
|
||||||
|
if(SUCCEEDED(IDataObject_QueryGetData(pDataObj, &fmt)))
|
||||||
|
{
|
||||||
|
printf("QueryGetData OK\n");
|
||||||
|
if(SUCCEEDED(IDataObject_GetData(pDataObj, &fmt, &stgmed)))
|
||||||
|
{
|
||||||
|
HDROP drop = (HDROP) GlobalLock(stgmed.hGlobal);
|
||||||
|
const int count = DragQueryFileW(drop, 0xffffffff, NULL, 0);
|
||||||
|
char** paths = _glfw_calloc(count, sizeof(char*));
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf("GetData OK\n");
|
||||||
|
_glfwInputCursorPos(This->window, pt.x, pt.y);
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
const UINT length = DragQueryFileW(drop, i, NULL, 0);
|
||||||
|
WCHAR* buffer = _glfw_calloc((size_t) length + 1, sizeof(WCHAR));
|
||||||
|
|
||||||
|
DragQueryFileW(drop, i, buffer, length + 1);
|
||||||
|
paths[i] = _glfwCreateUTF8FromWideStringWin32(buffer);
|
||||||
|
|
||||||
|
_glfw_free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputDrop(This->window, count, (const char**) paths);
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
_glfw_free(paths[i]);
|
||||||
|
_glfw_free(paths);
|
||||||
|
|
||||||
|
GlobalUnlock(stgmed.hGlobal);
|
||||||
|
ReleaseStgMedium(&stgmed);
|
||||||
|
|
||||||
|
*pdwEffect = DROPEFFECT_COPY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user