如何使用DragType dtOLE将节点从TVirtualStringTree拖放到VCL控件中?

时间:2017-01-18 20:53:31

标签: delphi virtualtreeview tvirtualstringtree

TVirtualStringTree设置为DragType(而非dtOLE)时,是否可以将节点从dtVCL拖放到VCL控件中

我有一种情况,我需要能够将节点从一个VT拖动到另一个VT(dtOLE工作正常),但同时,在拖动时,我需要一个选项才能删除将节点转换为TListBox(或其他VCL控件)。

我尝试为DragAcceptFiles()句柄设置TListBox API,但它没有效果。

怎么做?

1 个答案:

答案 0 :(得分:3)

DragAcceptFiles上没有TListBox属性。如果您的意思是在TListBox.Handle窗口中调用Win32 API DragAcceptFiles()函数,那么只有在以下情况下才会起作用:

  1. 您手动将TListBox.WindowProc属性子类化以处理WM_DROPFILES窗口消息。

  2. TVirtualStringTree在OLE拖动期间提供CF_HDROP格式。

  3. 但是,

    2并非如此。 CF_HDROP仅用于拖动文件系统路径,而不是TVirtualStringTree拖动。所以使用DragAcceptFiles()已经出局了。

    TVirtualStringTree(以及其他TBaseVirtualTree后代)在OLE拖动期间使用自定义数据格式(VirtualTrees.pas单元的接口部分声明这些格式ID,因此您无需注册它们在您自己的代码中手动):

    • CF_VIRTUALTREE包含IStreamHGLOBAL,其中包含正在拖动的所选树节点的序列化形式。序列化由描述每个节点的一系列数据块组成。你必须参考VirtualTree.pas单位的实现来破译这种格式(我不打算在这里做)。

    • CF_VTREFERENCE包含HGLOBALTVTReference记录(也在VirtualTrees.pas单元的接口部分声明),其中包含指向实际的指针正在拖动的TBaseVirtualTree对象以及树所属进程的ID。

    因此,为了能够将树节点放到TListBox上,您必须执行以下操作:

    1. 编写一个实现IDropTarget接口的类(或使用预先存在的实现,例如来自Anders Melander's Drag&Drop suite)。

    2. 使用RegisterDragDrop()TListBox.Handle窗口中注册该课程。

    3. 在您的IDropTarget实施中,您可以针对IDataObjectCF_VIRTUALTREE格式查询提供的CF_VTREFERENCE。如果成功,您的Drop()方法将有权访问正在拖动的树节点数据,并可根据需要将其复制到TListBox

    4. 假设您的TListBox存在于与被拖出的TVirtualStringTree相同的过程中,我建议您只关注CF_VTREFERENCE,因为它是一种非常小而简单的格式(请参阅TBaseVirtualTree.GetTreeFromDataObject()方法的实现,并且当您可以直接枚举源CF_VIRTUALTREE时,解析TBaseVirtualTree.ProcessOLEData()数据将是过度的(请参阅TVirtualStringTree方法的实现)代替。