DragDrop在运行时移动图片框

时间:2012-11-06 05:42:13

标签: c# winforms

我有一个名为pic的PictureBox,放在另一个名为picTrack的PictureBox中。

我的目标是让用户在运行时通过拖动来更改pic的位置。

这是我到目前为止所做的:

    int x_offset = 0; // any better to do this without having a global variable?
    int y_offset = 0;
    void pic_MouseDown(object sender, MouseEventArgs e)
    {
        PictureBox me = (PictureBox)sender;
        x_offset = me.Left - e.X;
        y_offset = me.Top - e.Y;
    }

    void pic_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            PictureBox me = (PictureBox)sender;
            me.Left = e.X + x_offset; 
            me.Top = e.Y + y_offset;
            picTrack.Invalidate();
        }
    }

此代码仅适用于非常基本的级别。我有两个问题:

1。)如果用户没有松开鼠标按钮,则不会更新picTrack。当pic被移动时,可以看到pic的幽灵图像(就像pic有尾巴一样)。

2。)pic是“咯咯地笑”(即在其位置周围快速左右上下摇晃)。

我应该如何解决这两个问题,并创造一个更平稳的阻力&下降?感谢。

2 个答案:

答案 0 :(得分:1)

这实际上有效,我之前写了很多拖东西......它可能不完美但是这应该给你一些工作。

    Point dragPoint = Point.Empty;
    bool dragging = false;

    private void pic_MouseDown(object sender, MouseEventArgs e)
    {
        dragging = true;
        dragPoint = new Point(e.X, e.Y);
    }

    private void pic_MouseMove(object sender, MouseEventArgs e)
    {
        if (dragging)
            pic.Location = new Point(pic.Location.X + e.X - dragPoint.X, pic.Location.Y + e.Y - dragPoint.Y);
    }

    private void pic_MouseUp(object sender, MouseEventArgs e)
    {
        dragging = false;
    }

请参阅,如果您要拖动自己刚刚渲染的局部图片,这样就不对了..但是因为移动后移动控件,所以新的移动坐标相对于对照。因此,您无需将dragPoint更新到移动时的最后位置。如果你只是移动一个你正在渲染OnPaint的形状/图像,你必须每次移动都更新拖动点。

如果需要,您可以进行一项改进,即只有当用户将光标移动一定距离D时才开始拖动。例如,类似这样的事情:

    Point dragPoint = Point.Empty;
    bool dragging = false;
    bool mouseDown = false;

    private void pic_MouseDown(object sender, MouseEventArgs e)
    {
        mouseDown = true;
        dragPoint = new Point(e.X, e.Y);
    }

    private void pic_MouseMove(object sender, MouseEventArgs e)
    {
        int deltaX = e.X - dragPoint.X;
        int deltaY = e.Y - dragPoint.Y;

        if (!dragging && mouseDown && deltaX * deltaX + deltaY * deltaY > 100)
            dragging = true;

        if (dragging)
            pic.Location = new Point(pic.Location.X + deltaX, pic.Location.Y + deltaY);
    }

    private void pic_MouseUp(object sender, MouseEventArgs e)
    {
        dragging = false;
        mouseDown = false;
    }

检查用户是否将鼠标移动了10个像素(sqrt of 100)。

如果您不想要全局,您可以尝试实现自己的行为系统并创建一个可重复使用的代码片段,您可以将其附加到您想要移动的内容上。像这样:

public class Behavior<T> where T : class 
{
    public T AssociatedObject
    {
        get;
        private set;
    }

    public Behavior(T associatedObject)
    {
        this.AssociatedObject = associatedObject;
    }

    public virtual void Attach() { }
    public virtual void Detach() { }
}

public class DragBehavior : Behavior<Control>
{
    Point dragPoint = Point.Empty;
    bool dragging = false;
    bool mouseDown = false;

    public DragBehavior(Control c) : base(c)
    {

    }

    public override void Attach()
    {
        AssociatedObject.MouseDown += new MouseEventHandler(control_MouseDown);
        AssociatedObject.MouseMove += new MouseEventHandler(control_MouseMove);
        AssociatedObject.MouseUp += new MouseEventHandler(control_MouseUp);
    }

    private void control_MouseUp(object sender, MouseEventArgs e)
    {
        dragging = false;
        mouseDown = false;
    }

    private void control_MouseMove(object sender, MouseEventArgs e)
    {
        int deltaX = e.X - dragPoint.X;
        int deltaY = e.Y - dragPoint.Y;

        if (mouseDown && deltaX * deltaX + deltaY * deltaY > 100)
            dragging = true;

        if (dragging)
            AssociatedObject.Location = new Point(AssociatedObject.Location.X + deltaX, AssociatedObject.Location.Y + deltaY);
    }

    private void control_MouseDown(object sender, MouseEventArgs e)
    {
        mouseDown = true;
        dragPoint = new Point(e.X, e.Y);
    }

    public override void Detach()
    {
        AssociatedObject.MouseDown -= new MouseEventHandler(control_MouseDown);
        AssociatedObject.MouseMove -= new MouseEventHandler(control_MouseMove);
        AssociatedObject.MouseUp -= new MouseEventHandler(control_MouseUp);
    }
}

public partial class Form1 : Form
{
    DragBehavior dragger;

    public Form1()
    {
        InitializeComponent();
        DoubleBuffered = true;

        dragger = new DragBehavior(pic);
        dragger.Attach();
    }       
}

也许这比“创建全局变量”更好(或者更像是在表单中创建成员变量。=)

答案 1 :(得分:0)

试试这个

int x_offset = 0; // any better to do this without having a global variable?
int y_offset = 0;
private void pic_MouseDown(object sender, MouseEventArgs e)
{
   PictureBox me = (PictureBox)sender;
   x_offset = e.X;
   y_offset = e.Y;
}

private void pic_MouseMove(object sender, MouseEventArgs e)
{
  if (e.Button == System.Windows.Forms.MouseButtons.Left)
  {
     PictureBox me = (PictureBox)sender;
     me.Left = e.X + me.Left - x_offset;
     me.Top = e.Y + me.Top - y_offset;
   }
}