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

实现一个拖放目标

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.27/5 (10投票s)

2000 年 11 月 10 日

viewsIcon

141314

downloadIcon

1828

循序渐进的文章,解释如何实现一个拖放目标

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

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

数据拖动即将到来... 拖放目标

你想象一下? 对,有不止一种可能性,这次我将给你三种。 一种用于你的私有数据,一种用于接收来自其他应用程序(如 Excel,WinWord 等)的通用数据,最后,我将给你 一个方便的类,你可以从中派生任何 MFC 对象,使其成为一个拖放目标。

从拖放的对象中获取数据,MFC 方法

我假设你想把你的 CFormViewCListControl 中一些行拖到本系列文章前面提到的一个模态对话框中。 在现实生活中,你可以使用这种方法来实现任何 CWnd 派生对象的拖放功能,无论是在模态对话框中还是不在。

第一步与实现拖放源时相同

  1. 对于你的拖放目标类,例如,基于我的 CDialog 的类 CDropDialog,添加一个 UINT 类型的成员变量
    UINT m_DragDropFormat;
  2. 在视图的构造函数中,将其初始化为与私有数据交换
    m_DragDropFormat = 
        ::RegisterClipboardFormat("YourInterfaceClipboardFormat");

    对于通用格式,只需使用

    m_DragDorpFormat = CF_TEXT;
  3. 将以下行添加到 stdafx.h
       #include <afxdisp.h>
       #include <afxole.h>
  4. 在应用程序的 InitInstance 函数中,在创建文档模板之前调用 AfxOleInit()
  5. 如果用作拖放目标的窗口是 CView 派生的,那么你现在很幸运,大部分工作已经完成。 在 OnInitialUpdate 函数中,调用 Register() 函数并覆盖 OnDragOverOnDrop 函数(实现与步骤 9 中的 CInterfaceDropTarget 相同)在“正常”情况下应该足够了 - 完成!
  6. 如果你有另一种目标,还需要做更多的工作。
  7. 使用 ClassWizard 创建一个从 MFC 类 COleDropTarget 派生的新的通用(!)类。 我称之为 CInterfaceDropTarget
  8. 创建并初始化一个 UINT m_DragDropFormat,如步骤 2 中所示。
  9. 创建 - 至少 - 函数 OnDragOverOnDrop
    DROPEFFECT CInterfaceDropTarget::OnDragOver (CWnd *pDrop, 
        COleDataObject* pDataObject, DWORD dwKeyState, CPoint point )
    {
        CFile *pFile = pDataObject->GetFileData(m_DragDropFormat);
        if (pFile != NULL)
            // perhaps some point checking here?
            return DROPEFFECT_COPY; // data fits
        else
            return DROPEFFECT_NONE; // data won't fit
    }
    
    BOOL CInterfaceDropTarget::OnDrop(CWnd *pDrop, 
        COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point )
    {
        CFile *pFile = pDataObject->GetFileData(m_DragDropFormat);
        if (pFile != NULL)
        {
            int number, colCou;
            CString Data;
            // perhaps some point checking first?
            TRY
            {
                CArchive ar(&file, CArchive::load);
                TRY
                {
                    if (DragDropFormat != CF_TEXT)
                    {
                        // "Serialize" your data object from the archive
                        // (yes, you may use YourObject.Serialize(ar) here!)
                        ar >> number;
                        ar >> colCou;
    
                        for (int i=0; i<colCou; i++)
                        {
                            ar >> Data ;
    #pragma message(__FILE__ " dont't forget to process Data here.....")
                        }
                    }
                    else
                    {
                        CString Data, t;
    
                        TRY
                        {
                            while(ar.ReadString(t))
                                Data += t + "\n";
                        }
    #pragma message(__FILE__ " ... and here!")
                        CATCH_ALL(eInnerMost)
                        {
    #ifdef _DEBUG
                            TCHAR szCause[255];
                            CString strFormatted;
                            eInnerMost->GetErrorMessage(szCause, 255);
                            strFormatted = _T("Exception: ");
                            strFormatted += szCause;
                            AfxMessageBox(strFormatted); 
    #endif //_DEBUG
                            ASSERT(FALSE);
                        }
                        END_CATCH_ALL;
                    }
                    ar.Close();
                }
                CATCH_ALL(eInner)
                {
                    // exception while reading
                    // from or closing the archive
                    ASSERT(FALSE);
                }
                END_CATCH_ALL;
            }
            CATCH_ALL(eOuter)
            {
                // exception in the destructor of ar
                ASSERT(FALSE);
            }
            END_CATCH_ALL;
            return TRUE;
        }
        return COleDropTarget::OnDrop(pDrop, 
                pDataObject, dropEffect, point);
    }
  10. 不要忘记在 OnDrop 函数中处理数据。 你应该将刚刚拖放的对象发送到你的 CWnd 类并在那里“做一些事情”。 该示例通过函数 ProcessData(CString data)ProcessData(int rowcount, int linecount, CString Data) 来实现这一点。
  11. 在用作拖放目标的 CWnd 派生类中,添加一个 CInterfaceDropTarget 类型的成员变量,例如,为了方便起见,将其命名为 m_DT
  12. 在此窗口存在的任何时候(例如:OnInitDialog 很好),调用 m_DTRegister 函数
    BOOL CDropDialog::OnInitDialog() 
    {
        CDialog::OnInitDialog();
       m_DT.Register(this);
       // the other stuff follows ....
    }

完成!

许可证

本文档没有附加明确的许可证,但可能在文章文本或下载文件中包含使用条款。 如果有疑问,请通过下面的讨论区与作者联系。 可以在这里找到作者可能使用的许可证列表。

© . All rights reserved.