Archive:
January - 2010
November - 2009
October - 2009
September - 2009
August - 2009
July - 2009
June - 2009
April - 2009
March - 2009
January - 2009
May - 2008
April - 2008
March - 2008
October - 2007
August - 2007
July - 2007
June - 2007
May - 2007
April - 2007
December - 2006
November - 2006
September - 2006
August - 2006
July - 2006
March - 2006
February - 2006
January - 2006
December - 2005
November - 2005
October - 2005
September - 2005
August - 2005
July - 2005
June - 2005
May - 2005
April - 2005
February - 2005
January - 2005
December - 2004
November - 2004
October - 2004
September - 2004
August - 2004
July - 2004
June - 2004
May - 2004
April - 2004
March - 2004
Simple Drag-andDrop for Filenames

by Jonathan Hays

 

(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;

}