我怎样才能推迟这一点;渲染“;Winforms跨进程拖放期间我的数据对象的
我有一个对象,虽然它有一个文本表示(即可以存储在大约1000个可打印字符的字符串中),但生成它的成本很高。我还有一个树控件,它显示对象的“摘要”。我不仅希望在自己的应用程序中拖放这些对象,还希望将这些对象拖放到接受CF_TEXT或CF_UNICODETEXT的其他应用程序中,此时文本表示将插入到拖放目标中 我一直在考虑延迟“呈现”对象的文本表示,以便仅当对象被拖放或粘贴时才会发生。然而,Winforms似乎在拖动开始时急切地调用GetData()方法,这会在拖动开始时造成痛苦的几秒钟延迟我怎样才能推迟这一点;渲染“;Winforms跨进程拖放期间我的数据对象的,winforms,drag-and-drop,ole,Winforms,Drag And Drop,Ole,我有一个对象,虽然它有一个文本表示(即可以存储在大约1000个可打印字符的字符串中),但生成它的成本很高。我还有一个树控件,它显示对象的“摘要”。我不仅希望在自己的应用程序中拖放这些对象,还希望将这些对象拖放到接受CF_TEXT或CF_UNICODETEXT的其他应用程序中,此时文本表示将插入到拖放目标中 我一直在考虑延迟“呈现”对象的文本表示,以便仅当对象被拖放或粘贴时才会发生。然而,Winforms似乎在拖动开始时急切地调用GetData()方法,这会在拖动开始时造成痛苦的几秒钟延迟 有没有
有没有办法确保GetData()只在删除时发生?或者,在Winforms程序中实现此延迟删除机制的正确机制是什么?经过一些研究,我能够想出如何做到这一点,而不必实现COM接口
IDataObject
(及其所有FORMATETC
gunk)。我认为这可能会引起其他处于同样困境的人的兴趣,所以我写下了我的解决方案。如果能做得更聪明些,我会全神贯注的
System.Windows.Forms.DataObject
类具有以下构造函数:
public DataObject(string format, object data)
我这样称呼它:
string expensive = GenerateStringVerySlowly();
var dataObject = new DataObject(
DataFormats.UnicodeText,
expensive);
DoDragDrop(dataObject, DragDropEffects.Copy);
string expensive = GenerateStringVerySlowly();
var dataObject = new DataObject(
DataFormats.UnicodeText,
new MemoryStream(Encoding.Unicode.GetBytes(expensive)));
DoDragDrop(dataObject, DragDropEffects.Copy);
上述代码将在复制操作期间将字符串数据放入HGLOBAL
。但是,您也可以这样调用构造函数:
string expensive = GenerateStringVerySlowly();
var dataObject = new DataObject(
DataFormats.UnicodeText,
expensive);
DoDragDrop(dataObject, DragDropEffects.Copy);
string expensive = GenerateStringVerySlowly();
var dataObject = new DataObject(
DataFormats.UnicodeText,
new MemoryStream(Encoding.Unicode.GetBytes(expensive)));
DoDragDrop(dataObject, DragDropEffects.Copy);
与通过HGLOBAL
复制数据不同,后面的调用具有通过(COM)IStream
复制数据的良好效果。显然,.NET互操作层正在发挥某种魔力,它处理COMIStream
和.NETSystem.IO.Stream
之间的映射
我现在所要做的就是编写一个类,将流的创建推迟到最后一分钟(),当drop目标开始调用Length
,Read
等时。它看起来是这样的:(为简洁起见编辑了部分)
这正是我所需要的,使这项工作。然而,我在这里依赖于下降目标的良好行为。行为不端的drop目标急切地调用Read
方法,会导致代价高昂的操作提前发生