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.
Related
So im trying to get mouse coordinates from a click on an image, and it gives the wrong coordinates. When i move the mouse to draw, the line appears away from the cursor.
This is the code i use to get the mouse coordinates:
private void ponaredek_MouseDown(object sender, MouseButtonEventArgs e)
{
mouseDown = true;
//x1 = System.Windows.Forms.Control.MousePosition;
x1 = new System.Drawing.Point((int)e.GetPosition(this).X, (int)e.GetPosition(this).Y);
}
x1 is of type System.Drawing.Point (i need the point from drawing, to use in emgucv). What do i have to do to correct the cursor location (i drew where the cursor was)
You want to get the mouse position relative to the Image element, not the Window. So replace
e.GetPosition(this)
by
e.GetPosition((IInputElement)sender)
or
e.GetPosition(ponaredek)
if that is the Image element.
It should look like this:
var pos = e.GetPosition((IInputElement)sender);
x1 = new System.Drawing.Point(pos.X, pos.Y);
Also make sure the Image element's Stretch property is set to None.
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);
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.
Actually i am wondering to erase an image to transparency. like i have an image on page background and another image above that. Now i want that if i erase above image by finger then lower image should be appear, simply means to say image will become transparent.i'm doing something like this but its not meet my requirements.
Your suggestions are Welcome :)
private void Canvas_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
currentPoint = e.GetPosition(this.canvas);
//Initialize line according to currentpoint position.
Line line = new Line()
{
X1 = currentPoint.X,
Y1 = currentPoint.Y,
X2 = oldPoint.X,
Y2 =oldPoint.Y
};
line.StrokeDashCap = PenLineCap.Round;
line.StrokeEndLineCap = PenLineCap.Round;
line.StrokeLineJoin = PenLineJoin.Round;
line.StrokeThickness = 20;
line.Stroke = new SolidColorBrush(Colors.Black) ;
////////////////////////////////
//Set color & thickness of line.
//Line add in canvas children to draw image & assign oldpoint.
this.canvas.Children.Add(line);
oldPoint = currentPoint;
}
You can do it with 3 different ways:
Using opaque overlay and UIElement.Clip property. But you need to deal with Geometry. And I'm afraid it will be very CPU cost.
Using WriteableBitmap and changing an alpha channel of image. You can do it using WriteableBitmapEx.
Using opaque overlay and UIElement.OpacityMask property. I think it's the best way to accomplish that, as you're not limited to use bitmap (so you can place any XAML control below overlay) as in the second way.
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.