绪论
用户一般分为两类:一类习惯用
键盘操作,一类习惯用鼠标操作。程序员们在编程时一般会提供快捷键或快捷方式来照顾到那些习惯
键盘的
用户,但是那些鼠标
用户却被忽略了。因为程序员们一般都习惯用
键盘,所以他们这种重视
键盘操作的特点是可以理解的,但是每个程序员也应该考虑到提供鼠标
支持。 鼠标
用户所期望的一件事就是能够在应用程序中实现拖放。如果你注意到一些大型应用程序或windows自身的话,拖放操作几乎随处可见。例如,
用户可能已经习惯了在windows资源管理器中拖放
文件,或在中拖放文本等操作了。 尽管拖放操作随处可见,但是只有极少数程序员在他们所编写的程序中实现拖放
功能,最可能的原因是他们认为实现拖放可能比想象的还要难。这篇
文章列举了如何在窗体内、窗体之间,甚至应用程序之间移动文本、
图片或者
文件的例子,
显示了在中实现拖放是非常容易得。 拖放如何进行 拖放实际上就如同用鼠标复制粘帖,因此你必须有一个可以复制或移动的源,也要有一个可以粘贴的目的地。在这两个操作过程中,数据是保存在内存中的。复制粘贴用的是剪切版,而拖放用的却是一种本质上是私有剪切板的Dataobject的对象。 下面是典型的托放操作的时间序列: 1、拖是通过
调用源控件的DoDragDrop
方法来初始化的,DoDragDrop有两个参数 data,指定将要传送的数据 allowedEffects,指定允许进行的操作(复制或移动) 这样
自动创建了一个新的Dataobject对象 2、接下来就依次激发了Give
FeedBack事件。在大多数情况下,你并不需要担心Give
FeedBack事件,然而你如果想
自定义拖放过程中的鼠标指针的话,你可以在这些地方
加上你的
代码。 3、任何有AllowDrop
属性而且被设置成True的控件都是隐含的Drop对象。AllowDrop
属性可以在设计时的
属性窗口中进行设置,也可以在Form_load事件
自动加载。 4、当鼠标移到某个控件时,就同时激发了这个控件的DragEnter事件。GetDataPresent
方法是用来确认拖过来的数据是否适合目标控件,Effect
属性是用来
显示适当的鼠标指针。 5、如果
用户在有效的目标控件上释放鼠标,就同时激发了DragDrop事件。DragDrop事件句柄中的
代码从DataObject对象中释放数据并把它
显示在目标控件中。 从VB6到VB.NET有何变化? (略) 拖放文本 拖放操作的一个很简单然而很有用的情形是从一个Text
Box控件复制文本到另一个Text
Box控件。当然你可以只用
键盘就能实现,然而拖放更简单因为它仅需要鼠标的移动就可以完成。 1、向一个窗体中
添加两个文本框,并把第二个Text
Box控件的AllowDrop
属性设置成True,
添加如下
代码。 PrivateMouseIsDownAsBoolean=False PrivateSubText
Box1_MouseDownHandlesText
Box1.MouseDown ‘Setaflagtoshowthatthemouseisdown. MouseIsDown=True EndSub PrivateSubText
Box1_MouseMoveHandlesText
Box1.MouseMove IfMouseIsDownThen ‘Initiatedragging. Text
Box1.DoDragDrop EndIf MouseIsDown=False EndSub PrivateSubText
Box2_DragEnterHandlesText
Box2.DragEnter ‘Checktheformatofthedatabeingdropped. If)Then ‘Displaythecopycursor. e.Effect=DragDropEffects.Copy Else ‘Displaytheno-dropcursor. e.Effect=DragDropEffects.None EndIf EndSub PrivateSubText
Box2_DragDropHandlesText
Box2.DragDrop ‘Pastethetext. Text
Box2.Text=e.Data.GetDataHandlesMyBase.Load ‘Enabledropping. Picture
Box2.AllowDrop=True EndSub PrivateSubPicture
Box1_MouseDownHandlesPicture
Box1.MouseDown IfNotPicture
Box1.ImageIsNothingThen ‘Setaflagtoshowthatthemouseisdown. m_MouseIsDown=True EndIf EndSub PrivateSubPicture
Box1_MouseMoveHandlesPicture
Box1.MouseMove Ifm_MouseIsDownThen ‘Initiatedraggingandalloweithercopyormove. Picture
Box1.DoDragDrop EndIf m_MouseIsDown=False EndSub PrivateSubPicture
Box2_DragEnterHandlesPicture
Box2.DragEnter Ife.Data.GetDataPresentThen ‘CheckfortheCTRLkey. Ife.KeyState=9Then e.Effect=DragDropEffects.Copy Else e.Effect=DragDropEffects.Move EndIf Else e.Effect=DragDropEffects.None EndIf EndSub PrivateSubPicture
Box2_DragDropHandlesPicture
Box2.DragDrop ‘AssigntheimagetothePicture
Box. Picture
Box2.Image=e.Data.GetData ‘IftheCTRLkeyisnotpressed,deletethesourcepicture. IfNote.KeyState=8Then Picture
Box1.Image=Nothing EndIf EndSub 注意到上面的例子中第二个Picture
Box控件的AllowDrop
属性是在Form1_load事件中设置的,这是因为设计时Picture
Box并没有AllowDrop
属性。 在MouseDown事件中,
代码首先检测是否有要赋给Picture
Box的
图片;如果没有的话,当你移动
图片后,接下来的click将引发一个意外。 还应该注意到的是在DragEnter和DragDrop事件中
代码检测CTRL键是否被按下,从而决定是否是复制还是移动
图片。为什么值会不同呢?在DragEnter事件中,当鼠标左键按下时,产生的值是1,在
加上CTRL的值8,从而值为9。见KeyState枚举列表DragEventArgs.KeyStateProperty。 到目前为止,这两个例子处理的都是同一窗体不同控件间的拖放,然而在同一应用程序的不同窗体上同样适用。 拖动
文件 在windows中拖放通常是复制或移动
文件,windows完全
支持该
功能,而且对许多
用户来说这也是操作
文件的优选方式。除此之外,
用户已经习惯了把
文件拖动到一个程序来打开
文件的方式,像拖动一个doc
文件到word来打开。 在这个例子中用从windows资源管理器拖来的
文件来操作List
Box控件。 向窗体中
添加一个List
Box控件,并设置其AllowDrop
属性为True,并
添加如下
代码: PrivateSubList
Box1_DragEnterHandlesList
Box1.DragEnter Ife.Data.GetDataPresentThen e.Effect=DragDropEffects.All EndIf EndSub PrivateSubList
Box1_DragDropHandlesList
Box1.DragDrop Ife.Data.GetDataPresentThen DimMyFilesAsString DimiAsInteger ‘Assignthefilestoanarray. MyFiles=e.Data.GetData ‘Loopthroughthearrayandaddthefilestothelist. Fori=0ToMyFiles.Length-1 List
Box1.Items.Add) Next EndIf EndSub 你可能已经注意到了DragEnter事件中的Effect
属性被设置成DragDropEffects.All。因为
文件本身并不是真的就被复制或移动了,因此源控件设置成哪个AllowedEffects并没有关系,所以指定All对任何FileDrop都可以。 在上面的例子中FileDrop格式包含了每个被拖动
文件的全路径。 下面的例子讲述了拖放的一个特殊情况:在两个列表间来回拖放。 表间拖放 拖放的另一个情况是从一个列表移动项目到另一个列表。这种情况下拖放将变得更加简单。 向窗体中
添加两个ListView控件,并把他们的AllowDrop、Multiselect、View
属性分别设置成True、True、List。并
添加如下
代码: PrivateSubListView_ItemDragHandlesListView1.ItemDrag,_ ListView2.ItemDrag DimmyItemAsListViewItem DimmyItemsAsListViewItem DimiAsInteger=0 ‘LoopthoughtheSelectedItemscollectionforthesource. ForEachmyItemInsender.SelectedItems ‘AddtheListViewItemtothearrayofListViewItems. myItems=myItem i=i+1 Next ‘CreateaDataObjectcontaingthearrayofListViewItems. sender.DoDragDrop,myItems),_ DragDropEffects.Move) EndSub PrivateSubListView_DragEnterHandlesListView1.DragEnter,_ ListView2.DragEnter ‘CheckforthecustomDataFormatListViewItemarray. Ife.Data.GetDataPresent)Then e.Effect=DragDropEffects.Move Else e.Effect=DragDropEffects.None EndIf EndSub PrivateSubListView_DragDropHandlesListView1.DragDrop,_ ListView2.DragDrop DimmyItemAsListViewItem DimmyItemsAsListViewItem=_e.Data.GetData) DimiAsInteger=0 ForEachmyItemInmyItems ‘Addtheitemtothetargetlist. sender.Items.Add.Text) ‘Removetheitemfromthesourcelist. IfsenderIsListView1Then ListView2.Items.Remove) Else ListView1.Items.Remove) EndIf i=i+1 Next EndSub 你可能不明白为什么这个例子中用的是ListView控件而不是List
Box控件,这个问题题的好,因为List
Box控件
不支持多项拖放。 ListView和TreeView控件有个ItemDrag事件。上面的例子中,一个ItemDrag事件句柄覆盖了两个控件,并在列在Handles从句。Sender参数表明哪个控件正在初始化Drag。 因为DataFormats类没有ListViewItem类型成员,数据必须传递给一个系统类型。ItemDrag创建了一个ListViewItem类型的数组,并用一个循环来遍历SelectedItem集合。在DoDragDrop
方法中,创建了一个新的DataObject并用数组来来对它进行操作。可以用这种
方法来拖放任何系统类型。 结论: 正像你从这些例子中所看到的一样,为应用程序
添加拖放操作并不是很难。当你理解了这些基本的技巧后,你就可以为你自己的程序
添加拖放的
代码了