Annoying because it has different behaviour depending on whether you zoom in
or out.
Once you have the two cases however, the result is pretty simple.....
Here's the user control (with some inelegant dummy drawing :-) )
public partial class zoom2centerControl : UserControl
{
public zoom2centerControl()
{
InitializeComponent();
_docCenter = new Point(this.ClientRectangle.Width / 2,
this.ClientRectangle.Height / 2);
}
Point _docCenter;
float _zoom = 1.0f;
public float Zoom
{
get { return _zoom; }
set {
_zoom = value;
Invalidate();
this.AutoScrollMinSize = new Size(
(int)(this.ClientRectangle.Width * _zoom),
(int)(this.ClientRectangle.Height * _zoom)
);
this.AutoScrollPosition = new Point(
this.AutoScrollMinSize.Width / 2 - this.ClientSize.Width / 2,
this.AutoScrollMinSize.Height / 2 - this.ClientSize.Height / 2
);
}
}
protected override void OnScroll(ScrollEventArgs se)
{
Invalidate();
base.OnScroll(se);
}
protected override void OnPaint(PaintEventArgs e)
{
Matrix mx=new Matrix();
if (_zoom >= 1)
mx = new Matrix(_zoom, 0, 0, _zoom, this.AutoScrollPosition.X,
this.AutoScrollPosition.Y);
else
mx = new Matrix(_zoom, 0, 0, _zoom, this.ClientRectangle.Width / 2 -
(this.ClientRectangle.Width / 2 * _zoom), this.ClientRectangle.Height / 2 -
(this.ClientRectangle.Height / 2 * _zoom));
e.Graphics.Transform = mx;
e.Graphics.DrawLine(Pens.Red, 0, this.ClientRectangle.Height / 2,
this.ClientRectangle.Width, this.ClientRectangle.Height / 2);
e.Graphics.DrawLine(Pens.Red, this.ClientRectangle.Width/2, 0,
this.ClientRectangle.Width/2, this.ClientRectangle.Height);
for (int x = 0; x < 5; x++)
e.Graphics.DrawEllipse(Pens.Blue, ((this.ClientRectangle.Width / 2) - (1 +
(3 * x))), ((this.ClientRectangle.Height / 2) - (1 + (3 * x))), x * 6, x *
6);
}
}
And here's the form the drives it all.....
partial class Form1 : Form
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed;
otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.trackBar1 = new System.Windows.Forms.TrackBar();
this.zoom2centerControl1 = new zoom2centre.zoom2centerControl();
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
this.SuspendLayout();
//
// trackBar1
//
this.trackBar1.Dock = System.Windows.Forms.DockStyle.Top;
this.trackBar1.Location = new System.Drawing.Point(0, 0);
this.trackBar1.Maximum = 20;
this.trackBar1.Minimum = 1;
this.trackBar1.Name = "trackBar1";
this.trackBar1.Size = new System.Drawing.Size(292, 45);
this.trackBar1.TabIndex = 1;
this.trackBar1.Value = 5;
this.trackBar1.ValueChanged += new
System.EventHandler(this.trackBar1_ValueChanged);
//
// zoom2centerControl1
//
this.zoom2centerControl1.AutoScroll = true;
this.zoom2centerControl1.AutoScrollMinSize = new System.Drawing.Size(584,
452);
this.zoom2centerControl1.Dock = System.Windows.Forms.DockStyle.Fill;
this.zoom2centerControl1.Location = new System.Drawing.Point(0, 45);
this.zoom2centerControl1.Name = "zoom2centerControl1";
this.zoom2centerControl1.Size = new System.Drawing.Size(292, 226);
this.zoom2centerControl1.TabIndex = 2;
this.zoom2centerControl1.Zoom = 2F;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(292, 271);
this.Controls.Add(this.zoom2centerControl1);
this.Controls.Add(this.trackBar1);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TrackBar trackBar1;
private zoom2centerControl zoom2centerControl1;
public Form1()
{
InitializeComponent();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
private void trackBar1_ValueChanged(object sender, EventArgs e)
{
if (this.trackBar1.Value > 4)
this.zoom2centerControl1.Zoom = 1 + this.trackBar1.Value - 5;
else
this.zoom2centerControl1.Zoom = 1.0f / (5 - this.trackBar1.Value) * 0.5f;
}
}
--
Bob Powell [MVP]
Visual C#, System.Drawing
Ramuseco Limited .NET consulting
http://www.ramuseco.com
Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm
Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm
All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.
Post by d***@gmail.comHi,
I'm currently trying to write a custom UserControl which (essentially)
is a drawing canvas and allows zooming and panning.
The functionality I'm trying to implement relates to zooming. I've
currently implemented something along the lines of Bob Powell's example
at http://www.bobpowell.net/zoompicbox.htm, however, what I'm trying to
achieve is zooming to the center point of the control, rather than to
the top left hand (i.e. the co-ordinate location).
I can't quite get my head around how to do this cleanly. Can anyone
offer an advice or pointers? The only way I can think of doing it at
the moment, is by manually setting the AutoScrollPosition by
calculating the new position before scaling, and then setting that
position after the scaling. However I'm not sure this is the best way
to achieve what I what?
Kind Regards
Doug