I am attempting to zoom in a picturebox using the mousewheel.
Using the following variables:
public static int offsetX = 0;
public static int offsetY = 0;
public static double scale = .05;
I draw a series of polygons to the picture box. However, I wanted the bottom left corner to refer to 0,, so I draw everything to the form with a -y. The drawn points have been affected by the above variables but the real points stay the same.
void pictureBox1_MouseWheel(object sender, MouseEventArgs e)
{
if (e.Delta > 0)
scale += .025;
else
scale -= .025;
pictureBox1.Invalidate();
}
When the mousewheel is moved forward I increase the scale variable and the box is refreshed. It is repainted using this code in the picturebox paint method:
Graphics g = e.Graphics;
foreach (Member m in activeTruss.members)
{
if (m.Visible == true)
{
Point[] pointArray = new Point[m.poly.Points.Count()];
int index = 0;
foreach (System.Windows.Point p in m.poly.Points)
{
pointArray[index].X = (int)((p.X + offsetX) * scale);
pointArray[index].Y = (int)-((p.Y + offsetY) * scale);
index++;
}
SolidBrush myBrush = new SolidBrush(m.color);
g.FillPolygon(myBrush, pointArray);
}
}
it zooms the correct amount, however it appears to zoom towards the upper left corner because the offsets stay the same. The opposite is true when zooming out. How should I edit the offsets as I turn the mouse wheel in order to zoom directly towards the point under my mouse?
If you want to center your zoom
double offsetX = scale/2
double offsetY = scale/2
Update
To answer your second part about flipped picture, it sounds like you are not making a distinction on the x,y of your picture vs the x,y screen coordinates. Usually, screen coordinates start on the top of the screen, so top left is 0,0, however when you draw your picture, your picture's 0,0 is on the bottom left so you use -y. What you want to do is to start drawing from 0,0 to 0,MAXY without the flip. For this implementation detail, your code would help alot hehe :)
Related
I have a PictureBox inside a Panel, and I have implemented the zoom function with a TrackBar.
When I increase (or decrease) the PictureBox, the position of the image remain fixed on the left side of the PictureBox.
See the example to better understand the problem.
What I want is the possibility to relocate the image compared to the center of the Panel. See the following example
For example I tried to define the PictureBox X origin in this way:
before the zoom I calculate the distance (Δdx) between the origin of the PictureBox (x0) and the center of the Panel (x1).
I increase the distance with the zoom factor (Δdx').
I calculate the new origin of the image (x0') as x1 - Δdx'
I do the same with Y and I define the new PictureBox location with x0' and y0'.
Here the code:
// new image width after the zoom
double width = pbImg.Image.Width + (pbImg.Image.Width * trackbar.Value / 100);
// new image height after the zoom
double height = pbImg.Image.Height + (pbImg.Image.Height * trackbar.Value / 100);
// panel center
int cX = panel.Width / 2;
int cY = panel.Height / 2;
// actual origin for the picturebox
int imgX = pbImg.Location.X;
int imgY = pbImg.Location.Y;
// distance the panel center and the picturebox origin
int distFromXc = cX - imgX;
int distFromYc = cY - imgY;
// new distance with zoom factor
distFromXc = distFromXc + (distFromXc * trackbar.Value / 100);
distFromYc = distFromYc + (distFromYc * trackbar.Value / 100);
// new origin point for the picturebox
int pbX = (cX - distFromXc);
int pbY = (cY - distFromYc);
// new dimension for the picturebox
pbImg.Size = new Size(Convert.ToInt32(width), Convert.ToInt32(height));
// relocate picturebox
Point p = new Point(pbX, pbY);
pbImg.Location = p;
I tried to modify this C# code, but I’m not familiar with it.
In my case I want to manage the Picturebox and the image inside it as the same object (if it’s possible).
What I want is the possibility to increase (or decrease) the Picturebox (and the image inside) but I want the Picturebox to stay centered where it currently is.
The SizeMode of the picture is StretchImage.
The Trackbar has 0% as he minimum value and 100% as the maximum.
The size of the Picturebox, and the image isnside, can be variable, I receive the images from another software.
A zoomed Picturebox can be bigger than Panel, but it’s not a problem, because I can move it.
The problems are the following:
1. If i use the code I wrote above, the reposition seems to work, but the Picturebox isn’t resized.
2. If I use a fixed value for the origin of the Picturebox (for example Point p = new Point(50, 50)), the resize works but obviously the position of the Picturebox is fixed.
This is because you are changing the size of the picturebox and not the size of the image within it. To ensure an image matches the size of the picture box ensure you set the stretchimage sizemode
pbImg.SizeMode = PictureBoxSizeMode.StretchImage
to get it working you could add this line just before you change the size of the picture box, however i recommend setting this on picturebox during its creation.
Refer to : Fit Image into PictureBox
If you want the PictureBox to stay centered where it currently is, and only expand or deflate "in place", then try something like this:
double width = pbImg.Width * trackbar.Value / 100;
double height = pbImg.Height * trackbar.Value / 100;
Rectangle rc = pbImg.Bounds;
rc.Inflate((int)((width - pbImg.Width) / 2), (int)((height - pbImg.Height) / 2));
pbImg.Bounds = rc;
Note that this is all based on the size of the PictureBox itself, NOT the Image within. Not sure what SizeMode you have set for the PB...
---------- EDIT ----------
I'm using StretchImage as SizeMode. Is possible to have the same behavior but without the button? When I move the cursor from left to right the Pb increase and decrease from right to left – Scarj
Of course. Put my code into the ValueChanged() and/or Scroll() events. - Idle_Mind
The original post works off the current size of the PictureBox. You might want to store the original Bounds() of the PB (maybe in the Tag() property) and then always compute the new size based on that instead.
Here's an example of that:
private void Form1_Load(object sender, EventArgs e)
{
pbImg.Tag = pbImg.Bounds;
}
private void button1_Click(object sender, EventArgs e)
{
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
ZoomPB();
}
private void trackBar1_ValueChanged(object sender, EventArgs e)
{
ZoomPB();
}
private void ZoomPB()
{
Rectangle rc = (Rectangle)pbImg.Tag;
double width = rc.Width * trackbar.Value / 100;
double height = rc.Height * trackbar.Value / 100;
rc.Inflate((int)((width - rc.Width) / 2), (int)((height - rc.Height) / 2));
pbImg.Bounds = rc;
}
Can anyone help me on this?
I have a picture box with a image and this image have some coordinates.
My X starts at 60 and end at 135
My Y stats at 75 and end at 120
Because i have only the first and the last point, i want to calculate and see the coordinates when i mouse over my image.
I started with solving my first problem: i have to delimitate my start and my end.
So i tried a trackbar.
Im trying first get the current X position:
Set my picturebox at position x = 0;
Set my trackbar at position x = -10, so my first pin will be at position 0;
Set my tracbar size.x = picturebox.x + 20, so my last pin will be at end of picture box.
My trackbar have the current properties:
Minimum = 60, Maximum = 135;
Set a mouse move event in my picturebox:
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
double dblValue;
dblValue = ((double)e.X/ (double)trackBar1.Width) * (trackBar1.Maximum - trackBar1.Minimum);
dblValue = dblValue + 60;
trackBar1.Value = Convert.ToInt32(dblValue);
lblX.Text = dblValue.ToString();
}
It's almost working, but still not very accurate.
Anyone have some idea that may work?
I'm not exactly sure what it is you are trying to do, but if you are trying to get to the coordinates within the picturebox, there is a function on the pictureBox class called PointToClient(Point) that computes the location of the specified screen point into client coordinates. You can use the X and Y coordinates from the MouseEventArgs to create the Point object to pass to the function.
To clarify:
The X and Y properties of the MouseEventArgs in the MouseMove event are the screen coordinates (0,0) being the upper left corner of the screen.
Many controls like the PictureBox control include a PointToClient method that will convert the screen coordinates to the local control's coordinates, where (0,0) will be the upper left corner of the control.
So, for example, if your control is placed on the screen at location (60, 75) and has a bottom right coordinate of (135, 120). If your mouse is over the control, and is 10 pixels from the left and 20 pixels from the top, then the X and Y properties of the MouseEventArgs in the MouseMove event would be: X = 70 and Y = 95. If you convert these to the internal coordinates of the picturebox control using PointToClient, it will indicate that X = 10 and Y = 20.
Now, if you were wanting to have a TrackBar that displays a relative indication of where the X coordinate of the mouse is over some control, you would calculate it as follows:
// Set the minimum and maximum of the trackbar to 0 and 100 for a simple percentage.
trackBar1.Minimum = 0;
trackBar1.Maximum = 100;
// In the pictureBox1_MouseMove event have the following code:
trackBar1.Value = pictureBox1.PointToClient(new Point(e.X, e.Y)).X * 100 / pictureBox1.Width;
If you wanted to have the trackbar use screen coordinates to track the relative position of the X coordinate of the mouse over some control, you would calculate it as follows:
// Set the minimum and maximum values of the track bar to the screen coordinates of the
// control we want to track.
trackBar1.Minimum = pictureBox1.PointToScreen(0,0).X;
trackBar1.Maximum = pictureBox1.PointToScreen(pictureBox1.Width, 0).X;
// In the pictureBox1_MouseMove event have the following code:
trackBar1.Value = e.X;
If you wanted to have the trackbar use the internal coordinates of some control to track the internal position of the X coordinate of the mouse over that control, you would calculate it as follows:
// Set the minimum and maximum values of the track bar to zero and the width of the
// control we want to track.
trackBar1.Minimum = 0;
trackBar1.Maximum = pictureBox1.Width;
// In the pictureBox1_MouseMove event have the following code:
trackBar1.Value = pictureBox1.PointToClient(new Point(e.X, e.Y)).X;
// or - not recommended - read below.
trackBar1.Value = e.X - pictureBox1.Left;
Now, there is one caveat, and that is if you put controls inside other controls, like a panel inside a panel inside a panel, etc. then the 'world' coordinates of a control inside of another control are based upon their location within the parent control. That is why it is a good idea to use the internal coordinates of the control via PointToClient and screen coordinates from internal coordinates via PointToScreen because otherwise you would have to work your way up through all of the containers until you reached the screen, keeping track of Top and Left coordinates all the way.
I hope this answers your question.
I need to pan an image at a preset Scale level (no zoom). When panning from left to right, I need the left-side of the image to disappear as the leading right edge appears. This would give the image the appearance of a video as the camera pans the scene. What I've done so far:
double origX = 0.0;
double origY = 0.5;
double newx;
double newy;
image1.RenderTransformOrgin = new Point(origX, origY);
image1.RenderTransform = new ScaleTransform(2.0, 2.0);
if (newX == 0.0)
{
image1.RenderTransformOrgin = new Point(origX, origY);
}
else
{
image1.RenderTransformOrgin = new Point(newX, newY);
}
Using this code I am able to start the virtual "camera lens" on the left and then move it to any other point of the image. By manually increasing newX's value incrementally I am able to create the effect I need. My question is how best to increase the newX value to produce a smooth, animated appearance? Thank You.
I'm working on a practice application that adds blue squares to a canvas when you click inside the canvas. One of the requirements is that the shape is added at that point with the mouse representing the center of the new shape.
By default, the click point of the mouse will be the top left of the square. Is there a way to make the square spawn from the center of the mouse click instead of the top right?
This is how i currently add my squares to the canvas:
private void canvasArea_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Shape Rendershape = null;
switch (Shape1)
{
case SelectedShape.Rectangle:
Rendershape = new Rectangle()
{
Fill = Brushes.Blue,
Height = num1,
Width = num2
};
break;
default:
return;
}
Canvas.SetLeft(Rendershape, e.GetPosition(canvasArea).X);
Canvas.SetTop(Rendershape, e.GetPosition(canvasArea).Y);
canvasArea.Children.Add(Rendershape);
}
All you need to do is shift the rectangle by half the rectangle's width and height, see following code:
Canvas.SetLeft(Rendershape, e.GetPosition(canvasArea).X - ( Rendershape.Width / 2.0 ) );
Canvas.SetTop(Rendershape, e.GetPosition(canvasArea).Y - ( Rendershape.Height / 2.0 ) );
How can I know at what pixel of a pictureBox the mouse is placed (coordinates)?
Catch mouse move event:
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
Text = String.Format("X: {0}; Y: {1}", e.X, e.Y);
}
You have X and Y position there.
If your image has been zoomed and/or panned, rememeber you have to apply transformations on those coords.
To be clear: if your image has been placed on (x0,y0) and been zoomed with zf (remember that zf<1 means reduced), pixel coords will be
px = (e.X - x0) / zoom;
py = (e.Y - y0) / zoom;
I think that the question is a little bit vague since you did not tell us what exactly are you planning to do nor what you have effectively tried.
The Control.PointToClient method seems to do what you need:
Computes the location of the specified screen point into client
coordinates.
You can then use the Bitmap.GetPixel and use the X-Y coordinates to get the pixel at the given mouse co-ordinates:
Gets the color of the specified pixel in this Bitmap
All of this can be triggered by a Mouse_Over event, Mouse_Click, etc.
If you determine the color inside a MouseEvent, you can just use the coordinates provided from MouseEventArgs
// Declare a Bitmap
Bitmap mybitmap;
// Load Picturebox image to bitmap
mybitmap = new Bitmap(pictureBox1.Image);
// In the mouse move event
var pixelcolor = mybitmap.GetPixel(e.X, e.Y);
// Displays R / G / B Color
pixelcolor.ToString()
There is a static method on the Mouse class that allows you to get the position of the mouse pointer relative to another element . Look at Mouse.GetPosition(UIElement).
Here's how you use it.
Point point = Mouse.GetPosition(pictureBox);
Debug.WriteLine("X: " + point.X +"\n Y: "+ point.Y);