我有一个名为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
是“咯咯地笑”(即在其位置周围快速左右上下摇晃)。
我应该如何解决这两个问题,并创造一个更平稳的阻力&下降?感谢。
答案 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;
}
}