mirror of
https://github.com/glfw/glfw.git
synced 2024-12-03 07:17:10 +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");
|
||||
}
|
||||
|
||||
_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;
|
||||
}
|
||||
|
||||
@ -191,6 +204,9 @@ static void freeLibraries(void)
|
||||
|
||||
if (_glfw.win32.ntdll.instance)
|
||||
_glfwPlatformFreeModule(_glfw.win32.ntdll.instance);
|
||||
|
||||
if (_glfw.win32.ole32.instance)
|
||||
_glfwPlatformFreeModule(_glfw.win32.ole32.instance);
|
||||
}
|
||||
|
||||
// Create key code translation tables
|
||||
@ -430,6 +446,27 @@ static GLFWbool createHelperWindow(void)
|
||||
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 //////
|
||||
@ -699,6 +736,9 @@ int _glfwInitWin32(void)
|
||||
if (!createHelperWindow())
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!initDragDrop())
|
||||
return GLFW_FALSE;
|
||||
|
||||
_glfwPollMonitorsWin32();
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
@ -708,6 +748,8 @@ void _glfwTerminateWin32(void)
|
||||
if (_glfw.win32.deviceNotificationHandle)
|
||||
UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
|
||||
|
||||
OleUninitialize();
|
||||
|
||||
if (_glfw.win32.helperWindowHandle)
|
||||
DestroyWindow(_glfw.win32.helperWindowHandle);
|
||||
if (_glfw.win32.helperWindowClass)
|
||||
|
@ -64,11 +64,15 @@
|
||||
// GLFW uses OEM cursor resources
|
||||
#define OEMRESOURCE
|
||||
|
||||
// define COM C object macros
|
||||
#define COBJMACROS
|
||||
|
||||
#include <wctype.h>
|
||||
#include <windows.h>
|
||||
#include <dinput.h>
|
||||
#include <xinput.h>
|
||||
#include <dbt.h>
|
||||
#include <ole2.h>
|
||||
|
||||
// HACK: Define macros that some windows.h variants don't
|
||||
#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);
|
||||
#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
|
||||
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
|
||||
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);
|
||||
@ -408,6 +428,13 @@ typedef struct _GLFWlibraryWGL
|
||||
GLFWbool ARB_context_flush_control;
|
||||
} _GLFWlibraryWGL;
|
||||
|
||||
typedef struct _GLFWdropTarget
|
||||
{
|
||||
IDropTargetVtbl* lpVtbl;
|
||||
ULONG cRefCount;
|
||||
_GLFWwindow* window;
|
||||
} _GLFWdropTarget;
|
||||
|
||||
// Win32-specific per-window data
|
||||
//
|
||||
typedef struct _GLFWwindowWin32
|
||||
@ -432,6 +459,8 @@ typedef struct _GLFWwindowWin32
|
||||
int lastCursorPosX, lastCursorPosY;
|
||||
// The last received high surrogate when decoding pairs of UTF-16 messages
|
||||
WCHAR highSurrogate;
|
||||
|
||||
_GLFWdropTarget dropTarget;
|
||||
} _GLFWwindowWin32;
|
||||
|
||||
// Win32-specific global data
|
||||
@ -455,6 +484,7 @@ typedef struct _GLFWlibraryWin32
|
||||
RAWINPUT* rawInput;
|
||||
int rawInputSize;
|
||||
UINT mouseTrailSize;
|
||||
IDropTargetVtbl dropTargetVtbl;
|
||||
|
||||
struct {
|
||||
HINSTANCE instance;
|
||||
@ -497,6 +527,15 @@ typedef struct _GLFWlibraryWin32
|
||||
HINSTANCE instance;
|
||||
PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_;
|
||||
} ntdll;
|
||||
|
||||
struct {
|
||||
HINSTANCE instance;
|
||||
|
||||
PFN_OleInitialize OleInitialize_;
|
||||
PFN_OleUninitialize OleUninitialize_;
|
||||
PFN_RegisterDragDrop RegisterDragDrop_;
|
||||
PFN_RevokeDragDrop RevokeDragDrop_;
|
||||
} ole32;
|
||||
} _GLFWlibraryWin32;
|
||||
|
||||
// Win32-specific per-monitor data
|
||||
@ -620,3 +659,11 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
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 <limits.h>
|
||||
#include <stdio.h> // TODO remove
|
||||
#include <stdlib.h>
|
||||
#include <string.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)
|
||||
{
|
||||
@ -1493,6 +1502,8 @@ void _glfwDestroyWindowWin32(_GLFWwindow* window)
|
||||
if (_glfw.win32.disabledCursorWindow == window)
|
||||
_glfw.win32.disabledCursorWindow = NULL;
|
||||
|
||||
RevokeDragDrop(window->win32.handle);
|
||||
|
||||
if (window->win32.handle)
|
||||
{
|
||||
RemovePropW(window->win32.handle, L"GLFW");
|
||||
@ -2452,3 +2463,119 @@ GLFWAPI HWND glfwGetWin32Window(GLFWwindow* 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