Click here to Skip to main content
Click here to Skip to main content

Implementing Reusable Drag & Drop Classes

By , 4 Jun 2001
 

Introduction

I tried to create as generic a Drag and Drop classes as possible. Here is what I came up with. I think it's a good starting point if you're looking to add drag and drop support to your app.

The demo project has sample code for various clipboard formats:

  • CF_TEXT
  • CF_HDROP
  • CF_BITMAP
  • CF_DIB
  • CF_ENHMETAFILE

and MEDIUMs

  • TYMED_HGLOBAL
  • TYMED_ISTREAM
  • TYMED_ENHMF
  • TYMED_GDI.

Some screenshots of image drag and drop from static window:


(Fig. 1. Dragging from static window to WordPad)

(Fig. 2. Using Clipboard)

(Fig. 3. Pasting the above clipboard contents into WordPad)

Usage:

To enable your window as a DropTarget:

  • Derive a class from CIDropTarget.
  • Override OnDrop. Return true or false from this method. If true, base class will free the medium. If false, it won't free the medium.
  • Call ::RegisterDragDrop for your window.
  • Add Supported formats by calling CIDropTarget::AddSuportedFormat.
  • Optionally override other methods such as DragOver and DragLeave.
    I used it for the tree to highlight the current item.

Example:

class CTreeDropTarget : public CIDropTarget
{
public:
      virtual bool OnDrop(FORMATETC* pFmtEtc, STGMEDIUM& medium, DWORD *pdwEffect)
      {
            if(pFmtEtc->cfFormat == CF_TEXT && medium.tymed == TYMED_HGLOBAL)
            {
              // Handle it
            }
          return true;
      }
     // etc...
};

In your Window derived class create a member of CTreeDropTarget. Then initialize it like this:

{
// ...
m_pDropTarget = new CTreeDropTarget(m_hWnd);
RegisterDragDrop(m_hWnd,m_pDropTarget);
// create the supported formats:
FORMATETC ftetc={0}; 
ftetc.cfFormat = CF_TEXT; 
ftetc.dwAspect = DVASPECT_CONTENT; 
ftetc.lindex = -1; 
ftetc.tymed = TYMED_HGLOBAL; 
m_pDropTarget->AddSuportedFormat(ftetc); 
ftetc.cfFormat=CF_HDROP; 
m_pDropTarget->AddSuportedFormat(ftetc);
// ...
}

That's all for drop target.

To enable your window as the Drag and Drop source:

  • Catch the Windows message that initiates the drag and drop such as TVN_BEGINDRAG.
  • In the message function handler create new CIDataObject and CIDropSource.
  • Create the clipboard formats and medium for those formats.
  • Call SetData to add the clipboard formats and medium to DataObject. Second parameter to SetData indicates if DataObject should take the ownership of medium or not. If set to TRUE, then DataObject takes the ownership of your medium, you don't need to free it. Otherwise it will make a copy of your medium without releasing the one you gave it.

Eaxmple:

 LRESULT OnBegindrag(...)
{
   CIDropSource* pdsrc = new CIDropSource;
   CIDataObject* pdobj = new CIDataObject(pdsrc);
   // Init the supported format
   FORMATETC fmtetc = {0}; 
   fmtetc.cfFormat = CF_TEXT; 
   fmtetc.dwAspect = DVASPECT_CONTENT; 
   fmtetc.lindex = -1; 
   fmtetc.tymed = TYMED_HGLOBAL;
  // Init the medium used
  STGMEDIUM medium = {0};
  medium.tymed = TYMED_HGLOBAL;
  // medium.hGlobal = init to something
  // Add it to DataObject
  pdobj->SetData(&fmtetc,&medium,TRUE); // Release the medium for me
  // add more formats and medium if needed
  // Initiate the Drag & Drop
  ::DoDragDrop(pdobj, pdsrc, DROPEFFECT_COPY, &dwEffect);
} 

To use the shell's drag image manager (comes with Windows 2000):

You don't need to add the support for it if you are acting as drop target. It is encapsulated in CIDropTarget class.
If you're acting as data source:

  • Create an instance of CDragSourceHelper before calling ::DoDragDrop.
  • Call CDragSourceHelper::InitializeFromWindow or CDragSourceHelper::InitializeFromBitmap.

Adding the Copy/Paste through clipboard is not much work either.

Example:

LRESULT OnContextMenu(...)
{
  // ...
   CIDataObject* pdobj = new CIDataObject(NULL);  
   // Init FORMATETC and STGMEDIUM just like before
   // Add the format and medium to Dataobject
  pdobj->SetData(&fmtetc,&medium,TRUE);
  // Add data to clipboard
  OleSetClipboard(pdobj);
  OleFlushClipboard(); //render the data on clipboard, so it's available even if we close the app 
 // ...
}

References:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Leon Finker
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generaldrag Outlook attachmemberdevcdd22 Dec '06 - 4:12 
It does not work, when drag Outlook attachCry | :((
GeneralRe: drag Outlook attachmemberdevcdd24 Dec '06 - 2:54 
I'm figured out Wink | ;) http://mobile.infan.ru/files/d/dragdrop_demo.zip[^]
QuestionHow to cut filemembernhoc_conxauxi18 Aug '06 - 2:44 
VC6.0
My Application: the same window explore
I cut 2 files in window explore, then in my application
I paste them there. How to know that:
1. 2 files are cutting
2. Path is exist
3. ListCtrl control: how to sort folders are top, files are bottom
Thanks

QuestionHow to cut filemembernhoc_conxauxi18 Aug '06 - 2:36 
VC6.0
My application: the same window explore
I cut 2 files in window explore, then in my application I paste them there. How to know that:
1. these files is cutting. Which attribute?
2. path is exist. Which function?
3. ListCtrl : how to sort folders is top, files is bottom as window explore

GeneralCut filemembernhoc_conxauxi18 Aug '06 - 2:25 
VC6.0(MFC): My Application: the same window explore
1.I cut 1 file in window explore, then in my application I paste it. How to know "that file is cutting"? Which attribute?
2.How to know " a path is exist ?".Which function
3.ListCtrl control : how to sort to folders is top, files is bottom?
Thanks
 


QuestionIssues with the drag images.memberoptikflux2 Nov '05 - 14:12 
I'm using Windows XP SP2 and I don't get drag images to show up in the demo project. I can get them to show up in the treeview if I create an imagelist and assign it into the tree. - I don't need to add any images to the list, just creating and assigning is enough.
 
But then a different problem manifests. If the dragsource creates an image, the hit test doesn't find any tree items. The test works just fine if we don't create the drag image, but if we do...
 
I'm not even sure WHY it would be failing. Does the hit test window somehow consider the drag image to be part of the window, and so the point falls inside the rect of the image? I've tried offsetting the drag image, but to no avail.
 
Any ideas?
 

(Other than that, great set of classes Smile | :) )
AnswerRe: Issues with the drag images.membermrmcafee16 Mar '06 - 6:54 
I believe the problem w/ no 'drag images' has to do w/ the Windows Display Properties >> Effects tab ---> 'Show window contents while dragging' checkbox. If it is not set, no drag images. I had the same problem until I checked this box.
GeneralCompile bug in ATL Visual C++ .NETmemberthewizardcode15 Oct '05 - 9:10 
Hello:
 
I download this example. I drop in the DragDropImpl.h and DragDropImpl.cpp. I get a compile errors.
 
DragDropImpl.cpp(606) : fatal error C1010: unexpected end of file while looking for precompiled header directive
 
Can any one point out what need to be change to get it compile.
 
Mike
QuestionHow to use DragDropImpl.h and DragDropImpl.cpp in MFC projectmemberchinkuanyeh3 Oct '04 - 6:33 
Does anybody know how to use DragDropImpl.h and DragDropImpl.cpp in MFC project? It didn't compile ok when I added both files to my MFC project.
Thanks for your help...
GeneralDrag images don't show on W2K Server part IImemberJD_VIN28 Aug '04 - 10:50 
Hello
 
I have one problem. For some reason IDragSourceHelper::InitializeFromBitmap always return E_FAIL. It's seems IDragSourceHelper doesn't work at all on W2K Server (maybe on 2003 Server too ?). At the same time this code work prefect on w2k professional and windows XP.
 
Any suggestions?

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 5 Jun 2001
Article Copyright 2001 by Leon Finker
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid