Implementing Reusable Drag '& Drop Classes | CodeGuru

Implementing Reusable Drag ‘& Drop Classes

IDataObject,IEnumFORMATETC,IDropSource,IDropTarget,IDragSourceHelper,IDropTargetHelper Tools used: Microsoft. Platform SDK Whistler Beta 1 and VC++ 6.0 (SP5), WTL Platform used: Windows 2000 I tried to create as generic 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 […]

Written By
CodeGuru Staff
CodeGuru Staff
May 23, 2001
2 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

IDataObject,IEnumFORMATETC,IDropSource,IDropTarget,IDragSourceHelper,IDropTargetHelper

Tools used: Microsoft. Platform SDK Whistler Beta 1 and VC++ 6.0 (SP5), WTL

Platform used: Windows 2000


I tried to create as generic 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.

Example:



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
   // ...
}

Advertisement

References:

Downloads


Download demo project - 76 Kb

Download source - 6 Kb
CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.