0

というpic別の PictureBox 内に配置された という PictureBox がありpicTrackます。

私の目標は、ユーザーが実行時に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();
        }
    }

このコードは非常に基本的なレベルでのみ機能します。私はそれに2つの問題があります:

1.)picTrackユーザーがマウス ボタンを離さない場合、更新されません。が動き回っている間、 の幽霊像picが見られます(尻尾が付いているようなものです)。picpic

2.) pic「くすくす笑っている」(つまり、その場所の周囲で上下左右に素早く揺れる)。

この 2 つの問題を解決し、よりスムーズなドラッグ & ドロップを作成するにはどうすればよいですか? ありがとう。

4

2 に答える 2

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 移動した場合にのみドラッグを開始するという改善策が 1 つあります。たとえば、次のようなものです。

    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 ピクセル (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();
    }       
}

多分それは「グローバル変数を作成する」よりも優れています(または、フォームでメンバー変数を作成するようなものです。=)

于 2012-11-06T06:51:23.703 に答える
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;
   }
}
于 2012-11-06T05:56:55.483 に答える