VC控件“树”中多选拖放功能的实现
2007-10-05 20:22:44 来源:WEB开发网控件”树”(tree)能够清晰地显示所包含数据的继承关系,是一个强有力的控件。但是真正掌握并能运用CTreeCtrl类的众多特性并不是一件容易的事情。在Visual C++ Developer杂志的9月份、10月份这两期中,Stephen介绍了两个类CBitmapTree和CCheckableTree的用法,这两个类可以扩展和简化类CTreeCtrl。在这篇文章里,将主要介绍类CBitmapTree的升级版,它可以简化往”树”控件中添加拖放功能的过程,而且还可以实现多选拖放功能。
在CTreeCtrl类中,拖放特性是很难掌握和应用的特性之一。由于该特性能给拖放操作带来许多特有的灵活性,所以MFC组专门指派程序员负责这方面函数的编写工作,这将使得用户在开发的应用程序中实现控件”树”的拖放功能不再"望而生畏"。这里将介绍类CBitmapTree中扩充的有关成员函数,以便简化控件”树”的拖放功能的实现,同时还将该特性扩展到多选拖放。
本文所做的介绍是假定您已经对9、10月份Visual C++ Developer杂志中有关文章里面的概念和技术有所了解。这两篇文章的题目是 A Tree Control with Multiple Selection and Simpler Image Handling〖1〗和A Tree Control with Three-State Check Boxes and Sophisticated Sorting〖2〗。另外,升级的类CCheckableTree [CHECK.ZIP]文件可以从网址:www.pinpub.com/vcd/下的Subscriber Downloads部分中下载得到。
可拖动的项和释放的目标位置(Draggable items and drop targets)
拖放操作主要包含两个行为对象:被拖动的项和释放的目标位置项。为了支持可反复进行的拖放操作功能,需要能够识别出树控件类中哪些项是可拖动的以及它们的释放位置如何,而不是去识别父窗口类中的项。通过一个成员变量m_draggable中某一特定位值的设置可以设置某项的拖动特性,就象一个树的图象可以设置成"可扩充"特性一样。函数SetDraggable()、IsDraggable()、SetDropTarget()和IsDropTarget()中就使用了该成员变量m_draggable。下面是函数SetDraggable()的代码:
void CBitmapTree::SetDraggable(int base)
{
ASSERT(base < (sizeof(m_draggable)*8 -1));
m_draggable|= (1UL << base);
}
熟悉类CBitmapTree的读者可能注意到了该函数与SetExpandable()函数极其相似。变量base指明了所选的图象在"树"控件TVISL_NORMAL图象列表中的索引号。该索引号将转换成一个单位值,并且存储在成员变量m_draggable中。m_draggable成员变量类型为长整型,占4个字节32位,所以变量base指定的是位于图象列表中前32个图象中的某一个图象。而成员函数IsDraggable()可以用来查询变量m_draggable的值。成员函数IsDraggable()和IsDropTarget()都定义为虚函数,所以在需要对可拖动特性和可释放特性进行更为复杂的判断时,用户可以在类CBitmapTree的派生类中超越(overriding)该函数。网址www.pinpub.com/vcd下Subscriber Downloads部分中所包含的程序示例中,所有的文档节点都是可拖动的,所有的文件夹节点都可以作为拖动后释放的目标位置项。
准备拖动(Getting ready to drag)
当成功地执行完一次拖放操作后,函数SetDrag()就会建立一个回调函数来处理树项的移动或复制。笔者曾经在前面的文章里提供了一个比较简单的回调函数MoveTreeItemCB(),它可以完成树项在"树"控件中从一个位置移动到另一个位置。注意:这个函数本身的局限性很强,如果想完成某些该函数不具备的其它方面的功能时,就需要用户根据实际需要编写自己的回调函数。(例如,当使用宏LPSTR_TEXTCALLBACK来替代表示树项的文本时,函数MoveTreeItemCB()就不能正常运行。)
另外,在拖动树项时,可以提供给函数SetDrag()一个位图的资源标识符(并不是必需的)。该位图可以作为一种提示图标,它应该具有如图1所示的格式。当拖动超出了有效范围的边界时,则显示第一个图象;当拖动项只有一项时,则显示第二个图象;当拖动项包含多项时,则显示第三个图象。如果在程序中并没有提供图象给函数SetDrag(),那么将显示一个缺省的拖动图象,即当前所选项的灰色显示。
更多精彩
赞助商链接