有一個MSDN客戶提問在WinForm中如何實現拖拽效果——比如在WinForm中有一個Button,我要實現的效果是拖拽這個Button到目標位置后生成一個該控件的副本。
其實這個操作主要分成三步走:
1)確定被拖拽的對象:這里是Button(要使得Button被單擊之后可以拖拽,那么必須處理其MouseDown事件,同時調用其DoDragDrop——該函數接受兩個參數:i)要拖動的數據。ii)拖動的效果(該效果是2“目標位置”所能夠接受的效果,是一個枚舉值):
[C#]
Button1.DoDragDrop(Button1, DragDropEffects.Copy || DragDropEffects.Move); //形成拖拽效果,移動+拷貝的組合效果
[VB.NET]
Button1.DoDragDrop(Button1, DragDropEffects.Copy Or DragDropEffects.Move) '形成拖拽效果,移動+拷貝的組合效果
2)目標位置:這里是Form窗體自身。為了使得和Windows資源管理器中實現的文件拖拽效果一樣(即拖拽一個文件到目標位置的中途,鼠標出現“+”號的效果)。那么應當處理DragEnter事件——即拖拽控件途中進入Form體內把效果設置成Copy的效果。
[C#]
private void Form1_DragEnter(System.Object sender, System.Windows.Forms.DragEventArgs e) { //當Button被拖拽到WinForm上時候,鼠標效果出現 if ((e.Data.GetDataPresent(typeof(Button)))) { e.Effect = DragDropEffects.Copy; } }
[VB.NET]
Private Sub Form1_DragEnter(sender As System.Object, e As System.Windows.Forms.DragEventArgs) Handles MyBase.DragEnter If (e.Data.GetDataPresent(GetType(Button))) Then '當Button被拖拽到WinForm上時候,鼠標效果出現 e.Effect = DragDropEffects.Copy End If End Sub
同時,為了使得Form自身支持接受拖拽傳來的控件,必須設置其AllowDrag=True:
另外,一旦松開鼠標,那么拖拽過程結束。此時應當處理DragDrop事件,復制一個按鈕:
[C#]
private void Form1_DragDrop(System.Object sender, System.Windows.Forms.DragEventArgs e) { //拖放完畢之后,自動生成新控件 Button btn = new Button(); btn.Size = Button1.Size; btn.Location = this.PointToClient(new Point(e.X, e.Y)); //用這個方法計算出客戶端容器界面的X,Y坐標。否則直接使用X,Y是屏幕坐標 this.Controls.Add(btn); btn.Text = "按鈕" + count.ToString; count = count + 1; }
[VB.NET]
Private Sub Form1_DragDrop(sender As System.Object, e As System.Windows.Forms.DragEventArgs) Handles MyBase.DragDrop '拖放完畢之后,自動生成新控件 Dim btn As New Button btn.Size = Button1.Size btn.Location = Me.PointToClient(New Point(e.X, e.Y)) '用這個方法計算出客戶端容器界面的X,Y坐標。否則直接使用X,Y是屏幕坐標 Me.Controls.Add(btn) btn.Text = "按鈕" + count.ToString count = count + 1 End Sub
這里需要注意點:Location屬性(指定控件放置位置的起始點)不能直接用e.X或e.Y——因為這是屏幕坐標,要根據實際的控件界面坐標進行適度轉換,最簡單方法是——PointToClient方法。
好了,以下給出完整代碼:
【界面】
[C#]
using Microsoft.VisualBasic; using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics; public class Form1 { //計數變量,說明輸出了第N個Button private int count = 1; private void Form1_Load(System.Object sender, System.EventArgs e) { this.AllowDrop = true; //窗體自身支持接受拖拽來的控件 } private void Button1_MouseDown(System.Object sender, System.Windows.Forms.MouseEventArgs e) { //左鍵的話,標志位為true(表示拖拽開始) if ((e.Button == System.Windows.Forms.MouseButtons.Left)) { Button1.DoDragDrop(Button1, DragDropEffects.Copy | DragDropEffects.Move); //形成拖拽效果,移動+拷貝的組合效果 } } private void Form1_DragEnter(System.Object sender, System.Windows.Forms.DragEventArgs e) { //當Button被拖拽到WinForm上時候,鼠標效果出現 if ((e.Data.GetDataPresent(typeof(Button)))) { e.Effect = DragDropEffects.Copy; } } private void Form1_DragDrop(System.Object sender, System.Windows.Forms.DragEventArgs e) { //拖放完畢之后,自動生成新控件 Button btn = new Button(); btn.Size = Button1.Size; btn.Location = this.PointToClient(new Point(e.X, e.Y)); //用這個方法計算出客戶端容器界面的X,Y坐標。否則直接使用X,Y是屏幕坐標 this.Controls.Add(btn); btn.Text = "按鈕" + count.ToString(); count = count + 1; } public Form1() { DragDrop += Form1_DragDrop; DragEnter += Form1_DragEnter; Load += Form1_Load; } }
[VB.NET]
Public Class Form1 '計數變量,說明輸出了第N個Button Private count As Integer = 1 Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load Me.AllowDrop = True '窗體自身支持接受拖拽來的控件 End Sub Private Sub Button1_MouseDown(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles Button1.MouseDown '左鍵的話,標志位為true(表示拖拽開始) If (e.Button = Windows.Forms.MouseButtons.Left) Then Button1.DoDragDrop(Button1, DragDropEffects.Copy Or DragDropEffects.Move) '形成拖拽效果,移動+拷貝的組合效果 End If End Sub Private Sub Form1_DragEnter(sender As System.Object, e As System.Windows.Forms.DragEventArgs) Handles MyBase.DragEnter If (e.Data.GetDataPresent(GetType(Button))) Then '當Button被拖拽到WinForm上時候,鼠標效果出現 e.Effect = DragDropEffects.Copy End If End Sub Private Sub Form1_DragDrop(sender As System.Object, e As System.Windows.Forms.DragEventArgs) Handles MyBase.DragDrop '拖放完畢之后,自動生成新控件 Dim btn As New Button btn.Size = Button1.Size btn.Location = Me.PointToClient(New Point(e.X, e.Y)) '用這個方法計算出客戶端容器界面的X,Y坐標。否則直接使用X,Y是屏幕坐標 Me.Controls.Add(btn) btn.Text = "按鈕" + count.ToString count = count + 1 End Sub End Class