I have a WinForms picturebox with the Picture Size Mode set to StretchImage. I need the picturebox to zoom in by 1% every two milliseconds which will use a loop.
The pictureBox must zoom in at the center and scrollbars should not be shown.
This is my current code that doesn't work:
while (Visible) {
pictureBox1.Width = pictureBox1.Width + 1;
pictureBox1.Height = pictureBox1.Height + 1;
Application.DoEvents();
System.Threading.Thread.Sleep(2);
}
In this code, there is a window, but the image does not move in any way.
How should this problem be implemented?
Related
I've seen few questions about this problem, I tried every solution but none of them worked for my case.
My code is working; this image shows what happens when I click on Draw button.
I need to zoom on that drawing.Is it possible to code something like autocad feature "zoom/extent"?
Pen myPen = new Pen(Color.Black);
int centerpointx, centerpointy;
private void pictureBoxDraw_Paint(object sender, PaintEventArgs e)
{
centerpointx = pictureBoxDraw.Size.Width/2;
centerpointy = pictureBoxDraw.Size.Height/2;
myPen.Width = 2;
if (binary > 0)
{
var sizecrestgeo = 40;
var distancearraycrestgeo = new float[sizecrestgeo];
var elevationarraycrestgeo = new float[sizecrestgeo];
for (int i = 0; i < sizecrestgeo; i++)
{
distancearraycrestgeo[i] = float.Parse(dataGridViewCrestGeo.Rows[i].Cells[0].Value.ToString());
elevationarraycrestgeo[i] = float.Parse(dataGridViewCrestGeo.Rows[i].Cells[1].Value.ToString())*-1;
}
for (int i=0; i < sizecrestgeo-1; i++)
{
e.Graphics.DrawLine(myPen, distancearraycrestgeo[i]+centerpointx, elevationarraycrestgeo[i]+centerpointy, distancearraycrestgeo[i + 1]+centerpointx, elevationarraycrestgeo[i + 1]+centerpointy);
}
}
else
{
}
}
private void buttonDraw_Click_1(object sender, EventArgs e)
{
if (Hd > 0.0001)
{
binary = 1;
pictureBoxDraw.Invalidate();
}
else
{
MessageBox.Show("No data to draw, perform analysis first.");
}
}
private void buttoncleardraw_Click(object sender, EventArgs e)
{
binary = 0;
pictureBoxDraw.Invalidate();
}
}
This is not so hard, provided you know all the puzzle pieces.
Let's start with the obvious one:
You can scale the Graphics object to create zoomed graphics with ScaleTransform.
As I mentioned, this will include the widths of pens, font sizes and also any images you draw (though not the hatches of a HatchBrush).
You also asked about keeping the drawing 'centered'. This is a non-obvious concept: Just what is the center of your drawing surface??
When zooming (just like rotating) you always need to know the center point of the zoom (or the rotation.) By default this is the origin (0,0). I chose the center of the Panel. You may want to pick some other point..
Once you do you can move the origin of the graphics viewport to this point with TranslateTransform.
Once you have achieved all this you almost certainly will want to allow scrolling.
To do so you have two options:
You can keep AutoScroll = false and nest the canvas control inside another control, usually a Panel, which has AutoScroll = true; next make the canvas control big enough to always hold your drawing and you're done.
Or you can turn on AutoScroll for the canvas control and also set a large enough AutoScrollMinSize. If you then add the current scrolling position to the translation you are also done. Let's see this solution in action:
This is the code in the Paint event:
Size sz = panel3.ClientSize;
Point center = new Point(sz.Width / 2, sz.Height / 2);
Graphics g = e.Graphics;
// center point for testing only!
g.DrawEllipse(Pens.Orange, center.X - 3, center.Y - 3, 6, 6);
// you determine the value of the zooming!
float zoom = (trackBar1.Value+1) / 3f;
// move the scrolled center to the origon
g.TranslateTransform(center.X + panel3.AutoScrollPosition.X,
center.Y + panel3.AutoScrollPosition.Y);
// scale the graphics
g.ScaleTransform(zoom, zoom);
// draw some stuff..
using(Pen pen = new Pen(Color.Yellow, 0.1f))
for (int i = -100; i < 100; i+= 10)
g.DrawEllipse(Pens.Yellow, i-22,i-22,44,44);
A few notes:
I draw an orange circle in the center to show this point is invariant.
My coordinates go from the negative to the positive so you can see that this works nicely.
I draw with a tiny pen width; so the width of the drawing only changes once the resulting pen goes over 1 pixel. Anything draw will always be draw with 1 pxiel width, though.
I first translate and then scale so I don't have to calculate scaled poitions.
The only line in the TrackBar's Scroll event is to trigger the Paint event: panel3.Invalidate();
The only settings needed for the Panel are
panel3.AutoScroll = true;
panel3.AutoScrollMinSize = new Size(500, 500); // use the size you want to allow!
However to avoid flicker it is highly recommended to use a DoubleBuffered control, maybe a Panel subclass like this:
class DrawPanel : Panel
{
public DrawPanel() { DoubleBuffered = true; }
}
Update: Instead of a Panel, which is a Container control and not really meant to draw onto you can use a Picturebox or a Label (with Autosize=false); both have the DoubleBuffered property turned on out of the box and support drawing better than Panels do.
Graphics.ScaleTransform() is how you can zoom. Try using something like this inside your paint event handler:
e.Graphics.ScaleTransform(2.0F, 2.0F);
We are implementing a picture viewer with zoom in based on center of the image with scroll options.
We have used Forms.Panel with a picture box control for displaying the image and auto scroll set to true.
In order to implement zoom we are using inflate function but this will redraw the image to top left:
To bring it to center we are setting the scroll position to center using the following code:
Rectangle rc = this.Panel_PicBox.ClientRectangle;
Point ScrollPosition = this.Panel_PicBox.AutoScrollPosition;
int height = (int)(PictureBox_png.Height);
int width = (int)(PictureBox_png.Width);
if (rc.Width < width)
ScrollPosition.X = (width - rc.Width) >> 1;
if (rc.Height < height)
ScrollPosition.Y = (height - rc.Height) >> 1;
Point p = new Point(ScrollPosition.X,ScrollPosition.Y);
this.Panel_PicBox.AutoScrollPosition = p;
The code works perfectly for bringing the image to center, only problem is we see a lot of flickering when the scroll position is set.
We have tried double buffer method to reduce flickering but didnt work. Please suggest if there is any other method to reduce flickering.
I have a panel called "canvas". It is transparent. So the background is from the form image, which is dark blue. This shows in the panel or canvas.
When I save the canvas to image, it saves the background, but not what I have drawn thereon, my drawline pen is yellow. And I can see it drawing on the panel. But when I save it... there are not yellow lines in the image.
What am I missing? Where are my yellow lines?
I am running this with my timer tick... to get the view to update.
This tracks the position of a CNC type machine. Gives a visual of where
the machine is in relation to Zero.
My ultimate goal, is to have a "viewport" that is zoomable, thus getting it
into a image, for easy resizing, and displaying in a pictureBox, which will
handle the stretched image and center it automatically?
I have read some complex solutions, but I am after the simple ones.
Any help would be appreciated. Sincerely,
private void VMoveNow()//Draw on panel called "canvas".
{
double a = GV.MYa * -1; //Change Direction of Y Drawing.
xc = Convert.ToInt32(GV.MXa) + (canvas.Width / 2);
yc = Convert.ToInt32(a) + (canvas.Height / 2);
g = canvas.CreateGraphics();
g.DrawLine(p, x, y, xc, yc);
x = xc;
y = yc;
g.Dispose();
}
private void SaveBMP()
{
try
{
Bitmap mybmp = new Bitmap(canvas.Width, canvas.Height);
canvas.DrawToBitmap(mybmp, canvas.Bounds);
mybmp.Save("C:\\myimage.bmp");
}
catch
{
return;
}
}
Thanks for looking.
I answered my own problem, after several attempts... I have figured out that I can scale my var's used for this drawings... and the size of the Drawline will be scale as a result.
So I now have scaling of the Drawline drawing, in a panel, with no picture or picture box needed. Does what I wished.
Setting the Pen width to -1 takes care of it resizing.
My form1 size is 800,600
Then i have two panels in the form1 designer:
Panel1 is at location: 0,24 size: 200,437
Panel2 is at location: 584,24 size: 200,437
The result is two panels at each side of the form.
Now i did in my program when you put the mouse somewhere in the form1 area its showing a pictureBox i create in the form1 constructor:
pb = new AnimatedPictureBox.AnimatedPictureBoxs();
pb.Visible = false;
pb.Size = new Size(500, 350);
pb.Location = new Point((ClientSize.Width - pb.Width) / 2,
(ClientSize.Height - pb.Height) / 2);
The problem is that the new pictureBox variable pb is not in the size that will fill all the area between the two panels.
I want the size of the pictureBox to fill almost all the space between the two panels Width and Height maybe to leave some space like 5 spaces each side so there will be a border.
How can i calculate what the pictureBox size should be ?
EDIT**
This is an image where the program is working regular. On each panel on the left and right i added 4 pictureBoxes.
When i move my mouse cursor inside one of the pictureBoxes area its showing its content in a larger pictureBox in the middle.
And this is how it looks like when i put the mouse cursor in one of the pictureBoxes area the pictureBox in the middle is not big enough its Width and Height dosent make the big pictureBox to be excatly between the two panels. The big pictureBox not high and not wide enough.
if you want to make your layout stable even after resizing you should use Dock property for your panels and set Anchor for your picture box. Like that:
panel1.Dock = DockStyle.Left;
panel2.Dock = DockStyle.Right;
pb.Anchor = AnchorStyles.Left | AnchorStyles.Right;
And in general to place it in the center you can use something like that:
var width = this.Width - panel1.Width - panel1.Margin.Horizontal
- panel2.Width - panel2.Margin.Horizontal;
pb.Size = new Size(width, 300); // put your needed height here
pb.Top = this.Height/2 - pb.Height/ 2;
pb.Left = panel2.Left + panel2.Width + panel2.Margin.Right;
I'm creating a simple drawing application using WPF. I've run into some strange behaviour when using the mouse_up event on a canvas control.
The effect I want is that when the user clicks on the canvas and then drags the mouse, the chosen shape grows. When the user releases the mouse button then the shape stays as it is. I have it working fine with an ellipse, as such:
//Calculate width and height based on difference from start and current mouse positions
int width = currentXPosition < StartXPosition ? StartXPosition - currentXPosition : currentXPosition - StartXPosition;
int height = currentYPosition < StartYPosition ? StartYPosition - currentYPosition : currentYPosition - StartYPosition;
StandardEllipse ellipse = new StandardEllipse
{
Fill = new SolidColorBrush(Colors.Blue),
Stroke = new SolidColorBrush(Colors.Blue),
StrokeThickness = 2,
Width = width,
Height = height
};
//Calculate and set the starting positions of the ellipse for the drawing canvas
int left = currentXPosition < StartXPosition ? currentXPosition : StartXPosition;
int top = currentYPosition < StartYPosition ? currentYPosition : StartYPosition;
Canvas.SetLeft(ellipse, left);
Canvas.SetTop(ellipse, top);
return ellipse;
However, when I try with a rectangle, using exactly the same code above, apart from setting the shape to rectangle, the mouse up event fires sporadically, I have to click the mouse button a number of times until it fires the event.
I'm not sure if there is a conflict between the mouse_move and mouse_up events somehow, but I can't see how as all other code is exactly the same apart from returning a rectangle instead of an ellipse Anybody any ideas?
Edit: I thought it may be the fact that when I am drawing the rectangle, the mouse is strictly over the very edge of the shape, so I tried setting the width and height to 99% and it seems to work okay now! If anybody has any insight, then I would be grateful.
On an elipse, the drag corner is outside the bounds of the shape, on a rectangle the drag corner is within the bounds of the shape. It may be that the mouse event is not being routed correctly to the canvas.