Implementing a Drop Target






4.27/5 (10 votes)
Nov 10, 2000

140803

1818
Simple step by step article explaining how to implement a drop target
This article is part of the drag and drop interface samples.
- Serializing ASCII Data
- Modeless child dialog
- Modeless sibling dialog
- The drag source
- The MFC drop target
- The TBTextTarget class
Data Drag is Coming to Town... The Drop Target
You imagine? Right, there's more than one possibility, this time I'll give you three. One for your private data, one for the common data in order to receive data from other applications like Excel, WinWord, etc. and at last, I'll give you a handy-dandy class you can derive ANY MFC object from, to make it a drop target.
Getting the Data from the Dropped Object, the MFC Way
I assume you want to drag the contents of some rows of a CListControl
of your CFormView
into one of the modal dialogs mentioned earlier in this article series. In real-life, you can use this approach to implement the drop functions to any CWnd
-derived object, whether in the modal dialog or not.
The first steps are the same as done when implementing the drop source:
- To your drop target class, e.g., my
CDialog
based classCDropDialog
, add a member variable of typeUINT
:UINT m_DragDropFormat;
- In the constructor of the view, initialize it for private data exchange with:
m_DragDropFormat = ::RegisterClipboardFormat("YourInterfaceClipboardFormat");
and for the common format, just use:
m_DragDorpFormat = CF_TEXT;
- Add the following lines to stdafx.h:
#include <afxdisp.h> #include <afxole.h>
- In your application's
InitInstance
function, make a call toAfxOleInit()
before creating the document template. - If the window used as drop target is
CView
-derived, you are now in luck, most of it is at the hand. In theOnInitialUpdate
function, call theRegister()
function and overwriting the functionsOnDragOver
andOnDrop
(implementation same asCInterfaceDropTarget
in step 9) should be enough in "normal" cases - READY! - If you have another kind of target, there's some more work.
- Use the
ClassWizard
to create a new generic(!) class derived from the MFC(!) classCOleDropTarget
. I call itCInterfaceDropTarget
. - Create and initialize a
UINT m_DragDropFormat
as in step 2. - Create - at least - the functions
OnDragOver
andOnDrop
.DROPEFFECT CInterfaceDropTarget::OnDragOver (CWnd *pDrop, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point ) { CFile *pFile = pDataObject->GetFileData(m_DragDropFormat); if (pFile != NULL) // perhaps some point checking here? return DROPEFFECT_COPY; // data fits else return DROPEFFECT_NONE; // data won't fit } BOOL CInterfaceDropTarget::OnDrop(CWnd *pDrop, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point ) { CFile *pFile = pDataObject->GetFileData(m_DragDropFormat); if (pFile != NULL) { int number, colCou; CString Data; // perhaps some point checking first? TRY { CArchive ar(&file, CArchive::load); TRY { if (DragDropFormat != CF_TEXT) { // "Serialize" your data object from the archive // (yes, you may use YourObject.Serialize(ar) here!) ar >> number; ar >> colCou; for (int i=0; i<colCou; i++) { ar >> Data ; #pragma message(__FILE__ " dont't forget to process Data here.....") } } else { CString Data, t; TRY { while(ar.ReadString(t)) Data += t + "\n"; } #pragma message(__FILE__ " ... and here!") CATCH_ALL(eInnerMost) { #ifdef _DEBUG TCHAR szCause[255]; CString strFormatted; eInnerMost->GetErrorMessage(szCause, 255); strFormatted = _T("Exception: "); strFormatted += szCause; AfxMessageBox(strFormatted); #endif //_DEBUG ASSERT(FALSE); } END_CATCH_ALL; } ar.Close(); } CATCH_ALL(eInner) { // exception while reading // from or closing the archive ASSERT(FALSE); } END_CATCH_ALL; } CATCH_ALL(eOuter) { // exception in the destructor of ar ASSERT(FALSE); } END_CATCH_ALL; return TRUE; } return COleDropTarget::OnDrop(pDrop, pDataObject, dropEffect, point); }
- Don't forget to process the data in the
OnDrop
function. You should send the just-dropped-object to yourCWnd
-class and "do something" with it there. The example does this with the functionsProcessData(CString data)
andProcessData(int rowcount, int linecount, CString Data)
. - In the
CWnd
-derived class used as drop target, add a member variable of typeCInterfaceDropTarget
, for example's sake, name itm_DT
. - At any point where this window exists (for example:
OnInitDialog
is great), call theRegister
function ofm_DT
:BOOL CDropDialog::OnInitDialog() { CDialog::OnInitDialog(); m_DT.Register(this); // the other stuff follows .... }
Done!
License
This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below. A list of licenses authors might use can be found here.