实现拖拽源






4.75/5 (4投票s)
一个简单的分步文章,解释如何实现拖拽源
本文是 拖放界面 示例的一部分。
数据正在流向国外... 实现拖拽源
再次说明,这个想法的实现有两种不同的版本。
第一个版本使用用户自定义数据,可能更适合您的需求。
由于我们处理的是列表控件,因此使用标准格式(版本二)可能更合适。作为副作用,您现在可以将列表控件的内容拖到 Word、Excel、Visual Studio 或任何其他支持拖放的文本编辑器 - 你看到我笑了么?
两个版本非常相似。为了在我的应用程序中实现这两个版本,我使用了注册表设置。使用“剪贴板格式”菜单项或 *HKEY_CURRENT_USER\Software\Codeguru\Interface\DragDrop\Clipformat* 字符串来指定默认的“Common
”或字符串“Private
”。任何其他值都会导致错误消息并假定 Common 类型。
请遵循以下步骤
- 在视图中,添加一个类型为
UINT
的成员变量UINT m_DragDropFormat;
- 在视图的构造函数中,将其初始化为私有数据交换,使用
m_DragDropFormat = ::RegisterClipboardFormat("YourInterfaceClipboardFormat");
对于通用格式,只需使用
m_DragDorpFormat = CF_TEXT;
对您的目标放置对象执行相同的操作。在我们的例子中,它是第一步创建的模态对话框之一。
- 将以下行添加到 stdafx.h
#include <afxdisp.h> #include <afxole.h>
在应用程序的
InitInstance
函数中,在创建文档模板之前调用AfxOleInit()
。 - 在您的拖拽源类的源文件中(或在 stdafx.h 中,用于步骤 5 中使用的
CSharedFile
)包含#include <afxadv.h>
。 - (私有数据)使用类向导向您的视图添加一个消息处理程序,该处理程序响应列表控件的
LVN_BEGINDRAG
消息。这是函数OnBeginDragList1
的私有数据版本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; }
这是函数
OnBeginDragList1
的通用数据版本。它甚至允许您将数据拖到 Excel!(通用数据)//... 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 ...