当TVirtualStringTree
设置为DragType
(而非dtOLE
)时,是否可以将节点从dtVCL
拖放到VCL控件中
我有一种情况,我需要能够将节点从一个VT拖动到另一个VT(dtOLE
工作正常),但同时,在拖动时,我需要一个选项才能删除将节点转换为TListBox
(或其他VCL控件)。
我尝试为DragAcceptFiles()
句柄设置TListBox
API,但它没有效果。
怎么做?
答案 0 :(得分:3)
DragAcceptFiles
上没有TListBox
属性。如果您的意思是在TListBox.Handle
窗口中调用Win32 API DragAcceptFiles()
函数,那么只有在以下情况下才会起作用:
您手动将TListBox.WindowProc
属性子类化以处理WM_DROPFILES
窗口消息。
TVirtualStringTree
在OLE拖动期间提供CF_HDROP
格式。
2并非如此。 CF_HDROP
仅用于拖动文件系统路径,而不是TVirtualStringTree
拖动。所以使用DragAcceptFiles()
已经出局了。
TVirtualStringTree
(以及其他TBaseVirtualTree
后代)在OLE拖动期间使用自定义数据格式(VirtualTrees.pas
单元的接口部分声明这些格式ID,因此您无需注册它们在您自己的代码中手动):
CF_VIRTUALTREE
包含IStream
或HGLOBAL
,其中包含正在拖动的所选树节点的序列化形式。序列化由描述每个节点的一系列数据块组成。你必须参考VirtualTree.pas
单位的实现来破译这种格式(我不打算在这里做)。
CF_VTREFERENCE
包含HGLOBAL
个TVTReference
记录(也在VirtualTrees.pas
单元的接口部分声明),其中包含指向实际的指针正在拖动的TBaseVirtualTree
对象以及树所属进程的ID。
因此,为了能够将树节点放到TListBox
上,您必须执行以下操作:
编写一个实现IDropTarget
接口的类(或使用预先存在的实现,例如来自Anders Melander's Drag&Drop suite)。
使用RegisterDragDrop()
在TListBox.Handle
窗口中注册该课程。
在您的IDropTarget
实施中,您可以针对IDataObject
和CF_VIRTUALTREE
格式查询提供的CF_VTREFERENCE
。如果成功,您的Drop()
方法将有权访问正在拖动的树节点数据,并可根据需要将其复制到TListBox
。
假设您的TListBox
存在于与被拖出的TVirtualStringTree
相同的过程中,我建议您只关注CF_VTREFERENCE
,因为它是一种非常小而简单的格式(请参阅TBaseVirtualTree.GetTreeFromDataObject()
方法的实现,并且当您可以直接枚举源CF_VIRTUALTREE
时,解析TBaseVirtualTree.ProcessOLEData()
数据将是过度的(请参阅TVirtualStringTree
方法的实现)代替。