|
(Adapted from tech-tip article written for Windows Developer
Journal.)
I often have a need to implement simple filename
drag-and-drop features without going through the whole complex OLE
solution. Unfortunately, the
information for implementing this in a simple manner is always obfuscated
inside MSDN and other books on the subject.
After much traipsing through code examples and overly complicated APIs,
I came up with the C++ class in Figure 1.
Whenever I need to use it, I simply derive from the MyDropTarget class
and over-ride the pure virtual function FileDroppedOnWindow().
The class will work with child windows, as well as parent
windows, making MyDropTarget especially useful for implementing drag-and-drop
in dialog edit boxes. Please note that
to simplify the code listing, I have not implemented proper COM reference
counting. Also note that it is up to
the application to call OleInitialize() and OleUninitialize().
Figure 1: A class for filename drag
and drop
Class
MyDropTarget : public IDropTarget
{
public:
MyDropTarget(HWND
hwnd);
virtual
~MyDropTarget();
virtual
void FileDroppedOnWindow(const char* file) = 0;
protected:
HRESULT
__stdcall Drop(IDataObject*,DWORD,_POINTL,DWORD*);
HRESULT
__stdcall DragEnter(IDataObject*,DWORD,_POINTL,DWORD*){return 0;}
HRESULT
__stdcall DragOver(DWORD,_POINTL,DWORD*){return 0;}
HRESULT
__stdcall DragLeave(){return 0;}
HRESULT
__stdcall QueryInterface,REFIID,void**){return 0;}
ULONG
__stdcall AddRef(){return 1;}
ULONG
__stdcall Release(){return 1;}
private:
HWND
itsHwnd;
};
MyDropTarget::MyDropTarget(HWND
hwnd) :
ItsHwnd(hwnd)
{
HRESULT result =
RegisterDragDrop(itsHwnd,this);
ASSERT(SUCCEEDED(result));
}
MyDropTarget::~MyDropTarget()
{
RevokeDragDrop(itsHwnd);
}
HRESULT
MyDropTarget::Drop(IDataObject* pdto,DWORD,POINTL,DWORD*)
{
FORMATETC format;
format.cfFormat = CF_HDROP;
format.dwAspect =
DVASPECT_CONTENT;
format.ptd = NULL;
format.lindex = -1;
format.tymed = TYMED_HGLOBAL;
STGMEDIUM medium;
HRESULT result =
pdto->GetData(&format, &medium);
if (result == S_OK)
{
HDROP
hDrop = (HDROP)medium.hGlobal;
int
fileCount = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
int
nameLength;
char
buffer[MAX_PATH];
for
(int x = 0; x < fileCount; x++)
{
nameLength =
DragQueryFile(hDrop,x,NULL,0);
DragQueryFile(hDrop, x, buffer,
nameLength + 1);
FileDroppedOnWindow(buffer);
}
GlobalFree(hDrop);
}
return result;
}
|