CSharp Tips:Drag & Drop的高级应用

昨天,有同事问了我一个问题,这个问题的第一种描述方式是“怎么利用拖放的方式把一个进程中的流传递到第二个进程中”;第二种描述方式是“把应用程序中的数据(文件/流)通过拖放的方式复制到桌面或者Explorer中”。看似简单的描述下面隐藏了不少东西,有点意思,于是昨晚翻了翻资料。

 

这个问题涉及到两个技术点:跨进程的大数据块的传递,Drag & Drop

跨进程的大数据块传递不考虑管道/Socket这类直接通讯方式的话,间接方式也很多,DDE、剪贴板、文件或者内存镜像文件。DDE有点古老,我都不记得该怎么玩了。实时性要求不高的话,保存成为临时文件,将文件名传递过去,是一个无论从系统开销,还是实现上都是一个不错的选择。至于内存镜像文件,是另一个专题,不在这里赘述了。剪贴板也是个比较有趣的东西,真要说的话,也有很多话可讲,也不在这里多说了。

数据传递的方案定了,再看Drag & Drop。在MSDN中查了一下,System.Window.Form.Control下有一组和拖放相关的方法和事件,例如DoDragDrop用来作为源启动一次拖放,DragEnterDragOverDragDrop是作为目标处理拖放的事件。整个拖放过程就是源在拖放开始的时候提交需要拖放的数据,并指明影响方式(例如CopyMove之类),目标在拖放被触发(Drop的时候)时获取拖放数据并且进行相应处理。数据和数据格式是通过一个叫IDataObject的接口来描述的,它用来存储数据,申明支持的数据格式,并且对数据格式进行转换。思路清楚了,关键要实现一个IDataObject

 

回过头看我们的问题,先解决“把应用程序中的数据(文件/流)通过拖放的方式复制到桌面或者Explorer中”这种情况。写一个小例子,一个窗口上面只有一个ListBox,里面有两个元素,分别对应硬盘上的两个文件,希望在ListBox中选中一个元素拖放到桌面,就把那个元素对应的文件复制到桌面。

代码逻辑很简单,处理ListBox的鼠标事件,判断是不是满足启动拖放的条件,当启动拖放时,把当前选中的元素封装到我们定义的IDataObject中,然后调用DoDragDrop方法。问题是IDataObject如果定义?有同学就问了我怎么知道桌面(Explorer)要求的数据格式是什么?易同学就这么问过。这也很简单,只要看看桌面作为拖放源的时候生成的DataObject支持那些格式,数据是什么形式的,仿照一下就行了。

在开始正式工作之前,先在窗口的DragEnter中写一段代码,检查DataSource支持的格式,运行程序,在桌面上拖到一个我们到我们写的应用程序窗口,一看输出,居然支持8种格式。作为工程师一定要把复杂的问题变得简单,看名字一分析,有几个格式叫“FileDrop”、“FileName”、“FileNameW”,返回的数据类型是一个字符串数组,每个成员是一个文件名,不用想,就和这些格式有关。马上动手,IDataObject类的实现如下,完整代码可到此处下载

 运行程序,拖动ListBox中的元素到桌面,成了,文件复制过去了。在进一步测试,其实只需要支持“FileDrop”的格式就可以了。

 

再看另一种情况,从自己写的一个应用程序拖放到另一个自己写的应用程序,怎么办?更好办了,双方约定一下IDataObject实现类需要支持的格式,目标应用程序在自己的DragDrop时间中获取数据再执行操作就可以了。

 

最后提一点DoDragDrop方法的第一个参数,是支持字符串类型的,MSDN提供的示例也是传递一个字符串,但是跨进程的话应该不能直接用,就算是自己的程序估计也不行,跨进程一定需要自己定义一个实现IDataObject的类,想想COM,总要做Marshal的。这段个人猜测,没有验证,供参考。

 

参考文档

Ø  Control.DoDragDrop方法

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值