65.9K
CodeProject 正在变化。 阅读更多。
Home

实现拖拽源

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (4投票s)

2000 年 11 月 10 日

CPOL
viewsIcon

129085

一个简单的分步文章,解释如何实现拖拽源

本文是 拖放界面 示例的一部分。

  1. 序列化 ASCII 数据
  2. 无模式子对话框
  3. 无模式兄弟对话框
  4. 拖放源
  5. MFC 目标
  6. TBTextTarget 类

数据正在流向国外... 实现拖拽源

再次说明,这个想法的实现有两种不同的版本。

第一个版本使用用户自定义数据,可能更适合您的需求。

由于我们处理的是列表控件,因此使用标准格式(版本二)可能更合适。作为副作用,您现在可以将列表控件的内容拖到 Word、Excel、Visual Studio 或任何其他支持拖放的文本编辑器 - 你看到我笑了么?

两个版本非常相似。为了在我的应用程序中实现这两个版本,我使用了注册表设置。使用“剪贴板格式”菜单项或 *HKEY_CURRENT_USER\Software\Codeguru\Interface\DragDrop\Clipformat* 字符串来指定默认的“Common”或字符串“Private”。任何其他值都会导致错误消息并假定 Common 类型。

请遵循以下步骤

  1. 在视图中,添加一个类型为 UINT 的成员变量
    UINT m_DragDropFormat;
  2. 在视图的构造函数中,将其初始化为私有数据交换,使用
    m_DragDropFormat = 
        ::RegisterClipboardFormat("YourInterfaceClipboardFormat");

    对于通用格式,只需使用

    m_DragDorpFormat = CF_TEXT;

    对您的目标放置对象执行相同的操作。在我们的例子中,它是第一步创建的模态对话框之一。

  3. 将以下行添加到 stdafx.h
    #include <afxdisp.h>
    #include <afxole.h>

    在应用程序的 InitInstance 函数中,在创建文档模板之前调用 AfxOleInit()

  4. 在您的拖拽源类的源文件中(或在 stdafx.h 中,用于步骤 5 中使用的 CSharedFile)包含 #include <afxadv.h>
  5. (私有数据)使用类向导向您的视图添加一个消息处理程序,该处理程序响应列表控件的 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 ...
© . All rights reserved.