作者:一块三毛钱
下载本文源代码
树型控件用来显示具有一定层次结构的数据项时方便、直观,被广泛地应用在各种软件中,如资源管理器中的磁盘目录就用的是树型
控件,我们在编程中也会经常用到,但 MFC 中提供的 CTreeCtrl 类并不直接支持拖动节点等高级特性,这使我们程序员编程时有很大限
制,又给软件用户带来了一些不便。下面就让我们自己动手来解决这个问题,实现树型控件中节点的拖动。
我们从 CTreeCtrl 中派生了一个类 CXTreeCtrl ,它具有如下的特点:
⑴ 基本拖动的实现。
⑵ 处理无意拖动。
⑶ 能处理拖动过程中的滚动问题。
⑷ 拖动过程中节点会智能展开。
图 1 为示例程序的运行界面。
(图 1)
好,我们来一步一步实现上述功能。
新建一对话框工程,编辑资源,在对话框中加入一树型控件 IDC_TREE ,属性设置如图 2,给该控件添加一个成员变量 m_wndTree ,
类型改为CXTreeCtrl。从 CTreeCtrl 中派生一个类 CXTreeCtrl 。
(图 2)
1、基本拖动的实现
当我们要拖动一个项目时,树型视图控件会给它的父窗口发送TVN_BEGINDRAG通知消息。可以在此处创建表示项目处在拖动操作中
的图象,调用 CreateDragImage 函数产生一副缺省的图象,该函数创建的图象由条目图象和标签文本组成。创建了拖动图象后,调用
BeginDrag 函数指定拖动图象的热点位置,然后调用 DragEnter 函数显示拖动图象。接下来处理 WM_MOUSEMOVE 消息用于更新拖动图
象,我们想让移动中的图象经过某些项目时高亮度显示,这可以调用 SelectDropTarget 来实现。在调用 SelectDropTarget 前,我们先调用
DragShowNolock ( false ) 来隐藏图象列表,之后再调用 DragShowNolock ( true ) 来恢复图象列表的显示,这样就不会在拖动过程中留下难
看的轨迹。最后我们处理 WM_LBUTTONUP 消息用于完成拖动操作,在给消息中,我们需要完成结束拖动图想的显示、删除拖动图象、释
放鼠标、节点的拷贝/删除等操作。在节点的拷贝/删除操作中,如果是父节点拖到子节点上,我们可以先将父节点拷到根结点下的临时节点
中,再从临时结点处拷到子节点,然后将根结点下的临时节点删除,这样做的目的是防止产生异常。
2、处理无意拖动
大家可能都有过这样的经历:在鼠标按下时不小心移动了鼠标,这时系统就认为产生了一个移动操作。如果我们不针对这种情况加以解
决的话,就很容易产生误操作。下面我们就提出一个解决方法:设置时间延迟。也就是说当用户按下鼠标后必须在原位置停留一段时间,才
能激活拖动操作。
3、处理拖动过程中的滚动问题
当我们进行拖动时,如果目的节点不可见,则需要拖动滚动条或收拢其它一些节点以使得目的节点显示出来,无疑,这会给我们带来很
大的不便。下面我们就来给树型控件添加自动滚动支持。
设置一个定时器,在 WM_TIMER 消息中检测鼠标的位置,如果靠近树型控件的下边缘,则使得控件向下滚动。靠近上边缘则向上滚动。
滚动速度根据鼠标的位置确定。
4、拖动过程中节点的智能展开
这一步我们要实现的功能是在拖动过程中当鼠标停留在某个节点上一段时间后,该节点会自动展开。
设置一个定时器,当鼠标在拖动过程中停止在某个节点上时,定时器被启动,再设置一变量保存当前的鼠标位置。
下面是实现的源代码
// XTreeCtrl.h……protected:UINT m_TimerTicks; //处理滚动的定时器所经过的时间UINT m_nScrollTimerID; //处理滚动的定时器CPoint m_Hove