我正在尝试构建自己的“PictureBox like”控件添加一些功能。例如,我希望只需单击并拖动鼠标即可平移大图像。
问题似乎出在我的 OnMouseMove 方法上。如果我使用下面的代码,我会得到我想要的拖动速度和精度,但当然,当我释放鼠标按钮并尝试再次拖动时,图像将恢复到原始位置。
using System.Drawing;
using System.Windows.Forms;
namespace Testing
{
public partial class ScrollablePictureBox : UserControl
{
private Image image;
private bool centerImage;
public Image Image
{
get { return image; }
set { image = value; Invalidate(); }
}
public bool CenterImage
{
get { return centerImage; }
set { centerImage = value; Invalidate(); }
}
public ScrollablePictureBox()
{
InitializeComponent();
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
Image = null;
AutoScroll = true;
AutoScrollMinSize = new Size(0, 0);
}
private Point clickPosition;
private Point scrollPosition;
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
clickPosition.X = e.X;
clickPosition.Y = e.Y;
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (e.Button == MouseButtons.Left)
{
scrollPosition.X = clickPosition.X - e.X;
scrollPosition.Y = clickPosition.Y - e.Y;
AutoScrollPosition = scrollPosition;
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.FillRectangle(new Pen(BackColor).Brush, 0, 0, e.ClipRectangle.Width, e.ClipRectangle.Height);
if (Image == null)
return;
int centeredX = AutoScrollPosition.X;
int centeredY = AutoScrollPosition.Y;
if (CenterImage)
{
//Something not relevant
}
AutoScrollMinSize = new Size(Image.Width, Image.Height);
e.Graphics.DrawImage(Image, new RectangleF(centeredX, centeredY, Image.Width, Image.Height));
}
}
}
但如果我将 OnMouseMove 方法修改为如下所示:
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (e.Button == MouseButtons.Left)
{
scrollPosition.X += clickPosition.X - e.X;
scrollPosition.Y += clickPosition.Y - e.Y;
AutoScrollPosition = scrollPosition;
}
}
...你会发现拖动不像以前那样平滑,有时表现得很奇怪(比如滞后或其他)。
我做错了什么?
我也尝试删除绝望运动中的所有“基本”电话来解决这个问题,哈哈,但是再次,它没有用。
感谢您的时间。
答案 0 :(得分:3)
最后,我设法找到了解决方案:
protected Point clickPosition;
protected Point scrollPosition;
protected Point lastPosition;
protected override void OnMouseDown(MouseEventArgs e)
{
clickPosition.X = e.X;
clickPosition.Y = e.Y;
}
protected override void OnMouseUp(MouseEventArgs e)
{
Cursor = Cursors.Default;
lastPosition.X = AutoScrollPosition.X;
lastPosition.Y = AutoScrollPosition.Y;
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Cursor = Cursors.Hand;
scrollPosition.X = clickPosition.X - e.X - lastPosition.X;
scrollPosition.Y = clickPosition.Y - e.Y - lastPosition.Y;
AutoScrollPosition = scrollPosition;
}
}
答案 1 :(得分:2)
每次我必须这样做时总会让人感到困惑。 为了新来到这个线程的人的利益,我提出了一个稍微简单的解决方案,可以平滑地进行平移。
Private GrabPoint As Point
Private Sub OnMouseDown(MouseEventArgs e)
GrabPoint = e.Location
End Sub
Private Sub OnMouseMove(MouseEventArgs e)
If e.Button = System.Windows.Forms.MouseButtons.Left Then
AutoScrollPosition = GrabPoint - e.Location - AutoScrollPosition
End If
End Sub
Private Sub OnMouseUp(MouseEventArgs e)
GrabPoint = Point.Empty
End Sub
顺便说一句,抓取和抓取手形游标可以从以下位置下载: http://theburningmonk.com/2010/03/wpf-loading-grab-and-grabbing-cursors-from-resource/
您可以将它们作为嵌入资源添加到项目中,并使用以下命令进行设置:
Cursor = New Cursor(System.Reflection.Assembly.GetExecutingAssembly.GetManifestResourceStream(String.Format("{0}.{1}.cur", Me.GetType.Namespace, "grabbing")))