用鼠标移动一个PictureBox

3

我正在开发一个针对Windows Mobile(Compact Framework 2.0)的应用程序。它有一个带有PictureBox的WinForms。

我想移动PictureBox的图像,但是我不知道如何做,所以我选择移动整个PictureBox。

为了实现这一点,我使用了以下事件:

private void imagenMapa_MouseMove(object sender, MouseEventArgs e)
{
      imagenMapa.Left = e.X;
      imagenMapa.Top = e.Y;
      this.Refresh();
}

但是当我移动PictureBox时,它会闪烁并且随处移动。

我做错了什么?

6个回答

7

实际代码(需要.NET Framework 3.5及以上版本,不确定Compact Framework是否可用)...

// Global Variables
private int _xPos;
private int _yPos;
private bool _dragging;

// Register mouse events
pictureBox.MouseUp += (sender, args) =>
{
    var c = sender as PictureBox;
    if (null == c) return;
    _dragging = false;
};

pictureBox.MouseDown += (sender, args) =>
{
    if (args.Button != MouseButtons.Left) return;
    _dragging = true;
    _xPos = args.X;
    _yPos = args.Y;
};

pictureBox.MouseMove += (sender, args) =>
{
    var c = sender as PictureBox;
    if (!_dragging || null == c) return;
    c.Top = args.Y + c.Top - _yPos;
    c.Left = args.X + c.Left - _xPos;
};

这个工作完美无缺!感谢您花时间分享代码 :) - saurabhj

6
e.Xe.Y 的值是相对于图片框的位置(例如,如果鼠标位于图片框的左上角,那么位置为0,0)。 imagenMapa.LeftimagenMapa.Top 的值是相对于窗体(或包含 imagenMapa 控件的任何控件)的位置。
如果你尝试在没有转换的情况下混合使用这两个系统的值,你会看到跳跃现象(就像你现在所看到的)。
你最好将鼠标位置转换为与包含图片框的控件所使用的相同坐标系。
你可以使用imagenMapa.PointToScreen来获取鼠标在屏幕坐标系中的位置(或使用Cursor.Position直接获取位置),并使用yourForm.PointToClient将其转换回窗体坐标系中。
请注意,根据您的需求,您可以通过覆盖/处理控件的Paint事件并自己绘制图像来实现在控件内移动图像。如果您这样做,您可以保持所有内容在图片框坐标系中,因为那些是您在调用graphicsObject.DrawImage时使用的坐标系。

Daniel,这是很好的理论,但你能把它转化为代码吗?我有完全相同的问题,但是使用VB.net。请帮忙! - Alex Gordon

1

拥抱数学!

control.Left = control.Left - (_lastMousePos.X - currentMousePos.X);
control.Top = control.Top - (_lastMousePos.Y - currentMousePos.Y);

快速解释: 您可以从鼠标位置获取差异并将其应用于要移动的对象。
例子: 如果旧鼠标X位置为382,新位置为385,则差值为-3。 如果控件当前X位置为10,则10 - (-3) = 13
为什么: 它适用于任何事情,并且比不断转换坐标便宜得多。

1

e.X和e.Y在pictureBox的坐标空间中,imagenMapa.Left和imagenMapa.Top在Form的坐标空间中。 :-)


1

另外别忘了将你的表单设置为双缓冲,这可能有助于消除闪烁,但对于其实际定位,我喜欢Daniel L的建议。


我正在使用紧凑框架,但表单没有双缓冲。我该怎么做? - VansFannel
这个链接描述了如何创建一个“双缓冲”图片框。很抱歉,我想当你提到CF 2.0时我没有注意到。 http://stackoverflow.com/questions/574958/c-cf-winforms-and-double-buffer - Fry

1
实际上你所做的是正确的。但是你把MouseMove属性给了picturebox。你应该把这个属性给Form(背景)。
例如:
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
  imagenMapa.Left = e.X;
  imagenMapa.Top = e.Y;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接