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 is Going Abroad... Implementing the Drag Source
Again, the implementation of this idea is in two different versions.
Version one uses user-defined data and may better fit your needs.
As we are dealing here with a list control, it may be considerable to use a standard format instead with version two. As a side-effect, you can now drag the contents of your list control to Word, Excel, Visual Studio, or any other drop-enabled texteditor - do I see you smile?
Both versions are very similar. To implement both of them with my application, I made use of the registry settings. Use the menu items at "Clipboard format" or the HKEY_CURRENT_USER\Software\Codeguru\Interface\DragDrop\Clipformat string to specify either the default of "Common
" or the string "Private
". Any other value will cause an error message and the assumption of the Common type.
Follow these steps:
- To the view, add a member-variable of type
UINT
:
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;
Do the same to your drop target. In our case, it’s either of the modal dialogs created in step one.
- Add the following lines to stdafx.h:
#include <afxdisp.h>
#include <afxole.h>
In your application’s InitInstance
function, make a call to AfxOleInit()
before creating the document template.
#include <afxadv.h>
in your drag-source-class source file (or in stdafx.h, it's for CSharedFile
used in Step 5). - (Private data) Use the Class Wizard to add a message handler to your view, which responds to the
LVN_BEGINDRAG
message of the list control. Here is the function OnBeginDragList1
for the private-data-version:
void CInterfaceView::OnBeginDragList1(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
*pResult = 0;
COleDropSource *pDropSource = new COleDropSource;
COleDataSource *pDataSource = new COleDataSource;
int idx = GetSelectedItem();
if (idx == -1 || !m_DragDropFormat)
{
ASSERT(FALSE);
return;
}
CString Data;
CHeaderCtrl* pHeader = (CHeaderCtrl*)m_Table.GetDlgItem(0);
int number = m_Table.GetSelectedCount(),
colCou = pHeader?pHeader->GetItemCount():0;
TRY
{
CSharedFile file(GMEM_ZEROINIT|GMEM_DDESHARE|GMEM_MOVEABLE);
TRY
{
CArchive ar(&file, CArchive::store);
TRY
{
ar << number;
ar << colCou
do
{
for (int i=0; i<colCou; i++)
{
Data = m_Table.GetItemText(idx, i);
ar << Data ;
}
idx = GetSelectedItem(idx);
} while (idx != -1);
ar.Close();
}
CATCH_ALL(eInner)
{
ASSERT(FALSE);
}
END_CATCH_ALL;
}
CATCH_ALL(eMiddle)
{
ASSERT(FALSE);
}
END_CATCH_ALL;
pDataSource->CacheGlobalData(m_DragDropFormat, file.Detach());
pDataSource->DoDragDrop(DROPEFFECT_MOVE|DROPEFFECT_COPY,
NULL, pDropSource);
}
CATCH_ALL(eOuter)
{
ASSERT(FALSE);
}
END_CATCH_ALL;
delete pDropSource;
delete pDataSource;
}
Here is the function OnBeginDragList1
for the common-data-version. It even allows you to drag your data to Excel! (common data)
CSharedFile file;
TRY
{
CArchive ar(&file, CArchive::store);
TRY
{
CString number;
number.Format("%i\n", m_Table.GetSelectedCount());
ar.WriteString(number);
do
{
Data.Empty();
for (int i=0; i<colCou; i++)
Data += m_Table.GetItemText(idx, i) + "\t";
ar.WriteString(Data + "\n");
idx = GetSelectedItem(idx);
} while (idx != -1);
ar.Close();
}
CATCH_ALL(eInner)