Hello,
I've been trying to solve this for a couple of days now but i just don't get it..
I have a UserControl which acts like an advanced version of the PictureBox. Changing image / panning the image is not problem nor is Zooming really.
The problem I'm having is related to the zooming in/out. When I scroll the mouse-wheel on the image, the image zooms in/out like it should, however, it ignores where the mouse cursor is places, just zooms in on the last know position set by panning the image.. What i want is: A way for the image to zoom in/out based on the mouse coordinates. Like, if i place the mouse at 400, 400 on the image and zoom in, i want the cursor to zoom in on that area (and keep the mouse over 400, 400) Kinda like how Google Maps zooming works.
Here's my UserControl so far:
I've been trying to solve this for a couple of days now but i just don't get it..
I have a UserControl which acts like an advanced version of the PictureBox. Changing image / panning the image is not problem nor is Zooming really.
The problem I'm having is related to the zooming in/out. When I scroll the mouse-wheel on the image, the image zooms in/out like it should, however, it ignores where the mouse cursor is places, just zooms in on the last know position set by panning the image.. What i want is: A way for the image to zoom in/out based on the mouse coordinates. Like, if i place the mouse at 400, 400 on the image and zoom in, i want the cursor to zoom in on that area (and keep the mouse over 400, 400) Kinda like how Google Maps zooming works.
Here's my UserControl so far:
public partial class ZoomablePanel : UserControl
{
[Description("Pan button"), Category("Data"), DefaultValue(MouseButtons.Right), Browsable(true)]
public MouseButtons Pan
{
get { return this.PanButton; }
set { this.PanButton = value; }
}
[Description("Current Zoom Factor"), Category("Data"), DefaultValue(1), Browsable(true)]
public Double Zoom
{
get { return this.ZoomFactor; }
set { this.ZoomFactor = value; }
}
[Description("The Image"), Category("Data"), DefaultValue(null), EditorBrowsable(EditorBrowsableState.Always), Browsable(true)]
public Image BGImage
{
get { return this.initialImage; }
set { this.initialImage = value; }
}
public PointF Origin;
private MouseButtons PanButton = System.Windows.Forms.MouseButtons.Right;
[DefaultValue(1)]
private Double ZoomFactor;
private Image initialImage;
private PointF Start;
private RectangleF DestRect, SrcRect;
public MapPanel()
{
if (this.Origin == null)
this.Origin = new PointF(0, 0);
this.Start = this.Origin;
InitializeComponent();
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
}
protected override void onmousewheel(MouseEventArgs e)
{
base.onmousewheel(e);
int Delta = (e.Delta / 120);
double prevZoom = this.ZoomFactor;
this.ZoomFactor = this.ZoomFactor + (Delta * 0.5);
if (this.ZoomFactor > 5) this.ZoomFactor = 5;
if (this.ZoomFactor < 0.5) this.ZoomFactor = 0.5;
if (prevZoom != this.ZoomFactor)
{
this.Origin.X = e.X;
this.Origin.Y = e.Y;
if (this.Origin.X > initialImage.Width - (ClientSize.Width / this.ZoomFactor))
this.Origin.X = initialImage.Width - (float)(ClientSize.Width / this.ZoomFactor);
if (this.Origin.Y > initialImage.Height - (ClientSize.Height / this.ZoomFactor))
this.Origin.Y = initialImage.Height - (float)(ClientSize.Height / this.ZoomFactor);
if (this.Origin.X < 0) this.Origin.X = 0;
if (this.Origin.Y < 0) this.Origin.Y = 0;
this.Invalidate();
}
}
protected override void onmousedown(MouseEventArgs e)
{
base.onmousedown(e);
if (e.Button == this.PanButton)
{
this.Start.X = e.X;
this.Start.Y = e.Y;
}
}
protected override void onmousemove(MouseEventArgs e)
{
if (e.Button == this.PanButton)
{
float DeltaX = this.Start.X - e.X;
float DeltaY = this.Start.Y - e.Y;
this.Origin.X = this.Origin.X + (float)(DeltaX / this.ZoomFactor);
this.Origin.Y = this.Origin.Y + (float)(DeltaY / this.ZoomFactor);
if (this.Origin.X < 0) this.Origin.X = 0;
if (this.Origin.Y < 0) this.Origin.Y = 0;
if (this.Origin.X > initialImage.Width - (ClientSize.Width / this.ZoomFactor))
this.Origin.X = initialImage.Width - (float)(ClientSize.Width / this.ZoomFactor);
if (this.Origin.Y > initialImage.Height - (ClientSize.Height / this.ZoomFactor))
this.Origin.Y = initialImage.Height - (float)(ClientSize.Height / this.ZoomFactor);
if (this.Origin.X < 0) this.Origin.X = 0;
if (this.Origin.Y < 0) this.Origin.Y = 0;
this.Start.X = e.X;
this.Start.Y = e.Y;
this.Invalidate();
}
base.onmousemove(e);
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
DestRect = new RectangleF(0, 0, ClientSize.Width, ClientSize.Height);
if (initialImage != null && this.Origin != null && this.ZoomFactor > 0)
{
if (this.Origin.X > initialImage.Width - (ClientSize.Width / this.ZoomFactor))
this.Origin.X = initialImage.Width - (float)(ClientSize.Width / this.ZoomFactor);
if (this.Origin.Y > initialImage.Height - (ClientSize.Height / this.ZoomFactor))
this.Origin.Y = initialImage.Height - (float)(ClientSize.Height / this.ZoomFactor);
if (this.Origin.X < 0) this.Origin.X = 0;
if (this.Origin.Y < 0) this.Origin.Y = 0;
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.Clear(this.BackColor);
Graphics g = e.Graphics;
DrawImage(ref g);
}
private void DrawImage(ref Graphics g)
{
if (initialImage == null) return;
SrcRect = new RectangleF(Origin.X, Origin.Y, (float)(ClientSize.Width / ZoomFactor), (float)(ClientSize.Height / ZoomFactor));
g.DrawImage(initialImage, DestRect, SrcRect, GraphicsUnit.Pixel);
}
}