Home
Serializing ASCII Data
Modeless child dialog
Modeless sibling dialog
The drag source
The MFC drop target
The TBTextTarget class
VC6 flat toolbar support
| |
Data is going abroad... implementing the drag source
You'll find the source code in Interface.zip
Again 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_DragDropFormat = CF_TEXT;
Do the same to your drop target. In our case its either
of the modal dialogs created in step one.
- Add the following lines to stdafx.h
#include
<afxdisp.h>
#include <afxole.h>
In your applications 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;
// Create the drag&drop source and data objects
COleDropSource *pDropSource = new COleDropSource;
COleDataSource *pDataSource = new COleDataSource;
// now determine which rows are selected
// copy from the CListCtrl section
int idx = GetSelectedItem();
if (idx == -1 || !m_DragDropFormat)
{
// nothing selected (must be for dragging)
// or error while registering the clipboard format
ASSERT(FALSE);
return;
}
// now grab the data (here: the count and text)
// and serialize (hoho!) it into an clipboard archive
CString Data;
// getting the column count, thanks Zafir!
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
{
// Write the number of items and columns
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)
{
// exception while writing into or closing the archive
ASSERT(FALSE);
} END_CATCH_ALL;
}
CATCH_ALL(eMiddle)
{
// exception in the destructor of ar
ASSERT(FALSE);
} END_CATCH_ALL;
// put the file object into the data object
pDataSource->CacheGlobalData(m_DragDropFormat, file.Detach());
pDataSource->DoDragDrop(DROPEFFECT_MOVE|DROPEFFECT_COPY, NULL, pDropSource);
}
CATCH_ALL(eOuter)
{
// exception while destructing the file
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)
//... the same until
CSharedFile file;
TRY
{
CArchive ar(&file, CArchive::store);
TRY
{
// for CF_TEXT use a flat ASCII-stream
// using tabs as delimiter will cause Excel and others to
// understand us that we have a table
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)
// and do the rest as above ...
|