HighTechTalks DotNet Forums  

Zoom to center of UserControl in C# using GDI+

Dotnet Framework (Drawing) microsoft.public.dotnet.framework.drawing


Discuss Zoom to center of UserControl in C# using GDI+ in the Dotnet Framework (Drawing) forum.



Reply
 
Thread Tools Search this Thread Display Modes
  #11  
Old   
dcopestake@gmail.com
 
Posts: n/a

Default Re: Zoom to center of UserControl in C# using GDI+ - 12-19-2006 , 01:30 PM






I've created the following control & form for people to see what
exactly I'm trying to do.

Here's the code:

--------------------------------LayoutMainControl.cs------------------------------

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace WindowsApplication1
{
public class LayoutMainControl : UserControl
{
private float _ScaleFactor = 1.0F;
private Rectangle DrawingCanvas = new Rectangle ( 0, 0, 1000, 500
);

public float ScaleFactor
{
get
{
return _ScaleFactor;
}

set
{
_ScaleFactor = value;

RescaleDrawingCanvas ( );

Invalidate ( );
}
}

private System.ComponentModel.IContainer components = null;

protected override void Dispose ( bool disposing )
{
if ( disposing && ( components != null ) )
{
components.Dispose ( );
}
base.Dispose ( disposing );
}

#region Component Designer generated code

private void InitializeComponent ( )
{
this.SuspendLayout ( );
this.AutoScaleDimensions = new System.Drawing.SizeF ( 6F, 13F );
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoScroll = true;
this.BackColor = System.Drawing.Color.White;
this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.DoubleBuffered = true;
this.Margin = new System.Windows.Forms.Padding ( 0 );
this.Name = "LayoutMainControl";
this.Size = new System.Drawing.Size ( 692, 409 );
this.Paint += new System.Windows.Forms.PaintEventHandler (
this.LayoutMainControl_Paint );
this.ResumeLayout ( false );

}

#endregion

public LayoutMainControl ( )
{
InitializeComponent ( );
}

private void RescaleDrawingCanvas ( )
{
AutoScrollMinSize = new Size ( ( int ) ( DrawingCanvas.Width *
_ScaleFactor ), ( int ) ( DrawingCanvas.Height * _ScaleFactor ) );
}

private void LayoutMainControl_Paint ( object sender,
PaintEventArgs e )
{
Graphics deviceContext = e.Graphics;

deviceContext.PageUnit = GraphicsUnit.Pixel;
deviceContext.InterpolationMode =
InterpolationMode.HighQualityBicubic;

deviceContext.ScaleTransform ( _ScaleFactor, _ScaleFactor );

deviceContext.TranslateTransform ( AutoScrollPosition.X /
_ScaleFactor, AutoScrollPosition.Y / _ScaleFactor );

Pen pen = new Pen ( Color.Red, 1 );
Rectangle rectangle = new Rectangle ( 500, 250, 10, 10 );
deviceContext.DrawRectangle ( pen, rectangle );
deviceContext.FillRectangle ( new SolidBrush ( pen.Color ),
rectangle );
}
}
}

--------------------------------Form1.cs------------------------------

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication1
{
public partial class Form1 : Form
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main ( )
{
Application.EnableVisualStyles ( );
Application.SetCompatibleTextRenderingDefault ( false );
Application.Run ( new Form1 ( ) );
}

/// <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.layoutMainControl1 = new LayoutMainControl ( );
( ( System.ComponentModel.ISupportInitialize ) ( this.trackBar1 )
).BeginInit ( );
this.SuspendLayout ( );
//
// trackBar1
//
this.trackBar1.Dock = System.Windows.Forms.DockStyle.Bottom;
this.trackBar1.Maximum = 100;
this.trackBar1.Minimum = 1;
this.trackBar1.Name = "trackBar1";
this.trackBar1.TabIndex = 0;
this.trackBar1.Value = 10;
this.trackBar1.ValueChanged += new System.EventHandler (
this.trackBar1_ValueChanged );
//
// layoutMainControl1
//
this.layoutMainControl1.AutoScroll = true;
this.layoutMainControl1.BackColor = System.Drawing.Color.White;
this.layoutMainControl1.BorderStyle =
System.Windows.Forms.BorderStyle.FixedSingle;
this.layoutMainControl1.Dock =
System.Windows.Forms.DockStyle.Fill;
this.layoutMainControl1.Margin = new System.Windows.Forms.Padding
( 0 );
this.layoutMainControl1.Name = "layoutMainControl1";
this.layoutMainControl1.ScaleFactor = 1F;
this.layoutMainControl1.TabIndex = 1;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF ( 6F, 13F );
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size ( 1020, 550 );
this.Controls.Add ( this.layoutMainControl1 );
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 LayoutMainControl layoutMainControl1;

public Form1 ( )
{
InitializeComponent ( );
}

private void trackBar1_ValueChanged ( object sender, EventArgs e )
{
this.layoutMainControl1.ScaleFactor = 0.1F *
this.trackBar1.Value;
}
}
}


Reply With Quote
  #12  
Old   
Michael C
 
Posts: n/a

Default Re: Zoom to center of UserControl in C# using GDI+ - 12-19-2006 , 05:56 PM






<dcopestake (AT) gmail (DOT) com> wrote

Quote:
But (unless I'm misunderstanding things?) the problem isn't to do with
the transformation of the image, it's related to the
AutoScrollPosition?

Surely if I start applying TranslateTransform's to the Graphic the
auto-scroll bars won't be in sync with the location I'm looking at?

As I said before, the only way I can think of doing it is by
calculating the new centered viewport co-ordinates and moving the
AutoScrollPosition to the scaled position once the ScaleTransform and
TranslateTransform have been performed?
In that case I wouldn't use the AutoScroll feature of the control, just
create your own scrollbars.

Michael




Reply With Quote
  #13  
Old   
Bob Powell [MVP]
 
Posts: n/a

Default Re: Zoom to center of UserControl in C# using GDI+ - 12-19-2006 , 06:09 PM



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.t rackBar1)).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.t rackBar1)).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.



<dcopestake (AT) gmail (DOT) com> wrote

Quote:
Hi,

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




Reply With Quote
  #14  
Old   
Michael C
 
Posts: n/a

Default Re: Zoom to center of UserControl in C# using GDI+ - 12-19-2006 , 07:17 PM



"Lloyd Dupont" <net.galador@ld> wrote

Quote:
Try that, this is my own ScrollView....
This doesn't compile. It's missing what I presume is an enum called
Alignment and it is missing a form called DraggingForm

Michael




Reply With Quote
  #15  
Old   
Michael C
 
Posts: n/a

Default Re: Zoom to center of UserControl in C# using GDI+ - 12-19-2006 , 08:04 PM



"Lloyd Dupont" <net.galador@ld> wrote

Quote:
You could remove the dragging code.
But just if you want to keep it, I copy here the DraggingForm.
I also attached the Alignment file
The dragging form is missing some constants but removing all references to
it fixed the problem. What is this control meant to do? Is it a replacement
for the standard scrolling features of controls?

Michael




Reply With Quote
  #16  
Old   
Lloyd Dupont
 
Posts: n/a

Default Re: Zoom to center of UserControl in C# using GDI+ - 12-19-2006 , 10:10 PM



This is a ScrollView which also zoom.
It is ideally suited for subclassing, where you could ovewrite OnPaint() as
follow:
/// protected override void OnPaint(PaintEventArgs e)
/// {
/// // prepare the client space (standart in ScrollView)
/// Matrix m = e.Graphics.Transform;
/// m.Multiply(ClientTransform());
/// e.Graphics.Transform = m;
///
/// // ... normal drawing code ...
/// }



"Michael C" <nospam (AT) nospam (DOT) com> wrote

Quote:
"Lloyd Dupont" <net.galador@ld> wrote in message
news:OPjW728IHHA.1248 (AT) TK2MSFTNGP03 (DOT) phx.gbl...
You could remove the dragging code.
But just if you want to keep it, I copy here the DraggingForm.
I also attached the Alignment file

The dragging form is missing some constants but removing all references to
it fixed the problem. What is this control meant to do? Is it a
replacement for the standard scrolling features of controls?

Michael




Reply With Quote
  #17  
Old   
dcopestake@gmail.com
 
Posts: n/a

Default Re: Zoom to center of UserControl in C# using GDI+ - 12-20-2006 , 05:00 AM



Thank you all very much for your help. Everything is working now!

Cheers
Doug

Lloyd Dupont wrote:
Quote:
This is a ScrollView which also zoom.
It is ideally suited for subclassing, where you could ovewrite OnPaint() as
follow:
/// protected override void OnPaint(PaintEventArgs e)
/// {
/// // prepare the client space (standart in ScrollView)
/// Matrix m = e.Graphics.Transform;
/// m.Multiply(ClientTransform());
/// e.Graphics.Transform = m;
///
/// // ... normal drawing code ...
/// }



"Michael C" <nospam (AT) nospam (DOT) com> wrote in message
news:%23IwzVG9IHHA.4848 (AT) TK2MSFTNGP04 (DOT) phx.gbl...
"Lloyd Dupont" <net.galador@ld> wrote in message
news:OPjW728IHHA.1248 (AT) TK2MSFTNGP03 (DOT) phx.gbl...
You could remove the dragging code.
But just if you want to keep it, I copy here the DraggingForm.
I also attached the Alignment file

The dragging form is missing some constants but removing all references to
it fixed the problem. What is this control meant to do? Is it a
replacement for the standard scrolling features of controls?

Michael



Reply With Quote
  #18  
Old   
Michael C
 
Posts: n/a

Default Re: Zoom to center of UserControl in C# using GDI+ - 12-20-2006 , 06:06 AM



"Lloyd Dupont" <net.galador@ld> wrote

Quote:
This is a ScrollView which also zoom.
It is ideally suited for subclassing, where you could ovewrite OnPaint()
as follow:
/// protected override void OnPaint(PaintEventArgs e)
/// {
/// // prepare the client space (standart in ScrollView)
/// Matrix m = e.Graphics.Transform;
/// m.Multiply(ClientTransform());
/// e.Graphics.Transform = m;
///
/// // ... normal drawing code ...
/// }
I've have a similar control which I use for a few different things. Instead
of having the onpaint event in the control I inherit from so that there is
no need to copy the code each time it is used.

Michael




Reply With Quote
Reply




Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.4
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.