C# Winform 涉及的拖放操作總結
在開發程序的時候,為了提高用戶的使用體驗,或滿足相關用戶的功能,總是離不開拖放功能。而本文是總結winform下的常用拖放操作。主要有
1.textbox接受拖放的文件
2.listbox允許用戶自定義排序
3.listbox之間的拖放
4.控件的拖放
5.console的拖放問題
用戶在進行拖放操作時,經過的步驟大體如下:
例如將A中的數據拖放的B中
鼠標點擊A中的數據(MouseDown)->鼠標移動(MouseMove)->出源數據邊界,即出A(DragLeave)->進入目標邊界,進入B(DragEnter)->在B中移動,選擇放數據的位置,即拖動效果(DragOver)->抬起鼠標(MouseDown)->將A數據放到B中,拖放結束。(DragDrop,所有的拖放都涉及DragDrop事件)。
下面的所有例子,都會使用到上面所列舉的幾個事件。
一、textbox接受拖放的文件。為了方便用戶的使用,這個應該是最常用到的操作。加入這個功能,可以使用戶省去“打開文件對話框,然后選擇文件”的操作。在這個例子中,我們不需要知道用戶的點擊,即選擇了什么文件。只需要了解用戶拖動文件進入Textbox(DragEnter),並松開鼠標,完成拖放(DragDrop)。主要涉及到兩個事件。
DragEnter:在將對象拖入控件的邊界時發生。判斷是否是文件拖放
DragDrop:在完成拖放操作時發生。判斷文件類型,只添加txt文件
首先添加一個textBox控件,將控件的屬性設置為AllowDrop=True,Multiline=True
代碼如下:
private void textBox1_DragEnter(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { e.Effect = DragDropEffects.Copy; } } private void textBox1_DragDrop(object sender, DragEventArgs e) { string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); foreach (string file in files) { if(Path.GetExtension(file)==".txt") //判斷文件類型,只接受txt文件 { textBox1.Text += file + "\r\n"; } } }
二、listbox允許用戶自定義排序。在一個listbox中的拖放操作,我們要知道用戶選擇了什么數據(MouseDown),要把數據放到哪里,即坐標(DragOver),完成拖放(DragDrop)。主要涉及的事件有3個
MouseDown:選擇Listbox中的item
DragOver: 鼠標的移動
DragDrop: 拖放完成。在鼠標當前位置插入數據
首先在窗體上加入Listbox控件,將AllowDrop屬性設置為True
代碼如下:
private void FrmListboxDragTest_Load(object sender, EventArgs e) { for (int i = 0; i <= 20; i++) { this.listBox1.Items.Add(string.Format("事件{0}",i)); } } private void listBox1_MouseDown(object sender, MouseEventArgs e) { if (this.listBox1.SelectedItem == null) { return; } //開始拖放操作,DragDropEffects為枚舉類型。 //DragDropEffects.Move 為將源數據移動到目標數據 this.listBox1.DoDragDrop(this.listBox1.SelectedItem, DragDropEffects.Move); } private void listBox1_DragOver(object sender, DragEventArgs e) { e.Effect = DragDropEffects.Move; } private void listBox1_DragDrop(object sender, DragEventArgs e) { Point point = listBox1.PointToClient(new Point(e.X, e.Y)); int index = this.listBox1.IndexFromPoint(point); if (index < 0) { index = this.listBox1.Items.Count - 1; } //獲取拖放的數據內容 object data = e.Data.GetData(typeof(string)); //刪除元數據 this.listBox1.Items.Remove(data); //插入目標數據 this.listBox1.Items.Insert(index, data); }
三.listbox之間的拖放。因為是在Listbox之間拖放數據,所以涉及到兩個控件。假如本例是將Listbox1中的數據拖放到Listbox2中。那涉及的事件有4個
Listbox1 中的MouseDown:選取Listbox1中的數據
Listbox2 中的DragEnter:拖放操作進入Listbox2
Listbox2 中的DragOver: 在Listbox2上移動
Listbox2 中的DragDrop: 拖放完畢,在Listbox2中顯示數據
代碼如下:
private void FrmTwoListboxDragTest_Load(object sender, EventArgs e) { for (int i = 0; i <= 20; i++) { this.listBox1.Items.Add(string.Format("listbox1中的數據{0}", i)); this.listBox2.Items.Add(string.Format("listbox2中的數據{0}", i)); } } private void listBox1_MouseDown(object sender, MouseEventArgs e) { if (listBox1.Items.Count == 0) return; int index = listBox1.IndexFromPoint(e.X, e.Y); string s = listBox1.Items[index].ToString(); listBox1.DoDragDrop(s, DragDropEffects.Copy); } private void listBox2_DragEnter(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.StringFormat)) e.Effect = DragDropEffects.Copy; } private void listBox2_DragOver(object sender, DragEventArgs e) { e.Effect = DragDropEffects.All; } private void listBox2_DragDrop(object sender, DragEventArgs e) { Point point = listBox2.PointToClient(new Point(e.X, e.Y)); int index = this.listBox1.IndexFromPoint(point); if (index < 0) { index = this.listBox1.Items.Count - 1; } object data = e.Data.GetData(typeof(string)); this.listBox1.Items.Remove(data); this.listBox2.Items.Insert(index, data); }
4.控件的拖放。以pictureBox為例。涉及的事件有
MouseDown 選取pictureBox,可以判斷鼠標按鍵(左鍵還是右鍵等)
MouseMove 移動鼠標到指定位置
MouseUp 釋放鼠標按鍵,放下pictureBox
在進行控件移動的時候,需要明白pictureBox的坐標並不是鼠標的坐標,MouseDown只是在鼠標按下后執行一次,而MouseMove隨着pictureBox的移動而不停的觸發。
代碼如下:
private bool _clicked = false; private int _clickx; private int _clicky; private int _mouseDownCount = 1; private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { if (_clicked) { Point p = new Point(); p.X = e.X + pictureBox1.Left; p.Y = e.Y + pictureBox1.Top; pictureBox1.Left = p.X - _clickx; pictureBox1.Top = p.Y - _clicky; lblMouseMove.Text = string.Format("{0}:{1}", pictureBox1.Left, pictureBox1.Top); } } private void pictureBox1_MouseUp(object sender, MouseEventArgs e) { _clicked = false; lblMouseUp.Text = string.Format("{0}:{1}", e.X,e.Y); } private void pictureBox1_MouseDown(object sender, MouseEventArgs e) { pictureBox1.Left = e.X; pictureBox1.Top = e.Y; _clickx = e.X; _clicky = e.Y; lblMouseDown.Text = string.Format("{0}:{1}:{2}", e.X, e.Y,_mouseDownCount); _clicked = true; _mouseDownCount += 1; }
五、console的拖放問題
console 的拖放時最簡單的一種操作,因為console本身就支持拖放(如同cmd)。而我們所要做的只是添加一行代碼,然后等待用戶按下回車。例如:
string content=Console.ReadLine(); Console.WriteLine(content); Console.ReadLine();