JD2022-TU1/main/extern/Camcam/TestApp/DragAndDrop.cpp

501 lines
10 KiB
C++

#define _WIN32_IE 0x0500
#define _WIN32_WINNT 0x0500
#include "resource.h"
#include <stdio.h>
#include <windows.h>
#include "Scene.h"
#define _WIN32_IE 0x0500
#define _WIN32_WINNT 0x0500
#include "resource.h"
#include <stdio.h>
#include <windows.h>
#include "Scene.h"
const ULONG MAX_FORMATS = 100;
class DragDataObject : public IDataObject
{
public:
//
// IUnknown members
//
HRESULT __stdcall QueryInterface (REFIID iid, void ** ppvObject);
ULONG __stdcall AddRef (void);
ULONG __stdcall Release (void);
//
// IDataObject members
//
HRESULT __stdcall GetData (FORMATETC *pFormatEtc, STGMEDIUM *pMedium);
HRESULT __stdcall GetDataHere (FORMATETC *pFormatEtc, STGMEDIUM *pMedium);
HRESULT __stdcall QueryGetData (FORMATETC *pFormatEtc);
HRESULT __stdcall GetCanonicalFormatEtc (FORMATETC *pFormatEct, FORMATETC *pFormatEtcOut);
HRESULT __stdcall SetData (FORMATETC *pFormatEtc, STGMEDIUM *pMedium, BOOL fRelease);
HRESULT __stdcall EnumFormatEtc (DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc);
HRESULT __stdcall DAdvise (FORMATETC *pFormatEtc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection);
HRESULT __stdcall DUnadvise (DWORD dwConnection);
HRESULT __stdcall EnumDAdvise (IEnumSTATDATA **ppEnumAdvise);
//
// Constructor / Destructor
//
DragDataObject(FORMATETC *fmt, STGMEDIUM *stgmed, int count);
~DragDataObject();
private:
int LookupFormatEtc(FORMATETC *pFormatEtc);
//
// any private members and functions
//
LONG m_lRefCount;
FORMATETC *m_pFormatEtc;
STGMEDIUM *m_pStgMedium;
LONG m_nNumFormats;
};
//
// Constructor
//
DragDataObject::DragDataObject(FORMATETC *fmtetc, STGMEDIUM *stgmed, int count)
{
m_lRefCount = 1;
m_nNumFormats = count;
m_pFormatEtc = new FORMATETC[count];
m_pStgMedium = new STGMEDIUM[count];
for(int i = 0; i < count; i++)
{
m_pFormatEtc[i] = fmtetc[i];
m_pStgMedium[i] = stgmed[i];
}
}
//
// Destructor
//
DragDataObject::~DragDataObject()
{
// cleanup
if(m_pFormatEtc) delete[] m_pFormatEtc;
if(m_pStgMedium) delete[] m_pStgMedium;
}
//
// IUnknown::AddRef
//
ULONG __stdcall DragDataObject::AddRef(void)
{
// increment object reference count
return InterlockedIncrement(&m_lRefCount);
}
//
// IUnknown::Release
//
ULONG __stdcall DragDataObject::Release(void)
{
// decrement object reference count
LONG count = InterlockedDecrement(&m_lRefCount);
if(count == 0)
{
delete this;
return 0;
}
else
{
return count;
}
}
//
// IUnknown::QueryInterface
//
HRESULT __stdcall DragDataObject::QueryInterface(REFIID iid, void **ppvObject)
{
// check to see what interface has been requested
if(iid == IID_IDataObject || iid == IID_IUnknown)
{
AddRef();
*ppvObject = this;
return S_OK;
}
else
{
*ppvObject = 0;
return E_NOINTERFACE;
}
}
HGLOBAL DupMem(HGLOBAL hMem)
{
// lock the source memory object
DWORD len = GlobalSize(hMem);
PVOID source = GlobalLock(hMem);
// create a fixed "global" block - i.e. just
// a regular lump of our process heap
PVOID dest = GlobalAlloc(GMEM_FIXED, len);
memcpy(dest, source, len);
GlobalUnlock(hMem);
return dest;
}
int DragDataObject::LookupFormatEtc(FORMATETC *pFormatEtc)
{
for(int i = 0; i < m_nNumFormats; i++)
{
if((pFormatEtc->tymed & m_pFormatEtc[i].tymed) &&
pFormatEtc->cfFormat == m_pFormatEtc[i].cfFormat &&
pFormatEtc->dwAspect == m_pFormatEtc[i].dwAspect)
{
return i;
}
}
return -1;
}
//
// IDataObject::GetData
//
HRESULT __stdcall DragDataObject::GetData (FORMATETC *pFormatEtc, STGMEDIUM *pMedium)
{
int idx;
//
// try to match the requested FORMATETC with one of our supported formats
//
if((idx = LookupFormatEtc(pFormatEtc)) == -1)
{
return DV_E_FORMATETC;
}
//
// found a match! transfer the data into the supplied storage-medium
//
pMedium->tymed = m_pFormatEtc[idx].tymed;
pMedium->pUnkForRelease = 0;
switch(m_pFormatEtc[idx].tymed)
{
case TYMED_HGLOBAL:
pMedium->hGlobal = DupMem(m_pStgMedium[idx].hGlobal);
//return S_OK;
break;
default:
return DV_E_FORMATETC;
}
return S_OK;
}
//
// IDataObject::GetDataHere
//
HRESULT __stdcall DragDataObject::GetDataHere (FORMATETC *pFormatEtc, STGMEDIUM *pMedium)
{
// GetDataHere is only required for IStream and IStorage mediums
// It is an error to call GetDataHere for things like HGLOBAL and other clipboard formats
//
// OleFlushClipboard
//
return DATA_E_FORMATETC;
}
//
// IDataObject::QueryGetData
//
// Called to see if the IDataObject supports the specified format of data
//
HRESULT __stdcall DragDataObject::QueryGetData (FORMATETC *pFormatEtc)
{
return (LookupFormatEtc(pFormatEtc) == -1) ? DV_E_FORMATETC : S_OK;
}
//
// IDataObject::GetCanonicalFormatEtc
//
HRESULT __stdcall DragDataObject::GetCanonicalFormatEtc (FORMATETC *pFormatEct, FORMATETC *pFormatEtcOut)
{
// Apparently we have to set this field to NULL even though we don't do anything else
pFormatEtcOut->ptd = NULL;
return E_NOTIMPL;
}
//
// IDataObject::SetData
//
HRESULT __stdcall DragDataObject::SetData (FORMATETC *pFormatEtc, STGMEDIUM *pMedium, BOOL fRelease)
{
return E_NOTIMPL;
}
//
// IDataObject::EnumFormatEtc
//
HRESULT __stdcall DragDataObject::EnumFormatEtc (DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc)
{
if(dwDirection == DATADIR_GET)
{
// for Win2k+ you can use the SHCreateStdEnumFmtEtc API call, however
// to support all Windows platforms we need to implement IEnumFormatEtc ourselves.
return SHCreateStdEnumFmtEtc(m_nNumFormats, m_pFormatEtc, ppEnumFormatEtc);
//return CreateEnumFormatEtc(m_nNumFormats, m_pFormatEtc, ppEnumFormatEtc);
}
else
{
// the direction specified is not support for drag+drop
return E_NOTIMPL;
}
}
//
// IDataObject::DAdvise
//
HRESULT __stdcall DragDataObject::DAdvise (FORMATETC *pFormatEtc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
{
return OLE_E_ADVISENOTSUPPORTED;
}
//
// IDataObject::DUnadvise
//
HRESULT __stdcall DragDataObject::DUnadvise (DWORD dwConnection)
{
return OLE_E_ADVISENOTSUPPORTED;
}
//
// IDataObject::EnumDAdvise
//
HRESULT __stdcall DragDataObject::EnumDAdvise (IEnumSTATDATA **ppEnumAdvise)
{
return OLE_E_ADVISENOTSUPPORTED;
}
HRESULT CreateDataObject(FORMATETC *fmtetc, STGMEDIUM *stgmeds, UINT count, IDataObject **ppDataObject)
{
if(ppDataObject == 0)
return E_INVALIDARG;
*ppDataObject = new DragDataObject(fmtetc, stgmeds, count);
return (*ppDataObject) ? S_OK : E_OUTOFMEMORY;
}
class DragDropSource : public IDropSource
{
public:
//
// IUnknown members
//
HRESULT __stdcall QueryInterface (REFIID iid, void ** ppvObject);
ULONG __stdcall AddRef (void);
ULONG __stdcall Release (void);
//
// IDropSource members
//
HRESULT __stdcall QueryContinueDrag (BOOL fEscapePressed, DWORD grfKeyState);
HRESULT __stdcall GiveFeedback (DWORD dwEffect);
//
// Constructor / Destructor
//
DragDropSource();
~DragDropSource();
private:
//
// private members and functions
//
LONG m_lRefCount;
};
//
// Constructor
//
DragDropSource::DragDropSource()
{
m_lRefCount = 1;
}
//
// Destructor
//
DragDropSource::~DragDropSource()
{
}
//
// IUnknown::AddRef
//
ULONG __stdcall DragDropSource::AddRef(void)
{
// increment object reference count
return InterlockedIncrement(&m_lRefCount);
}
//
// IUnknown::Release
//
ULONG __stdcall DragDropSource::Release(void)
{
// decrement object reference count
LONG count = InterlockedDecrement(&m_lRefCount);
if(count == 0)
{
delete this;
return 0;
}
else
{
return count;
}
}
//
// IUnknown::QueryInterface
//
HRESULT __stdcall DragDropSource::QueryInterface(REFIID iid, void **ppvObject)
{
// check to see what interface has been requested
if(iid == IID_IDropSource || iid == IID_IUnknown)
{
AddRef();
*ppvObject = this;
return S_OK;
}
else
{
*ppvObject = 0;
return E_NOINTERFACE;
}
}
//
// DragDropSource::QueryContinueDrag
//
// Called by OLE whenever Escape/Control/Shift/Mouse buttons have changed
//
HRESULT __stdcall DragDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
{
// if the <Escape> key has been pressed since the last call, cancel the drop
if(fEscapePressed == TRUE)
return DRAGDROP_S_CANCEL;
// if the <LeftMouse> button has been released, then do the drop!
if((grfKeyState & MK_LBUTTON) == 0)
return DRAGDROP_S_DROP;
// continue with the drag-drop
return S_OK;
}
//
// DragDropSource::GiveFeedback
//
// Return either S_OK, or DRAGDROP_S_USEDEFAULTCURSORS to instruct OLE to use the
// default mouse cursor images
//
HRESULT __stdcall DragDropSource::GiveFeedback(DWORD dwEffect)
{
return DRAGDROP_S_USEDEFAULTCURSORS;
}
//
// Helper routine to create an IDropSource object
//
HRESULT CreateDropSource(IDropSource **ppDropSource)
{
if(ppDropSource == 0)
return E_INVALIDARG;
*ppDropSource = new DragDropSource();
return (*ppDropSource) ? S_OK : E_OUTOFMEMORY;
}
int DragAndDrop(char *path, bool moveFiles)
{
DWORD dwEffect;
DWORD dwResult;
IDataObject *pDataObject;
IDropSource *pDropSource;
if (!OleInitialize(0) != S_OK)
return 0;
int so_hdrop = sizeof (DROPFILES);
int so_buff = so_hdrop + strlen (path) + 2; // 2 NULLS at end
HGLOBAL hglobal = GlobalAlloc (GMEM_SHARE | GHND | GMEM_ZEROINIT, so_buff);
DROPFILES *dropdat = (DROPFILES *) GlobalLock (hglobal);
dropdat->pFiles = sizeof(DROPFILES);
dropdat->fWide = 0;
char *cp = ((char *)dropdat) + so_hdrop;
strcpy (cp, path);
GlobalUnlock (hglobal);
FORMATETC format;
STGMEDIUM store;
memset(&format, 0, sizeof(format));
format.cfFormat = CF_HDROP;
format.dwAspect = DVASPECT_CONTENT;
format.lindex = -1;
format.tymed = TYMED_HGLOBAL;
memset(&store, 0, sizeof(store));
store.tymed = TYMED_HGLOBAL;
store.hGlobal = hglobal;
CreateDataObject(&format, &store, 1, &pDataObject);
CreateDropSource(&pDropSource);
int dragArgs = DROPEFFECT_COPY;
if (moveFiles) dragArgs |= DROPEFFECT_MOVE;
dwResult = DoDragDrop(pDataObject, pDropSource, dragArgs, &dwEffect);
GlobalFree ( hglobal );
OleUninitialize();
return 1;
}