感谢您使用微软产品。请参看以下网页:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/HTML/vcconexplorerstyleapplications.aspMSDN里有一个很好的例程:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcsample98/html/_sample_mfc_cmnctrl1.asp
- 微软全球技术中心 VC技术支持本贴子以“现状”提供且没有任何担保,同时也没有授予任何权利。具体事项可参见使用条款(http://support.microsoft.com/directory/worldwide/zh-cn/community/terms_chs.asp)。
为了为您创建更好的讨论环境,请参加我们的用户满意度调查(http://support.microsoft.com/directory/worldwide/zh-cn/community/survey.asp?key=(S,49854782))。

解决方案 »

  1.   

    CTreeViewExt是MFC使用者可重用的类,该类由CTreeView派生,可以用在文档-视结构的应用程序中,并且支持Drag&Drop。
    使用者所需要做的仅仅是将文件加到AppWizard产生的工程中,(CTreeView为基类)并且将CTreeView替换为CTreeViewExt。并重载三个Virtual Function。
    (WenYY:这很简单吧,下面是源代码,我会在必要的地方加上注释,但由于原作者并未加,所以如果有出入请原谅,作者定义了三处虚拟函数,其作用是让使用者重载后,加入自己的判断条件和结果处理的功能,很巧妙的思想:
          CopyItemProperties
          IsItemCanBeDroppedOn(HTREEITEM hSource, HTREEITEM hTarget);
          BOOL ItemCanBeDragged(HTREEITEM hItem);//检查是否可以对该ITEM实施Drag&Drop
    )
    Header file
    #if !defined(AFX_TREEVIEWEXT_H__99D8F6F8_79F0_11D1_8DC6_0000E8125FE5__INCLUDED_)
    #define AFX_TREEVIEWEXT_H__99D8F6F8_79F0_11D1_8DC6_0000E8125FE5__INCLUDED_
    #if _MSC_VER >= 1000
    #pragma once
    #endif // _MSC_VER >= 1000
    // TreeViewExt.h : header file
    //
    /////////////////////////////////////////
    // CTreeViewExt view
    class CTreeViewExt : public CTreeView
    {
    protected:
        CTreeViewExt(); // protected constructor used by dynamic creation
        DECLARE_DYNCREATE(CTreeViewExt)
    // Attributes
    public:
    // Operations
    public:
    // Overrides
        // ClassWizard generated virtual function overrides
        //{{AFX_VIRTUAL(CTreeViewExt)
        protected:
        virtual void OnDraw(CDC* pDC); // overridden to draw this view
        //}}AFX_VIRTUAL
    // Implementation
    protected:
        HTREEITEM m_hDraggedItem;
        BOOL m_bDraggingNow; //标记
        CImageList *m_pDragImageList;
        virtual ~CTreeViewExt();
    #ifdef _DEBUG
        virtual void AssertValid() const;
        virtual void Dump(CDumpContext& dc) const;
    #endif
        // Generated message map functions
    protected:
        virtual void CopyItemProperties(HTREEITEM hNewItem, HTREEITEM hDraggedItem);
        virtual BOOL IsItemCanBeDroppedOn(HTREEITEM hSource, HTREEITEM hTarget);
        virtual BOOL ItemCanBeDragged(HTREEITEM hItem);//检查是否可以对该ITEM实施Drag&Drop
        //{{AFX_MSG(CTreeViewExt)
        afx_msg void OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult);//必须重载的函数
        afx_msg void OnMouseMove(UINT nFlags, CPoint point);
        afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
        //}}AFX_MSG
        DECLARE_MESSAGE_MAP()
    };
    /////////////////////////////////////////
    //{{AFX_INSERT_LOCATION}}
    // Microsoft Developer Studio will insert additional declarations immediately before the previous line.
    #endif // !defined(AFX_TREEVIEWEXT_H__99D8F6F8_79F0_11D1_8DC6_0000E8125FE5__INCLUDED_)
    Implementation file
    // TreeViewExt.cpp : implementation file
    //
    #include "stdafx.h"
    #include "TreeViewExt.h"
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    /////////////////////////////////////////
    // CTreeViewExt
    IMPLEMENT_DYNCREATE(CTreeViewExt, CTreeView)
    CTreeViewExt::CTreeViewExt()
    {
        m_bDraggingNow = FALSE;
        m_hDraggedItem = NULL;
        m_pDragImageList = NULL;
    }
    CTreeViewExt::~CTreeViewExt()
    {
    }
    BEGIN_MESSAGE_MAP(CTreeViewExt, CTreeView)
        //{{AFX_MSG_MAP(CTreeViewExt)
        ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBegindrag)
        ON_WM_MOUSEMOVE()
        ON_WM_LBUTTONUP()
        //}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    /////////////////////////////////////////
    // CTreeViewExt drawing
    void CTreeViewExt::OnDraw(CDC* pDC)
    {
        CDocument* pDoc = GetDocument();
        // TODO: add draw code here
    }
    /////////////////////////////////////////
    // CTreeViewExt diagnostics
    #ifdef _DEBUG
    void CTreeViewExt::AssertValid() const
    {
        CTreeView::AssertValid();
    }
    void CTreeViewExt::Dump(CDumpContext& dc) const
    {
        CTreeView::Dump(dc);
    }
    #endif //_DEBUG
    /////////////////////////////////////////
    // CTreeViewExt message handlers
    void CTreeViewExt::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult)
    {
        NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
        if (!m_bDraggingNow)
        {//先检查是否正在过程中
            if (ItemCanBeDragged(pNMTreeView->itemNew.hItem))
            {//查询条件,是否允许Drag&Drop
                CTreeCtrl& tree = GetTreeCtrl();
                tree.SetCapture();
                m_bDraggingNow = TRUE;
                m_hDraggedItem = pNMTreeView->itemNew.hItem;//保存变量
                tree.Select(m_hDraggedItem, TVGN_CARET);
                m_pDragImageList = tree.CreateDragImage(m_hDraggedItem);
                m_pDragImageList->DragEnter(&tree, pNMTreeView->ptDrag);
                m_pDragImageList->BeginDrag(0, CPoint(0, 0));
            }
        }
        *pResult = 0;
    }
    void CTreeViewExt::OnMouseMove(UINT nFlags, CPoint point)
    {
        if (m_bDraggingNow)
        {
            CTreeCtrl& tree = GetTreeCtrl();
            m_pDragImageList->DragEnter(&tree, point);
            m_pDragImageList->DragMove(point);
        }
        CTreeView::OnMouseMove(nFlags, point);
    }
    void CTreeViewExt::OnLButtonUp(UINT nFlags, CPoint point)
    {
        if (m_bDraggingNow)
        {
            ReleaseCapture();
            m_bDraggingNow = FALSE;
            m_pDragImageList->EndDrag();
            delete m_pDragImageList;
            m_pDragImageList = NULL;
            CTreeCtrl& tree = GetTreeCtrl();
            UINT flags;
            HTREEITEM hTargetItem = tree.HitTest(point, &flags);//得到目标
            if (hTargetItem != NULL && IsItemCanBeDroppedOn(m_hDraggedItem, hTargetItem))
            {//查询是否可以成功完成,条件是开始时选中的Item和结束使选中的ITEM是否满足你的条件
                HTREEITEM hNewItem = tree.InsertItem("Untitled", hTargetItem);
                CopyItemProperties(hNewItem, m_hDraggedItem);//进行处理
                if (nFlags != MK_CONTROL)
                    tree.DeleteItem(m_hDraggedItem);
            }
            m_hDraggedItem = NULL;
        }
        CTreeView::OnLButtonUp(nFlags, point);
    }
    BOOL CTreeViewExt::ItemCanBeDragged(HTREEITEM hItem)
    {//作用为决定现在是否能开始,可以作为一种运行时的选项
        return FALSE;
    }
    BOOL CTreeViewExt::IsItemCanBeDroppedOn(HTREEITEM hSource, HTREEITEM hTarget)
    {//决定现在结束条件是否正常,如不正常则放弃这次操作
        return FALSE;
    }
    void CTreeViewExt::CopyItemProperties(HTREEITEM hNewItem, HTREEITEM hDraggedItem)
    {//按照你的需要对两个ITEM进行处理。