关键词搜索

源码搜索 ×
×

在VB.NET中实现拖放操作

发布2020-12-12浏览829次

详情内容

在VB.NET中实现拖放操作
  绪论
  Windows用户一般分为两类:一类习惯用键盘操作,一类习惯用鼠标操作。程序员们在编程时一般会提供快捷键(在命令或字母中加下划线)或快捷方式(用CTRL加字母的组合)来照顾到那些习惯键盘的用户,但是那些鼠标用户却被忽略了。因为程序员们一般都习惯用键盘,所以他们这种重视键盘操作的特点是可以理解的,但是每个程序员也应该考虑到提供鼠标支持。
鼠标用户所期望的一件事就是能够在应用程序中实现拖放。如果你注意到一些大型应用程序或windows自身的话,拖放操作几乎随处可见。例如,用户可能已经习惯了在windows资源管理器中拖放文件,或在word中拖放文本等操作了。
  尽管拖放操作随处可见,但是只有极少数程序员在他们所编写的程序中实现拖放功能,最可能的原因是他们认为实现拖放可能比想象的还要难。这篇文章列举了如何在窗体内、窗体之间,甚至应用程序之间移动文本、图片或者文件的例子,显示了在中实现拖放是非常容易得。
拖放如何进行
  拖放实际上就如同用鼠标复制粘帖,因此你必须有一个可以复制或移动的源,也要有一个可以粘贴的目的地。在这两个操作过程中,数据是保存在内存中的。复制粘贴用的是剪切版,而拖放用的却是一种本质上是私有剪切板的Dataobject的对象。
下面是典型的托放操作的时间序列:
  1、拖(dragging)是通过调用源控件的DoDragDrop方法来初始化的,DoDragDrop有两个参数
data,指定将要传送的数据
allowedEffects,指定允许进行的操作(复制或移动)
这样自动创建了一个新的Dataobject对象
  2、接下来就依次激发了GiveFeedBack事件。在大多数情况下,你并不需要担心GiveFeedBack事件,然而你如果想自定义拖放过程中的鼠标指针的话,你可以在这些地方加上你的代码。
  3、任何有AllowDrop属性而且被设置成True的控件都是隐含的Drop对象。AllowDrop属性可以在设计时的属性窗口中进行设置,也可以在Form_load事件自动加载。
  4、当鼠标移到某个控件时,就同时激发了这个控件的DragEnter事件。GetDataPresent方法是用来确认拖过来的数据是否适合目标控件,Effect属性是用来显示适当的鼠标指针。
  5、如果用户在有效的目标控件上释放鼠标,就同时激发了DragDrop事件。DragDrop事件句柄中的代码从DataObject对象中释放数据并把它显示在目标控件中。
从VB6到VB.NET有何变化?
(略)
拖放文本
  拖放操作的一个很简单然而很有用的情形是从一个TextBox控件复制文本到另一个TextBox控件。当然你可以只用键盘就能实现(CTRL + C and CTRL + V),然而拖放更简单因为它仅需要鼠标的移动就可以完成。
  1、向一个窗体中添加两个文本框,并把第二个TextBox控件的AllowDrop属性设置成True,添加如下代码。

Private MouseIsDown As Boolean = False
Private Sub TextBox1_MouseDown(ByVal sender As Object, ByVal e As _
System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseDown
' Set a flag to show that the mouse is down.
MouseIsDown = True
End Sub

Private Sub TextBox1_MouseMove(ByVal sender As Object, ByVal e As _
System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseMove
If MouseIsDown Then
' Initiate dragging.
TextBox1.DoDragDrop(TextBox1.Text, DragDropEffects.Copy)
End If
MouseIsDown = False
End Sub

Private Sub TextBox2_DragEnter(ByVal sender As Object, ByVal e As _
System.Windows.Forms.DragEventArgs) Handles TextBox2.DragEnter
' Check the format of the data being dropped.
If (e.Data.GetDataPresent(DataFormats.Text)) Then
' Display the copy cursor.
e.Effect = DragDropEffects.Copy
Else
' Display the no-drop cursor.
e.Effect = DragDropEffects.None
End If
End Sub

Private Sub TextBox2_DragDrop(ByVal sender As Object, ByVal e As _
System.Windows.Forms.DragEventArgs) Handles TextBox2.DragDrop
' Paste the text.
TextBox2.Text = e.Data.GetData(DataFormats.
End Sub

    在上面的例子中,MouseDown事件是用来判断鼠标是否按下的,MouseMove事件中用到了DoDragDrop方法。尽管你可以在MouseDown事件中来初始化Drag,然而这么做会带来出人意料之外的结果。在用户点击控件时,将显示no-drag 指针。DoDragDrop方法有两个参数
    data,这个例子中代表的是第一个TextBox的Text属性。
    allowedEffects,这个例子中是只允许复制。
      在MouseMove事件中MouseIsDown标志设置成了False,尽管在这个例子没有必要,但是如果你有很多控件支持拖放时,你将会得到一个运行时例外。
    在DragEnter事件中,GetDataPresent方法检查正在拖动的数据格式,在本例中是文本,所以Effect属性设置成复制,同时也显示copy指针。
      在DragDrop事件中,GetData方法用来从DataObject中获得文本,并把它送给目标文本框。
    拖动图片
      尽管拖放图片并不像拖放文本那样经常用到,然而它在许多应用程序中仍然是很有用的。实际上这两者之间也没有什么不同,只不过是数据类型发生了变化而已。
    1、 在Form中添加两个PictureBox控件。
    2、 在代码窗体中添加如下代码

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As _
    System.EventArgs) Handles MyBase.Load
    ' Enable dropping.
    PictureBox2.AllowDrop = True
    End Sub
    
    Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As _
    System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
    If Not PictureBox1.Image Is Nothing Then
    ' Set a flag to show that the mouse is down.
    m_MouseIsDown = True
    End If
    End Sub
    
    Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As _
    System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
    If m_MouseIsDown Then
    ' Initiate dragging and allow either copy or move.
    PictureBox1.DoDragDrop(PictureBox1.Image, DragDropEffects.Copy Or _
    DragDropEffects.Move)
    End If
    m_MouseIsDown = False
    End Sub
    
    Private Sub PictureBox2_DragEnter(ByVal sender As Object, ByVal e As _
    System.Windows.Forms.DragEventArgs) Handles PictureBox2.DragEnter
    If e.Data.GetDataPresent(DataFormats.Bitmap) Then
    ' Check for the CTRL key. 
    If e.KeyState = 9 Then
    e.Effect = DragDropEffects.Copy
    Else
    e.Effect = DragDropEffects.Move
    End If
    Else
    e.Effect = DragDropEffects.None
    End If
    End Sub
    
    Private Sub PictureBox2_DragDrop(ByVal sender As Object, ByVal e As _
    System.Windows.Forms.DragEventArgs) Handles PictureBox2.DragDrop
    ' Assign the image to the PictureBox.
    PictureBox2.Image = e.Data.GetData(DataFormats.Bitmap)
    ' If the CTRL key is not pressed, delete the source picture.
    If Not e.KeyState = 8 Then
    PictureBox1.Image = Nothing
    End If
    End Sub
    
      34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    注意到上面的例子中第二个PictureBox控件的AllowDrop属性是在Form1_load事件中设置的,这是因为设计时PictureBox并没有AllowDrop属性。
    在MouseDown事件中,代码首先检测是否有要赋给PictureBox的图片;如果没有的话,当你移动图片后,接下来的click将引发一个意外。
    还应该注意到的是在DragEnter和DragDrop事件中代码检测CTRL键是否被按下,从而决定是否是复制还是移动图片。为什么值会不同呢?在DragEnter事件中,当鼠标左键按下时,产生的值是1,在加上CTRL的值8,从而值为9。见KeyState枚举列表DragEventArgs.KeyState Property(?url=/library/en-us/cpref/html/frlrfsystemwindowsformsdrageventargsclasskeystatetopic.asp)。
    到目前为止,这两个例子处理的都是同一窗体不同控件间的拖放,然而在同一应用程序的不同窗体上同样适用。
    拖动文件
      在windows中拖放通常是复制或移动文件,windows完全支持该功能,而且对许多用户来说这也是操作文件的优选方式。除此之外,用户已经习惯了把文件拖动到一个程序来打开文件的方式,像拖动一个doc文件到word来打开。
      在这个例子中用从windows资源管理器拖来的文件来操作ListBox控件。
    向窗体中添加一个ListBox控件,并设置其AllowDrop属性为True,并添加如下代码:

    Private Sub ListBox1_DragEnter(ByVal sender As Object, ByVal e As _
    System.Windows.Forms.DragEventArgs) Handles ListBox1.DragEnter
    If e.Data.GetDataPresent(DataFormats.FileDrop) Then
    e.Effect = DragDropEffects.All
    End If
    End Sub
    
    Private Sub ListBox1_DragDrop(ByVal sender As Object, ByVal e As _
    System.Windows.Forms.DragEventArgs) Handles ListBox1.DragDrop
    If e.Data.GetDataPresent(DataFormats.FileDrop) Then
    Dim MyFiles() As String
    Dim i As Integer
    
    ' Assign the files to an array.
    MyFiles = e.Data.GetData(DataFormats.FileDrop)
    ' Loop through the array and add the files to the list.
    For i = 0 To MyFiles.Length - 1
    ListBox1.Items.Add(MyFiles(i))
    Next
    End If
    End Sub
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    你可能已经注意到了DragEnter事件中的Effect属性被设置成DragDropEffects.All。因为文件本身并不是真的就被复制或移动了,因此源控件设置成哪个AllowedEffects并没有关系,所以指定All对任何FileDrop都可以。
      在上面的例子中FileDrop格式包含了每个被拖动文件的全路径。
      下面的例子讲述了拖放的一个特殊情况:在两个列表间来回拖放。
    表间拖放
    拖放的另一个情况是从一个列表移动项目到另一个列表。这种情况下拖放将变得更加简单。
    向窗体中添加两个ListView控件,并把他们的AllowDrop、Multiselect、View属性分别设置成True、True、List。并添加如下代码:

    Private Sub ListView_ItemDrag(ByVal sender As Object, ByVal e As _
    System.Windows.Forms.ItemDragEventArgs) Handles ListView1.ItemDrag, _
    ListView2.ItemDrag
    Dim myItem As ListViewItem
    Dim myItems(sender.SelectedItems.Count - 1) As ListViewItem
    Dim i As Integer = 0
    
    ' Loop though the SelectedItems collection for the source.
    For Each myItem In sender.SelectedItems
    ' Add the ListViewItem to the array of ListViewItems.
    myItems(i) = myItem
    i = i + 1
    Next
    ' Create a DataObject containg the array of ListViewItems.
    sender.DoDragDrop(New _
    DataObject(System.Windows.Forms.ListViewItem(), myItems), _
    DragDropEffects.Move)
    End Sub
    
    Private Sub ListView_DragEnter(ByVal sender As Object, ByVal e As _
    System.Windows.Forms.DragEventArgs) Handles ListView1.DragEnter, _
    ListView2.DragEnter
    ' Check for the custom DataFormat ListViewItem array.
    If e.Data.GetDataPresent(System.Windows.Forms.ListViewItem()) Then
    e.Effect = DragDropEffects.Move
    Else
    e.Effect = DragDropEffects.None
    End If
    End Sub
    
    Private Sub ListView_DragDrop(ByVal sender As Object, ByVal e As _
    System.Windows.Forms.DragEventArgs) Handles ListView1.DragDrop, _
    ListView2.DragDrop
    Dim myItem As ListViewItem
    Dim myItems() As ListViewItem = _ e.Data.GetData(System.Windows.Forms.ListViewItem())
    Dim i As Integer = 0
    
    For Each myItem In myItems
    ' Add the item to the target list.
    sender.Items.Add(myItems(i).Text)
    ' Remove the item from the source list.
    If sender Is ListView1 Then
    ListView2.Items.Remove(ListView2.SelectedItems.Item(0))
    Else
    ListView1.Items.Remove(ListView1.SelectedItems.Item(0))
    End If
    i = i + 1
    Next
    End Sub
    
      34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    你可能不明白为什么这个例子中用的是ListView控件而不是ListBox控件,这个问题题的好,因为ListBox控件不支持多项拖放。
    ListView和TreeView控件有个ItemDrag事件。上面的例子中,一个ItemDrag事件句柄覆盖了两个控件,并在列在Handles从句。Sender参数表明哪个控件正在初始化Drag。
    因为DataFormats类没有ListViewItem类型成员,数据必须传递给一个系统类型。ItemDrag创建了一个ListViewItem类型的数组,并用一个循环来遍历SelectedItem集合。在DoDragDrop方法中,创建了一个新的DataObject并用数组来来对它进行操作。可以用这种方法来拖放任何系统类型。
    结论:
      正像你从这些例子中所看到的一样,为应用程序添加拖放操作并不是很难。当你理解了这些基本的技巧后,你就可以为你自己的程序添加拖放的代码了

    相关技术文章

    点击QQ咨询
    开通会员
    返回顶部
    ×
    微信扫码支付
    微信扫码支付
    确定支付下载
    请使用微信描二维码支付
    ×

    提示信息

    ×

    选择支付方式

    • 微信支付
    • 支付宝付款
    确定支付下载