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, its 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)