• 【控件专题】一个具有拖拽功能的TreeCtrl(转)


    #if !defined(AFX_DRAGTREE_H__3015F03F_045E_4531_A436_E2A890F23540__INCLUDED_)
    #define AFX_DRAGTREE_H__3015F03F_045E_4531_A436_E2A890F23540__INCLUDED_

    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // DragTree.h : header file
    //

    /////////////////////////////////////////////////////////////////////////////
    // CDragTree window

    class CDragTree : public CTreeCtrl
    {
    // Construction
    public:
     CDragTree();
     
     CImageList*  m_pDragImages; //拖动的图像列表
     BOOL m_bDrag;    //是否进行拖动
     HTREEITEM  m_hBeginDrag; //拖动的起点
    // Attributes
    public:

    // Operations
    public:

    // Overrides
     // ClassWizard generated virtual function overrides
     //{{AFX_VIRTUAL(CDragTree)
     //}}AFX_VIRTUAL

    // Implementation
    public:
     void CopyNodes(HTREEITEM hDesItem, HTREEITEM hSrcItem);
     virtual ~CDragTree();

     // Generated message map functions
    protected:
     //{{AFX_MSG(CDragTree)
     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 Visual C++ will insert additional declarations immediately before the previous line.

    #endif // !defined(AFX_DRAGTREE_H__3015F03F_045E_4531_A436_E2A890F23540__INCLUDED_)

    // DragTree.cpp : implementation file
    //

    #include "stdafx.h"
    #include "DragTreeItem.h"
    #include "DragTree.h"

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif

    /////////////////////////////////////////////////////////////////////////////
    // CDragTree

    CDragTree::CDragTree()
    {
     m_pDragImages = NULL;
     m_bDrag = FALSE;
     m_hBeginDrag = NULL;
    }

    CDragTree::~CDragTree()
    {
    }


    BEGIN_MESSAGE_MAP(CDragTree, CTreeCtrl)
     //{{AFX_MSG_MAP(CDragTree)
     ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBegindrag)
     ON_WM_MOUSEMOVE()
     ON_WM_LBUTTONUP()
     //}}AFX_MSG_MAP
    END_MESSAGE_MAP()

    /////////////////////////////////////////////////////////////////////////////
    // CDragTree message handlers

    void CDragTree::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult)
    {
     NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
     HTREEITEM hItem = pNMTreeView->itemNew.hItem;  //获取开始拖动的节点
     if (hItem==GetRootItem())       //不允许拖动根节点
     {
      *pResult = 0;
      return;
     }
     m_hBeginDrag = hItem;        //记录开始拖动的项目
     m_pDragImages = CreateDragImage(hItem);    //创建拖动的图像列表

     CPoint dragPT;          //记录起始点
     dragPT.x = pNMTreeView->ptDrag.x;
     dragPT.y = pNMTreeView->ptDrag.y;
     if (m_pDragImages != NULL)
     {
      m_pDragImages->BeginDrag(0, CPoint(8, 8));  //开始拖动图像
      ClientToScreen(&dragPT);      //转换客户坐标到屏幕坐标
      m_pDragImages->DragEnter(this, dragPT);   //锁定窗口更新,在拖动的过程中显示拖动的图像
      SetCapture();         //开始鼠标捕捉
      m_bDrag = TRUE;
     }
     *pResult = 0;
    }

    void CDragTree::OnMouseMove(UINT nFlags, CPoint point)
    {
     if (m_bDrag)          //处于拖动状态
     {
      HTREEITEM hItem;
      UINT  nHitFlags;
      CRect  clientRC;
      GetClientRect(&clientRC);      //获取客户区域
      m_pDragImages->DragMove(point);     //设置拖动的图像位置
      //鼠标经过时高亮显示
      if( (hItem = HitTest(point, &nHitFlags)) != NULL )
      {
       CImageList::DragShowNolock(FALSE);   //隐藏拖动的图像
       SelectDropTarget(hItem);     //设置选中的项目
       CImageList::DragShowNolock(TRUE);   //显示拖动的图像
      }
     }
     else
      CTreeCtrl::OnMouseMove(nFlags, point);
    }

    void CDragTree::OnLButtonUp(UINT nFlags, CPoint point)
    {
     if (m_bDrag)          //处于拖动状态
     {
      m_bDrag = FALSE;
      CImageList::DragLeave(this);     //
      CImageList::EndDrag();       //结束图像拖动
      ReleaseCapture();        //释放鼠标捕捉
      delete m_pDragImages;       //释放图像列表
      m_pDragImages = NULL;
      CRect winRC;
      GetWindowRect(&winRC);       //获取窗口区域
      HTREEITEM hItem;
      if((hItem = HitTest(point, &nFlags)) != NULL)
      {
       //进行拖动处理
       //如果目标项目与开始拖动的项目相同或者目标项目仍是开始项目的父节点,不进行处理
       if (m_hBeginDrag != hItem && hItem != GetParentItem(m_hBeginDrag))
       {
        CopyNodes(hItem, m_hBeginDrag);   //进行节点的复制
        DeleteItem(m_hBeginDrag);    //删除源节点
       }
       Invalidate();
       SelectDropTarget(NULL);
       m_hBeginDrag = NULL;
      }
     }
    }

    //复制节点,将hSrcItem及其子项目复制到下hDesItem节点下
    void CDragTree::CopyNodes(HTREEITEM hDesItem, HTREEITEM hSrcItem)
    {

     if (hDesItem==NULL || hSrcItem==NULL)    //验证参数
     {
      return;
     }
     TVITEM tvItem;          //定义项目信息
     tvItem.mask = TVIF_TEXT|TVIF_IMAGE;     //设置返回标记
     tvItem.hItem = hSrcItem;
     char chText[MAX_PATH] = {0};
     tvItem.pszText = chText;
     tvItem.cchTextMax = MAX_PATH;
     GetItem(&tvItem);         //获取项目信息
     TVINSERTSTRUCT tvInsert;       //定义插入操作的数据结构
     tvInsert.hParent = hDesItem;
     tvInsert.item = tvItem;
     HTREEITEM hInsert = InsertItem(&tvInsert);   //插入项目
     HTREEITEM hChild = GetChildItem(hSrcItem);   //获取子节点
     while (hChild != NULL)        //遍历子节点
     {
      tvItem.mask = TVIF_TEXT|TVIF_IMAGE;
      tvItem.hItem = hChild;
      tvItem.pszText = chText;
      tvItem.cchTextMax = MAX_PATH;
      GetItem(&tvItem);
      tvInsert.hParent = hInsert;
      tvInsert.item = tvItem;
      CopyNodes(hInsert, hChild);      //递归调用
      hChild = GetNextSiblingItem(hChild);   //查找下一个兄弟节点 
     }
    }

  • 相关阅读:
    JS中this指向问题(const self = this)
    nuxt.js中koa2写接口顺序
    关于Vue中的slot-scope="scope"
    Nuxt.js 中设置 div的css的 height 为100%
    nuxt报错:[nuxt] store/index.js should export a method that returns a Vuex instance.
    解决element UI中当value初始值存在空值时select只显示初始值,不显示placeholder值
    CSS控制一行显示两个li
    原生JS实现列表子元素顺序反转的方法分析
    Javascript 字符串全排列组合方法实现
    mysql引擎
  • 原文地址:https://www.cnblogs.com/rainbowzc/p/2125894.html
Copyright © 2020-2023  润新知