hi,
Fivewin can use REGISTERDRAGDROP() to use App "as Target" where i can drop to
i´m searching how to use App "as Source" to drag Data to "external" App, how
#include <windows.h>
#include <ole2.h>
#include <shlobj.h>
// Definir una estructura para almacenar los datos del destino de arrastre
typedef struct {
IDropTargetVtbl *lpVtbl; // Puntero a la tabla de funciones virtuales
DWORD refCount; // Contador de referencias
HWND hwnd; // Control de ventana asociado al destino de arrastre
BOOL isOver; // Indica si el cursor está sobre el destino de arrastre
BOOL allowDrop; // Indica si se permite soltar el objeto
IDataObject *dataObject; // Puntero al objeto de datos arrastrado
} DropTarget;
// Definir las funciones de la interfaz IDropTarget
HRESULT STDMETHODCALLTYPE QueryInterface (IDropTarget *, REFIID, void **);
ULONG STDMETHODCALLTYPE AddRef (IDropTarget *);
ULONG STDMETHODCALLTYPE Release (IDropTarget *);
HRESULT STDMETHODCALLTYPE DragEnter (IDropTarget *, IDataObject *, DWORD, POINTL, DWORD *);
HRESULT STDMETHODCALLTYPE DragOver (IDropTarget *, DWORD, POINTL, DWORD *);
HRESULT STDMETHODCALLTYPE DragLeave (IDropTarget *);
HRESULT STDMETHODCALLTYPE Drop (IDropTarget *, IDataObject *, DWORD, POINTL, DWORD *);
// Crear la tabla de funciones virtuales
static IDropTargetVtbl dropTargetVtbl = {
QueryInterface,
AddRef,
Release,
DragEnter,
DragOver,
DragLeave,
Drop
};
// Crear una instancia de la interfaz IDropTarget
DropTarget *CreateDropTarget (HWND hwnd) {
DropTarget *dropTarget = (DropTarget *) GlobalAlloc (GMEM_FIXED, sizeof (DropTarget));
dropTarget->lpVtbl = &dropTargetVtbl;
dropTarget->refCount = 1;
dropTarget->hwnd = hwnd;
dropTarget->isOver = FALSE;
dropTarget->allowDrop = FALSE;
dropTarget->dataObject = NULL;
return dropTarget;
}
// Implementar la función QueryInterface
HRESULT STDMETHODCALLTYPE QueryInterface (IDropTarget *this, REFIID riid, void **ppvObject) {
if (IsEqualIID (riid, &IID_IUnknown) || IsEqualIID (riid, &IID_IDropTarget)) {
this->lpVtbl->AddRef (this);
*ppvObject = this;
return S_OK;
}
else {
*ppvObject = NULL;
return E_NOINTERFACE;
}
}
// Implementar la función AddRef
ULONG STDMETHODCALLTYPE AddRef (IDropTarget *this) {
return InterlockedIncrement (&(((DropTarget *) this)->refCount));
}
// Implementar la función Release
ULONG STDMETHODCALLTYPE Release (IDropTarget *this) {
ULONG refCount = InterlockedDecrement (&(((DropTarget *) this)->refCount));
if (refCount == 0) {
GlobalFree (this);
return 0;
}
else {
return refCount;
}
}
// Implementar la función DragEnter
HRESULT STDMETHODCALLTYPE DragEnter (IDropTarget *this, IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) {
// Comprobar si el objeto de datos contiene archivos
FORMATETC formatEtc;
formatEtc.cfFormat = CF_HDROP;
formatEtc.ptd = NULL;
formatEtc.dwAspect = DVASPECT_CONTENT;
formatEtc.lindex = -1;
formatEtc.tymed = TYMED_HGLOBAL;
HRESULT hr = pDataObject->lpVtbl->QueryGetData (pDataObject, &formatEtc);
if (hr == S_OK) {
// Guardar una referencia al objeto de datos
((DropTarget *) this)->dataObject = pDataObject;
pDataObject->lpVtbl->AddRef (pDataObject);
// Indicar que el cursor está sobre el destino de arrastre
((DropTarget *) this)->isOver = TRUE;
// Indicar que se permite soltar el objeto
((DropTarget *) this)->allowDrop = TRUE;
// Establecer el efecto de la operación
*pdwEffect = DROPEFFECT_COPY;
}
else {
// Indicar que no se permite soltar el objeto
((DropTarget *) this)->allowDrop = FALSE;
// Establecer el efecto de la operación
*pdwEffect = DROPEFFECT_NONE;
}
return S_OK;
}
// Implementar la función DragOver
HRESULT STDMETHODCALLTYPE DragOver (IDropTarget *this, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) {
if (((DropTarget *) this)->isOver) {
if (((DropTarget *) this)->allowDrop) {
// Establecer el efecto de la operación
*pdwEffect = DROPEFFECT_COPY;
}
else {
// Establecer el efecto de la operación
*pdwEffect = DROPEFFECT_NONE;
}
}
return S_OK;
}
// Implementar la función DragLeave
HRESULT STDMETHODCALLTYPE DragLeave (IDropTarget *this) {
if (((DropTarget *) this)->isOver) {
// Liberar la referencia al objeto de datos
((DropTarget *) this)->dataObject->lpVtbl->Release (((DropTarget *) this)->dataObject);
// Indicar que el cursor ha salido del destino de arrastre
((DropTarget *) this)->isOver = FALSE;
}
return S_OK;
}
// Implementar la función Drop
HRESULT STDMETHODCALLTYPE Drop (IDropTarget *this, IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) {
if (((DropTarget *) this)->isOver) {
if (((DropTarget *) this)->allowDrop) {
// Obtener los nombres de los archivos arrastrados
FORMATETC formatEtc;
formatEtc.cfFormat = CF_HDROP;
formatEtc.ptd = NULL;
formatEtc.dwAspect = DVASPECT_CONTENT;
formatEtc.lindex = -1;
formatEtc.tymed = TYMED_HGLOBAL;
STGMEDIUM storageMedium;
HRESULT hr = pDataObject->lpVtbl->GetData (pDataObject, &formatEtc, &storageMedium);
if (SUCCEEDED (hr)) {
HDROP hDrop = (HDROP) GlobalLock (storageMedium.hGlobal);
if (hDrop != NULL) {
UINT fileCount = DragQueryFile (hDrop, 0xFFFFFFFF, NULL, 0);
for (UINT i = 0; i < fileCount; i++) {
TCHAR fileName[MAX_PATH];
if (DragQueryFile (hDrop, i, fileName, MAX_PATH) > 0) {
// Hacer algo con el nombre del archivo
MessageBox (((DropTarget *) this)->hwnd, fileName, TEXT ("Archivo arrastrado"), MB_OK);
}
}
GlobalUnlock (storageMedium.hGlobal);
DragFinish (hDrop);
}
ReleaseStgMedium (&storageMedium);
}
// Establecer el efecto de la operación
*pdwEffect = DROPEFFECT_COPY;
}
else {
// Establecer el efecto de la operación
*pdwEffect = DROPEFFECT_NONE;
}
// Liberar la referencia al objeto de datos
((DropTarget *) this)->dataObject->lpVtbl->Release (((DropTarget *) this)->dataObject);
// Indicar que el cursor ha salido del destino de arrastre
(
//
// MAIN.CPP
//
// DragSource
//
// Freeware written by J Brown 2004
//
// www.catch22.net
//
#define STRICT
#include <windows.h>
#include "resource.h"
#define APPNAME "IDropSource"
#pragma comment(linker, "/OPT:NOWIN98")
void BuildDrop(HWND, BOOL *, BOOL * );
HWND hwndMain;
HWND hwndEdit;
HINSTANCE hInstance;
WNDPROC OldEditWndProc;
HRESULT CreateDropSource(IDropSource **ppDropSource);
HRESULT CreateDataObject(FORMATETC *fmtetc, STGMEDIUM *stgmeds, UINT count, IDataObject **ppDataObject);
//
// Is the mouse cursor within the edit control's selected text?
//
// Return TRUE/FALSE
//
BOOL MouseInSelection(HWND hwndEdit, LPARAM MouseMsgParam)
{
DWORD nSelStart;
DWORD nSelEnd;
// get the selection inside the edit control
SendMessage(hwndEdit, EM_GETSEL, (WPARAM)&nSelStart, (LPARAM)&nSelEnd);
if(nSelStart != nSelEnd)
{
DWORD nCurPos;
// Get the cursor position the mouse has clicked on
nCurPos = SendMessage(hwndEdit, EM_CHARFROMPOS, 0, MouseMsgParam);
nCurPos = LOWORD(nCurPos);
// Did the mouse click inside the active selection?
return (nCurPos >= nSelStart && nCurPos < nSelEnd) ? TRUE : FALSE;
}
return FALSE;
}
//
// Remove any selection from the edit control
//
void ClearSelection(HWND hwndEdit)
{
SendMessage(hwndEdit, EM_SETSEL, -1, -1);
}
//
// Copy selected text to a HGLOBAL and return it
//
HGLOBAL CopySelection(HWND hwndEdit)
{
DWORD nSelStart, nSelEnd;
DWORD nSelLength, nEditLength;
HGLOBAL hMem;
char *ptr;
char *tmp;
SendMessage(hwndEdit, EM_GETSEL, (WPARAM)&nSelStart, (LPARAM)&nSelEnd);
nSelLength = nSelEnd - nSelStart;
// get the entire contents of the control
nEditLength = SendMessage(hwndEdit, EM_GETLIMITTEXT, 0, 0);
tmp = (char *)malloc(nEditLength);
SendMessage(hwndEdit, WM_GETTEXT, nEditLength, (LPARAM)tmp);
hMem = GlobalAlloc(GHND, nSelLength+1);
ptr = (char *)GlobalLock(hMem);
// copy the selected text and nul-terminate
memcpy(ptr, tmp+nSelStart, nSelLength);
ptr[nSelLength] = '\0';
GlobalUnlock(hMem);
free(tmp);
return hMem;
}
//
// Subclass window-procedure for EDIT control
//
LRESULT CALLBACK EditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static BOOL fMouseDown = FALSE;
static BOOL fDidDragDrop = FALSE;
switch(msg)
{
case WM_KEYDOWN:
// when ESCAPE is pressed clear the current selection
if(wParam == VK_ESCAPE)
ClearSelection(hwnd);
break;
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
// if the mouse is pressed when it is over a selection,
// then start a drag-drop as soon as the mouse moves next
if(MouseInSelection(hwndEdit, lParam))
{
fMouseDown = TRUE;
fDidDragDrop = FALSE;
SetCapture(hwnd);
return 0;
}
break;
case WM_SETCURSOR:
// set the mouse cursor to an ARROW when it intersects the
// current selection, or the default IBEAM otherwise
if((HWND)wParam == hwnd)
{
POINT pt;
GetCursorPos(&pt);
ScreenToClient(hwndEdit, &pt);
if(MouseInSelection(hwndEdit, MAKELPARAM(pt.x, pt.y)))
{
SetCursor(LoadCursor(0, MAKEINTRESOURCE(IDC_ARROW)));
}
else
{
SetCursor(LoadCursor(0, MAKEINTRESOURCE(IDC_IBEAM)));
}
}
return TRUE;
case WM_MOUSEMOVE:
// if the mouse is held down then start a drag-drop
if(fMouseDown)
{
BuildDrop( hwndEdit, &fMouseDown, &fDidDragDrop );
}
break;
case WM_LBUTTONUP:
// stop drag-drop from happening when the mouse is released.
if(fMouseDown)
{
ReleaseCapture();
fMouseDown = FALSE;
if(fDidDragDrop == FALSE)
ClearSelection(hwnd);
}
break;
}
return CallWindowProc(OldEditWndProc, hwnd, msg, wParam, lParam);
}
//
// Main Window message handler
//
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
// create a child-window EDIT control
hwndEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_WANTRETURN|WS_VSCROLL,
0,0,0,0, hwnd, 0, hInstance, 0);
// fixed-width font
SendMessage(hwndEdit, WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), 0);
// subclass the edit control so we can add drag+drop support to it
OldEditWndProc = (WNDPROC)SetWindowLong(hwndEdit, GWL_WNDPROC, (LONG)EditWndProc);
SetFocus(hwndEdit);
return TRUE;
case WM_COMMAND:
// react to menu messages
switch(LOWORD(wParam))
{
case IDM_FILE_EXIT:
CloseWindow(hwnd);
return 0;
case IDM_FILE_ABOUT:
MessageBox(hwnd, "IDropSource Test Application\r\n\r\n"
"Copyright(c) 2004 by Catch22 Productions\t\r\n"
"Written by J Brown.\r\n\r\n"
"Homepage at www.catch22.net", APPNAME, MB_ICONINFORMATION);
return 0;
}
break;
case WM_CLOSE:
// shut program down
DestroyWindow(hwnd);
PostQuitMessage(0);
return 0;
case WM_SIZE:
// resize editbox to fit in main window
MoveWindow(hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
void InitMainWnd()
{
WNDCLASSEX wc = { sizeof(wc) };
wc.lpfnWndProc = WndProc;
wc.lpszClassName = APPNAME;
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
wc.hInstance = hInstance;
RegisterClassEx(&wc);
}
void CreateMainWnd()
{
hwndMain = CreateWindowEx(0, APPNAME, APPNAME,
WS_VISIBLE|WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 512, 200, 0,0,
hInstance, 0);
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nShowCmd)
{
MSG msg;
hInstance = hInst;
// This program requires COM
OleInitialize(0);
InitMainWnd();
CreateMainWnd();
// message-pump
while(GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Shutdown COM
OleUninitialize();
return 0;
}
#include <windows.h>
extern "C" HGLOBAL CopySelection(HWND hwndEdit);
HRESULT CreateDropSource(IDropSource** ppDropSource);
HRESULT CreateDataObject(FORMATETC* fmtetc, STGMEDIUM* stgmeds, UINT count, IDataObject** ppDataObject);
extern "C" void BuildDrop(HWND hwndEdit, BOOL * fMouseDown, BOOL * fDidDragDrop)
{
IDataObject* pDataObject;
IDropSource* pDropSource;
DWORD dwEffect;
DWORD dwResult;
FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stgmed = { TYMED_HGLOBAL, { 0 }, 0 };
// transfer the current selection into the IDataObject
stgmed.hGlobal = CopySelection(hwndEdit);
// Create IDataObject and IDropSource COM objects
CreateDropSource(&pDropSource);
CreateDataObject(&fmtetc, &stgmed, 1, &pDataObject);
//
// ** ** ** The drag-drop operation starts here! ** ** **
//
dwResult = DoDragDrop(pDataObject, pDropSource, DROPEFFECT_COPY | DROPEFFECT_MOVE, &dwEffect);
// success!
if (dwResult == DRAGDROP_S_DROP)
{
if (dwEffect & DROPEFFECT_MOVE)
{
// remove selection from edit control
}
}
// cancelled
else if (dwResult == DRAGDROP_S_CANCEL)
{
}
pDataObject->Release();
pDropSource->Release();
ReleaseCapture();
* fMouseDown = FALSE;
* fDidDragDrop = TRUE;
}
//
// DATAOBJECT.CPP
//
// Implementation of the IDataObject COM interface
//
// By J Brown 2004
//
// www.catch22.net
//
#define STRICT
#include <windows.h>
// defined in enumformat.cpp
HRESULT CreateEnumFormatEtc(UINT nNumFormats, FORMATETC *pFormatEtc, IEnumFORMATETC **ppEnumFormatEtc);
class CDataObject : 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
//
CDataObject(FORMATETC *fmt, STGMEDIUM *stgmed, int count);
~CDataObject();
private:
int LookupFormatEtc(FORMATETC *pFormatEtc);
//
// any private members and functions
//
LONG m_lRefCount;
FORMATETC *m_pFormatEtc;
STGMEDIUM *m_pStgMedium;
LONG m_nNumFormats;
};
//
// Constructor
//
CDataObject::CDataObject(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
//
CDataObject::~CDataObject()
{
// cleanup
if(m_pFormatEtc) delete[] m_pFormatEtc;
if(m_pStgMedium) delete[] m_pStgMedium;
OutputDebugString("oof\n");
}
//
// IUnknown::AddRef
//
ULONG __stdcall CDataObject::AddRef(void)
{
// increment object reference count
return InterlockedIncrement(&m_lRefCount);
}
//
// IUnknown::Release
//
ULONG __stdcall CDataObject::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 CDataObject::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 CDataObject::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 CDataObject::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 CDataObject::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 CDataObject::QueryGetData (FORMATETC *pFormatEtc)
{
return (LookupFormatEtc(pFormatEtc) == -1) ? DV_E_FORMATETC : S_OK;
}
//
// IDataObject::GetCanonicalFormatEtc
//
HRESULT __stdcall CDataObject::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 CDataObject::SetData (FORMATETC *pFormatEtc, STGMEDIUM *pMedium, BOOL fRelease)
{
return E_NOTIMPL;
}
//
// IDataObject::EnumFormatEtc
//
HRESULT __stdcall CDataObject::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 CreateEnumFormatEtc(m_nNumFormats, m_pFormatEtc, ppEnumFormatEtc);
}
else
{
// the direction specified is not support for drag+drop
return E_NOTIMPL;
}
}
//
// IDataObject::DAdvise
//
HRESULT __stdcall CDataObject::DAdvise (FORMATETC *pFormatEtc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
{
return OLE_E_ADVISENOTSUPPORTED;
}
//
// IDataObject::DUnadvise
//
HRESULT __stdcall CDataObject::DUnadvise (DWORD dwConnection)
{
return OLE_E_ADVISENOTSUPPORTED;
}
//
// IDataObject::EnumDAdvise
//
HRESULT __stdcall CDataObject::EnumDAdvise (IEnumSTATDATA **ppEnumAdvise)
{
return OLE_E_ADVISENOTSUPPORTED;
}
//
// Helper function
//
HRESULT CreateDataObject (FORMATETC *fmtetc, STGMEDIUM *stgmeds, UINT count, IDataObject **ppDataObject)
{
if(ppDataObject == 0)
return E_INVALIDARG;
*ppDataObject = new CDataObject(fmtetc, stgmeds, count);
return (*ppDataObject) ? S_OK : E_OUTOFMEMORY;
}
//
// DROPSOURCE.CPP
//
// Implementation of the IDropSource COM interface
//
// By J Brown 2004
//
// www.catch22.net
//
#define STRICT
#include <windows.h>
class CDropSource : 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
//
CDropSource();
~CDropSource();
private:
//
// private members and functions
//
LONG m_lRefCount;
};
//
// Constructor
//
CDropSource::CDropSource()
{
m_lRefCount = 1;
}
//
// Destructor
//
CDropSource::~CDropSource()
{
}
//
// IUnknown::AddRef
//
ULONG __stdcall CDropSource::AddRef(void)
{
// increment object reference count
return InterlockedIncrement(&m_lRefCount);
}
//
// IUnknown::Release
//
ULONG __stdcall CDropSource::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 CDropSource::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;
}
}
//
// CDropSource::QueryContinueDrag
//
// Called by OLE whenever Escape/Control/Shift/Mouse buttons have changed
//
HRESULT __stdcall CDropSource::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;
}
//
// CDropSource::GiveFeedback
//
// Return either S_OK, or DRAGDROP_S_USEDEFAULTCURSORS to instruct OLE to use the
// default mouse cursor images
//
HRESULT __stdcall CDropSource::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 CDropSource();
return (*ppDropSource) ? S_OK : E_OUTOFMEMORY;
}
Antonio Linares wrote:Next is to properly use it from FWH and Harbour:
Return to FiveWin for Harbour/xHarbour
Users browsing this forum: No registered users and 76 guests