winforms と .Net 3.5 で画像のズームとパンを可能にするパネルを作成しようとしています。ほぼそこにいると思いますが、ズーム機能で問題が発生しています。
画像の中心を拡大しようとしているのですが、なぜか少しズレています。私はジオメトリについて考えるのが本当に苦手で、どこが間違っているのかを理解するための助けを本当に感謝しています.
コードは次のとおりです。
public class ImageViewer : Panel
{
public double ZoomFactor
{
get { return this.zoomFactor; }
set
{
this.zoomFactor = value;
this.Invalidate();
}
}
public Point Translation { get; set; }
/// <summary>
/// The image to be displayed
/// </summary>
[Category("Appearance"), Description("The image to be displayed.")]
public Image Image
{
get { return this.image; }
set
{
this.image = value;
this.ZoomExtents();
this.Invalidate();
}
}
private double initialScale;
private double zoomFactor;
private Image image;
private Point startingPoint;
/// <summary>
/// Class constructor
/// </summary>
public ImageViewer()
{
this.DoubleBuffered = true;
this.ResizeRedraw = true;
}
/// <summary>
/// Sets the Zoom to a value where the whole image is visible.
/// </summary>
public void ZoomExtents()
{
if (this.Image == null)
return;
this.initialScale = Math.Min((double)this.Width / this.Image.Width, (double)this.Height / this.Image.Height);
this.Invalidate();
}
/// <summary>
/// Mouse down event handler
/// </summary>
protected override void OnMouseDown(MouseEventArgs e)
{
switch (e.Button)
{
case MouseButtons.Middle:
startingPoint = new Point(e.Location.X - this.Translation.X, e.Location.Y - this.Translation.Y);
break;
}
base.OnMouseDown(e);
}
/// <summary>
/// Mouse move event handler
/// </summary>
protected override void OnMouseMove(MouseEventArgs e)
{
Point mousePosition = Control.MousePosition;
switch (e.Button)
{
case MouseButtons.Middle:
if (this.Bounds.Contains(e.Location))
Translation = new Point(e.Location.X - startingPoint.X, e.Location.Y - startingPoint.Y);
this.Invalidate();
break;
case MouseButtons.Right:
// Add functionality later
break;
}
base.OnMouseMove(e);
}
protected override void OnPaint(PaintEventArgs e)
{
float scale;
float[] translation;
if (this.Image == null)
return;
scale = (float)(this.initialScale * this.ZoomFactor);
translation = new float[] { (float)(this.Translation.X / scale), ((float)this.Translation.Y / scale) };
e.Graphics.Clear(this.BackColor);
e.Graphics.ScaleTransform(scale, scale);
e.Graphics.TranslateTransform(translation[0], translation[1]);
e.Graphics.DrawImage(this.image, new Rectangle(new Point((int)(-this.Width / 2 * scale), (int)(-this.Height / 2 * scale)), new Size(this.image.Width, this.image.Height)));
base.OnPaint(e);
}
}
ホイールを押すと、パンニングが有効になります。ズームは、zoomFactor
変数を設定することによって行われます。最終的にはマウスの右ボタンで実行したいので、メソッドのステートメントに空のcase
ブロックがあります。switch
OnMouseMove