C# Winform 拖放操作

http://www.cnblogs.com/imlions/p/3189773.html

在开发程序的时候,为了提高用户的使用体验,或满足相关用户的功能,总是离不开拖放功能。而本文是总结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事件)。

下面的所有例子,都会使用到上面所列举的几个事件。

首先对目标组件set "AllowDrop" to true

 

一、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();

 

 

Ohter:

DragDropEffects 枚举

成员名称说明
  All Copy   、Move 和 Scroll 效果的组合。
  Copy 将拖动源中的数据复制到放置目标。
  Link 将拖动源中的数据链接到放置目标。
  Move 将拖动源的数据移动到放置目标。
  None 放置目标不接受该数据。
  Scroll 拖动时可以滚动目标,以定位在目标中当前不可见的某个放置位置。

 

 

The only difference is the cursor, the user can tell from the cursor appearance whether your program will do a move or a copy.  The copy cursor has a +, the move cursor doesn't.

http://msdn.microsoft.com/zh-cn/library/system.windows.forms.dragdropeffects.aspx

http://stackoverflow.com/questions/10789027/whats-the-difference-between-dragdropeffects-copy-and-dragdropeffects-move

 

posted @ 2014-08-26 09:43  vivianC  阅读(1205)  评论(0编辑  收藏  举报