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.
Related
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?
I wrote a little Program that should display a Ellipse at the exact mouse position. The Problem is that, the way Iam doing it right now , The Mouse and Ellipse Position are only exact at the center of the Screen. If I put the mouse further away to the windowborder they drift further and further away.
I use the MouseOver Element to Update the Mouse Position.
Here is my code:
private void Window_MouseMove(object sender, MouseEventArgs e)
{
Main_Grid.Children.Clear();
MousePos_Ellipse = new Ellipse();
Point MousePos_Point = new Point();
MousePos_Point = Mouse.GetPosition(Main_Grid);
Main_Grid.Children.Remove(MousePos_Ellipse);
SolidColorBrush mySolidColorBrush = new SolidColorBrush();
mySolidColorBrush.Color = Color.FromArgb(55, 255, 255, 0);
MousePos_Ellipse.Fill = mySolidColorBrush;
MousePos_Ellipse.StrokeThickness = 2;
MousePos_Ellipse.Stroke = Brushes.Black;
// Set the width and height of the Ellipse.
MousePos_Ellipse.Width = 15;
MousePos_Ellipse.Height = 15;
// At this Point I do my Positioning
MousePos_Ellipse.Margin = new Thickness(left: MousePos_Point.X - ( Main_Grid.ActualWidth / 2) , top: MousePos_Point.Y - ( Main_Grid.ActualHeight / 2 ), right: 0 , bottom: 0);
//base.AddVisualChild(_circle);
// Add the Ellipse to the Grid
Main_Grid.Children.Add(MousePos_Ellipse);
}
I propose to use a Canvas instead of a grid.
With a canvas you can simply set the ellipse position like that:
Canvas.SetLeft(MousePos_Ellipse, MousePos_Point.X);
Canvas.SetTop(MousePos_Ellipse, MousePos_Point.Y);
The Grid control will do automatic positioning and sizing of child elements and is therefore not so suitable for your goal.
Disclaimer; while the answers above will fix your issue, the actual question is not properly resolved. The problem you are facing derives from your interpretation of the issue compared to how the computer sees it.
The position of your cursor relative to the grid is not the same as the position relative to your screen (i.e. different resolutions return different values). This is why our x and y values will be further off the further you get off center. You could fix this by defining that you want your X and Y position relative to the form, f.ex, like so:
var relativePoint = this.PointToClient(Cursor.Position);
The noticable difference here is that here, we Point to the client, and therefore get the Cursor's relative position within the form.
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 searched a lot to find a solution for my problem. Couldn't find anything.
This is what I do:
I render a polygon via point array on a grid. The polygon autoresizing itself to match the grids size(uniform). I get the new stretched coordinates with the following lines and create the ellipses with a method:
var transform = myPolygon.RenderedGeometry.Transform;
foreach (var point in myPolygon.Points)
{
var transformedPoint = transform.Transform(point);
CreateEllipse(5, 5, Convert.ToDouble(Convert.ToString(transformedPoint).Split(';')[0]), Convert.ToDouble(Convert.ToString(transformedPoint).Split(';')[1]), gridPoly);
}
Ellipse CreateEllipse(double width, double height, double desiredCenterX, double desiredCenterY, Grid grid)
{
Ellipse ellipse = new Ellipse { Width = width, Height = height };
double left = desiredCenterX - (width / 2);
double top = desiredCenterY - (height / 2);
ellipse.Stroke = System.Windows.Media.Brushes.Black;
ellipse.Fill = System.Windows.Media.Brushes.DarkBlue;
ellipse.Margin = new Thickness(left, top, 0, 0);
grid.Children.Add(ellipse);
return ellipse;
}
The problem is, if I put the polygon on a grid and the ellipses afterwards, they will render exact the half size and not at the correct position, not even relative. Same happens if I set stretch to 'none'.
If I render my polygon and ellipses on a canvas, they render exact on each polygon point and everything is perfect. Beside, canvas doesn't support stretch.Uniform. And I need to dynamically fit the polygon into its parent object.
My question is, how do I render ellipses on an auto resizing polygon using the point positiondata?
You have to take two more things into account.
First, the Grid may align (i.e. move) the whole stretched Polygon according to its HorizontalAlignment and VerticalAlignment properties. If you don't want to calculate that by yourself, you could get an appropriate GeneralTransform object by myPolygon.TransformToAncestor(grid):
var polygonGeometryTransform = myPolygon.RenderedGeometry.Transform;
var polygonToGridTransform = myPolygon.TransformToAncestor(gridPoly);
foreach (var point in myPolygon.Points)
{
var transformedPoint = polygonToGridTransform.Transform(
polygonGeometryTransform.Transform(point));
CreateEllipse(5, 5, transformedPoint.X, transformedPoint.Y, gridPoly);
}
Second, when you do an absolute positioning of the Ellipses relative to the upper left corner of the Grid, you would have to set their HorizontalAlignment to Left and the VerticalAlignment to Top:
ellipse.HorizontalAlignment = HorizontalAlignment.Left;
ellipse.VerticalAlignment = VerticalAlignment.Top;
grid.Children.Add(ellipse);
That said, you wouldn't typically set an element's Margin for absolute positioning. It would be much cleaner to use a separate Canvas for the Ellipses and set their Canvas.Left and Canvas.Top properties.
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.