Reputation: 43
At the moment I develope a ChartControl and it works just pretty well in my opinion, but now I'm at a point where it would be nice to have the ability to zoom the drawed signal for better analyzing.
At the moment I calculate the needed points like this:
for (int i = 0; i < PointsCount; i++){
xAxisPoint = xAxisOP.X + i * (xAxisWidth / PointsCount);
yAxisPoint = yAxisHeight * data[i].Point / Divisor;
if(yAxisPoint > yAxisHeight){
yAxisPoint = yAxisHeight;
}
if(yAxisPoint < -yAxisHeight){
yAxisPoint = -yAxisHeight;
}
Points[i] = new PointF(xAxisPoint, yAxisOP.Y + yAxisPoint);
}
if(zoom){
graphics.ScaleTransform(0.2f*ZoomFactor, 0.2f*ZoomFactor);
}
using (Pen plotPen = new Pen(plotColor, 1)){
graphics.DrawLines(plotPen, Points);
}
But the problem is: When it zooms in, the zoom is way too big and is drawn outside the bounds of my control.
Is there a way to specify an area in which it should be Scaled (zoomed)?
Upvotes: 3
Views: 4550
Reputation: 54433
For the final question: Is there a way to specify an area in which it should be scaled/zoomed? you need a combination of SetClip
, TranslateTransform
and ScaleTransform
.
Here is an example.
It uses a
zoomTgtArea
where the zoomed graphics are displayed,zoomOrigin
where the zoom origin is,zoomFactor
, a positive float
.Initial values:
Rectangle zoomTgtArea = new Rectangle(300, 500, 200, 200);
Point zoomOrigin = Point.Empty; // updated in MouseMove when button is pressed
float zoomFactor = 2f;
The trick to zoom in on only a part of the graphics is to display the graphics twice, once normally and once with the transformations of the Graphics
object.
Let's try:
private void pictureBox_Paint(object sender, PaintEventArgs e)
{
// normal drawing
DrawStuff(e.Graphics);
// for the movable zoom we want a small correction
Rectangle cr = pictureBox.ClientRectangle;
float pcw = cr.Width / (cr.Width - ZoomTgtArea.Width / 2f) ;
float pch = cr.Height / (cr.Height - ZoomTgtArea.Height / 2f) ;
// now we prepare the graphics object; note: order matters!
e.Graphics.SetClip(zoomTgtArea );
// we can either follow the mouse or keep the output area fixed:
if (cbx_fixed.Checked)
e.Graphics.TranslateTransform( ZoomTgtArea.X - zoomCenter.X * zoomFactor,
ZoomTgtArea.Y - zoomCenter.Y * zoomFactor);
else
e.Graphics.TranslateTransform( - zoomCenter.X * zoomFactor * pcw,
- zoomCenter.Y * zoomFactor * pch);
// finally zoom
e.Graphics.ScaleTransform(zoomFactor, zoomFactor);
// and display zoomed
DrawStuff(e.Graphics);
}
The DrawStuff
I used is simple:
void DrawStuff(Graphics g)
{
bool isZoomed = g.Transform.Elements[0]!= 1
|| g.Transform.OffsetX != 0 | g.Transform.OffsetY != 0;
if (isZoomed) g.Clear(Color.Gainsboro); // pick your back color
// all your drawing here!
Rectangle r = new Rectangle(10, 10, 500, 800); // some size
using (Font f = new Font("Tahoma", 11f))
g.DrawString(text, f, Brushes.DarkSlateBlue, r);
}
Its only extra is clearing the background so the normal drawing won't shine through the zoomed version..
Let's see:
Upvotes: 4