Created
February 1, 2023 20:28
-
-
Save hb3p8/0f689bb2cc50acc58144cd501a700f46 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <ole2.h> | |
#include <ShObjIdl.h> | |
#include <vector> | |
#include <string> | |
class CDropTarget : public IDropTarget | |
{ | |
public: | |
CDropTarget() {}; | |
~CDropTarget() {}; | |
// IUnknown methods | |
HRESULT __stdcall QueryInterface(REFIID iid, void** ppvObject); | |
ULONG __stdcall AddRef(); | |
ULONG __stdcall Release(); | |
// IDropTarget methods | |
HRESULT __stdcall DragEnter(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect); | |
HRESULT __stdcall DragOver(DWORD grfKeyState, POINTL pt, DWORD* pdwEffect); | |
HRESULT __stdcall DragLeave(); | |
HRESULT __stdcall Drop(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect); | |
int m_RefCount = 0; | |
DropHandler m_dropHandler; | |
std::vector<std::vector<char> > m_filenames; | |
}; | |
namespace lt { | |
// This one is called externally | |
bool RegisterDragDropWin (HWND__* in_windowHandle, const DropHandler& in_handler) | |
{ | |
if (::OleInitialize (NULL) != S_OK) | |
{ | |
return false; | |
} | |
CDropTarget* pDropTarget = new CDropTarget; | |
pDropTarget->m_dropHandler = in_handler; | |
return ::RegisterDragDrop (in_windowHandle, pDropTarget) == S_OK; | |
} | |
} // namespace lt | |
HRESULT CDropTarget::QueryInterface (REFIID iid, void** ppvObject) | |
{ | |
if (iid == IID_IUnknown || iid == IID_IDropTarget) | |
{ | |
*ppvObject = this; | |
AddRef(); | |
return S_OK; | |
} | |
return E_NOINTERFACE; | |
} | |
ULONG CDropTarget::AddRef() | |
{ | |
return ++m_RefCount; | |
} | |
ULONG CDropTarget::Release() | |
{ | |
if (--m_RefCount == 0) | |
{ | |
delete this; | |
return 0; | |
} | |
return m_RefCount; | |
} | |
void FetchFileNames (IDataObject* pDataObj, std::vector<std::vector<char> >& out_filenames) | |
{ | |
out_filenames.clear(); | |
FORMATETC format = { CF_HDROP, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; | |
STGMEDIUM stg; | |
if (SUCCEEDED(pDataObj->GetData(&format, &stg))) | |
{ | |
HDROP hDrop = (HDROP)stg.hGlobal; | |
UINT count = ::DragQueryFileW(hDrop, 0xFFFFFFFF, nullptr, 0); | |
for (UINT i = 0; i < count; i++) | |
{ | |
UINT num_chars = ::DragQueryFileW(hDrop, i, nullptr, 0) + 1; | |
WCHAR* buffer = new WCHAR[num_chars]; | |
::DragQueryFileW (hDrop, i, buffer, num_chars); | |
const int bytes_needed = WideCharToMultiByte (CP_UTF8, 0, buffer, -1, NULL, 0, NULL, NULL); | |
out_filenames.emplace_back (bytes_needed, '\0'); | |
WideCharToMultiByte (CP_UTF8, 0, buffer, -1, out_filenames.back().data(), bytes_needed, NULL, NULL); | |
delete[] buffer; | |
} | |
::DragFinish (hDrop); | |
} | |
// release the data object | |
ReleaseStgMedium (&stg); | |
} | |
HRESULT CDropTarget::DragEnter (IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) | |
{ | |
GetGuiState().fileDropHovering = true; | |
FetchFileNames (pDataObj, m_filenames); | |
// Can use names of dragged files here as well | |
return S_OK; | |
} | |
HRESULT CDropTarget::DragOver (DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) | |
{ | |
GetGuiState().fileDropHovering = true; | |
return S_OK; | |
} | |
HRESULT CDropTarget::DragLeave() | |
{ | |
GetGuiState().fileDropHovering = false; | |
return S_OK; | |
} | |
HRESULT CDropTarget::Drop (IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) | |
{ | |
FetchFileNames (pDataObj, m_filenames); | |
if (m_filenames.size() > 0) | |
{ | |
m_dropHandler (m_filenames[0].data()); | |
} | |
return S_OK; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The code might have some bits from sokol_app.h