Drawing a rectangle - c#

I am trying to draw a rectangle on top of an image when I hold right click and move the mouse across the image.
At the moment of the mouse click a boolean is changed to true and when the mouse move event occurs and the bool is true, I have the next code:
// currMouselocation - the current mouse location rightClickTrackLocation - the point where the user right clicked
trackRect.Visibility = Visibility.Visible;//making the rectangle visible
var xPos = Math.Min(currMouselocation.X, rightClickTrackLocation.X);
var yPos = Math.Min(currMouselocation.Y, rightClickTrackLocation.Y);
var w = Math.Max(currMouselocation.X, rightClickTrackLocation.X) - xPos;
var h = Math.Max(currMouselocation.Y, rightClickTrackLocation.Y) - yPos;
trackRect.Width = w;
trackRect.Height = h;
Canvas.SetLeft(trackRect, xPos);
Canvas.SetTop(trackRect, yPos);
The problem is that the Rectangle is drawn from the center of the image and not from the clicked point.

Related

How do you set a cursor's position in a different window/application?

I'm trying to set a cursor position to a specific set of coords in a different window, but the mouse never refreshes on that window unless I move the physical mouse I have.
This is for a program that moves the users cursor for them to a specific location IN A DIFFERENT WINDOW, and clicks after a logical expression returns true.
int x = 0;
int y = 0;
Cursor.Position = new Point(x, y);
I want the cursor to actually move inside of a window and not just in form1.
The code will move the cursor to that position but it will not move on the window I am currently on.
Sending RAW Input data to use mouse. Some applications read raw mouse strokes while others read virtual mouse strokes.
int to_x = 500;
int to_y = 300;
int screenWidth = InternalGetSystemMetrics(0);
screenHeight = InternalGetSystemMetrics(1);
// Mickey X coordinate
int mic_x = (int)System.Math.Round(to_x * 65536.0 / screenWidth);
// Mickey Y coordinate
int mic_y = (int)System.Math.Round(to_y * 65536.0 / screenHeight);
// 0x0001 | 0x8000: Move + Absolute position
Mouse_Event(0x0001 | 0x8000, mic_x, mic_y, 0, 0);
// 0x0002: Left button down
Mouse_Event(0x0002, mic_x, mic_y, 0, 0);
// 0x0004: Left button up
Mouse_Event(0x0004, mic_x, mic_y, 0, 0);```
Point cursorPos = Cursor.Position;
cursorPos.X = control.PointToScreen(coordinate).X;
Cursor.Position = cursorPos;

WPF Control disappears when is is animated with DoubleAnimation

I have a TextBox(toAnimate) and an Button(toClick).
When i click the button, the TextBox disappears.
But it should move on the X Position 20 units.
What did i do wrong?
//double left = Canvas.GetLeft(toAnimate); Returned wrong value.
TranslateTransform tanl = new TranslateTransform();
Vector pos = VisualTreeHelper.GetOffset(toAnimate);
double left = pos.X;
toAnimate.RenderTransform = tanl;
DoubleAnimation doua = new DoubleAnimation((left + 20), left, TimeSpan.FromSeconds(3));
tanl.BeginAnimation(TranslateTransform.XProperty, doua);

How to Draw a Rubber Band Selection Rectangle accurately on a Rotated Canvas?

This is a rubber band selection rectangle drawn on a canvas. My problem is that it is easy to get the correct size of the rectangle provided the canvas contents are not rotated. But as soon as it is rotated the rectangle no longer sizes with the cursor. I need the rubber band to stay parallel with screen
var dragPt = new PointF(e.Position.X - G.ReferenceOffset.X, e.Position.Y - G.ReferenceOffset.Y);
var rotation = ADEEnvironment.RotateAngle;
var width = (dragPt.X - pressPt.X);
var height = (dragPt.Y - pressPt.Y);
The code is pretty trivial. I capture the position of the mouse on mouse down: pressPt. In the mouse move event I get the current mouse position dragPt and calculate the width and height of the rubber band rectangle and use those values to create a rectangle with its origin on pressPt.
This works fine if the camera for the canvas is not rotated. When I rotate the display I need the rubber band to stay aligned with the screen and not the canvas it is drawn on. It I just leave it the rubber band is drawn rotated as well.
If I rotate the rubber band rectangle to return it to alignment with the screen then the rectangle is no longer sizing correctly. So after a lot of messing about I tried a bit of trigonometry:
var width = (float)((dragPt.X - pressPt.X) / Math.Cos(rotation));
var height = (float)((dragPt.Y - pressPt.Y) / Math.Cos(rotation));
Which doesn't work and gets very messy given that the rotation angle can be anything for 0 > 360
I have looked at other code on how to create a selection rectangle including the answers to this question: How to make a resizeable rectangle selection tool?
but I would like to use the basic code I have if possible since it is related to the graphics engine I am using (Piccolo).
I would put up some screenshots but I can't capture the rubber band. I think this is more of a math problem than anything else and it ought to be easy to fix but I just can't work out what math calculations to make to account to the effect of rotating the display.
This code uses the Paint event to draw
One fixed rectangle on a rotated canvas
An unrotated copy of it
An unrotated rubber-band
and checks on the corners of example rectanlge
// one example 'object'
Rectangle R0 = new Rectangle(182,82,31,31);
// a few helpers
Point curMouse = Point.Empty;
Point downMouse = Point.Empty;
Rectangle RM = Rectangle.Empty;
float angle = 30;
Point center = new Point(-55, -22);
private void canvas_Paint(object sender, PaintEventArgs e)
{
// preprare the canvas to rotate around a center point:
e.Graphics.TranslateTransform(center.X , center.Y);
e.Graphics.RotateTransform(angle);
e.Graphics.TranslateTransform(-center.X, -center.Y);
// draw one object and reset
e.Graphics.DrawRectangle(Pens.Green, R0);
e.Graphics.ResetTransform();
// for testing (and hittesting): this is the unrotated obejct:
e.Graphics.DrawRectangle(Pens.LightGray, R0);
// allowing for any way the rubber band is drawn..
// ..should be moved to a helper function!
Size S = new Size( Math.Abs(downMouse.X - curMouse.X),
Math.Abs(downMouse.Y - curMouse.Y));
Point P0 = new Point(Math.Min(downMouse.X, curMouse.X),
Math.Min(downMouse.Y, curMouse.Y));
RM = new Rectangle(P0, S);
// the ruber band
e.Graphics.DrawRectangle(Pens.Red, RM);
}
private void canvas_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
curMouse = e.Location;
canvas.Invalidate();
}
private void canvas_MouseDown(object sender, MouseEventArgs e)
{
downMouse = e.Location;
curMouse = e.Location;
}
IMO, the more interesting part will be to decide which objects are selected. Will any intersection count or should it be completely contained?
I found a nice piece of rotation code in this post and add it with an example to check on the fixed Rectangle.
Of course more complex object will call for more involved lists of points. To get really exact results you may even need to go for GraphicsPaths and the set operations on Regions they support; but maybe a simple convex hull will do..
Of course, you will want to store the rotated points instead of reapeatedly calculating them..
static Point RotatePoint(Point pointToRotate, Point centerPoint, double angleInDegrees)
{
double angleInRadians = angleInDegrees * (Math.PI / 180);
double cosTheta = Math.Cos(angleInRadians);
double sinTheta = Math.Sin(angleInRadians);
return new Point
{
X =
(int)
(cosTheta * (pointToRotate.X - centerPoint.X) -
sinTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.X),
Y =
(int)
(sinTheta * (pointToRotate.X - centerPoint.X) +
cosTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.Y)
};
}
private void canvas_MouseUp(object sender, MouseEventArgs e)
{
List<Point> points = new List<Point>();
points.Add(RotatePoint(new Point(R0.Left, R0.Top), center, angle));
points.Add(RotatePoint(new Point(R0.Right, R0.Top), center, angle) );
points.Add(RotatePoint(new Point(R0.Right, R0.Bottom), center, angle) );
points.Add(RotatePoint(new Point(R0.Left, R0.Bottom), center, angle));
bool ok = true;
foreach (Point pt in points) if (!RM.Contains(pt)) ok = false;
if (ok) this.Text = "HIT"; else this.Text = "no hit";
}

Shape not drawing at mouse position on inkcanvas C# WPF

I use the following code to draw a square on an inkcanvas at the position of the mouse. But it doesn't draw the shape at the centre of the mouse position, instead slightly to the right and much lower as demonstrated by the following image:
Additionally I would like to stop the pen from drawing when I click to add a shape to the canvas.
How can I correct the positioning and stop the pen drawing?
private void inkCanvas_MouseMove(object sender, MouseEventArgs e)
{
cursorCoords.Content = Mouse.GetPosition(Application.Current.MainWindow);
// Get the x and y coordinates of the mouse pointer.
System.Windows.Point position = e.GetPosition(this);
pX = position.X;
pY = position.Y;
}
private Stroke NewRectangle(double dTop, double dLeft, double dWidth, double dHeight)
{
double T = dTop;
double L = dLeft;
double W = dWidth;
double H = dHeight;
StylusPointCollection strokePoints = new StylusPointCollection();
strokePoints.Add(new StylusPoint(L, T));
strokePoints.Add(new StylusPoint(L + W, T));
strokePoints.Add(new StylusPoint(L + W, T + H));
strokePoints.Add(new StylusPoint(L, T + H));
strokePoints.Add(new StylusPoint(L, T));
Stroke newStroke = new Stroke(strokePoints);
return newStroke;
}
private void inkCanvas_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (tool == 3) // shape tool
{
switch (chosenShape)
{
case "square":
Stroke oS = NewRectangle(pY, pX, size, size);
DrawingAttributes attribs = new DrawingAttributes();
attribs.Color = shapeColour;//Colors.LimeGreen;
attribs.Height = 5.0;
attribs.Width = 5.0;
attribs.FitToCurve = false;
oS.DrawingAttributes = attribs;
inkCanvas.Strokes.Add(oS);
break;
}
}
}
In your code this refers to window?
// Get the x and y coordinates of the mouse pointer.
System.Windows.Point position = e.GetPosition(this);
If so then position is the cursor position relatively to the window and not to the inkCanvas
Try
System.Windows.Point position = e.GetPosition(inkCanvas);
If you want to stop canvas from drawing when you select a tool you can switch its IsEnabled property.

Selecting part of image on windows form

I'm making instrument to select part of image. I have PictrureBox, and simple way to make it :
void StartPanel(object sender, MouseEventArgs args)
{
xStart = args.X;
yStart = args.Y;
panelStarted = true;
pan.Location = new Point(xStart, yStart);
}
void FinishPanel(object sender, MouseEventArgs args)
{
xFinish = args.X;
yFinish = args.Y;
panelStarted = false;
}
void UpdatePanel(object sender, MouseEventArgs args)
{
if (panelStarted)
{
int x = args.X;
int y = args.Y;
int newxstart = xStart;
int newystart = yStart;
int neww = 0;
int newh = 0;
if (x >= xStart)
neww = x - xStart;
else
{
neww = xStart - x;
newxstart = x;
}
if (y >= yStart)
newh = y - yStart;
else
{
newh = yStart - y;
newystart = y;
}
pan.Size = new Size(neww, newh);
pan.Location = new Point(newxstart, newystart);
}
}
When I move mouse right and down, it is absolutely ok. But when I move it left or up I can see blinks at my area. So I have understood, that it is because when I move mouse left or up, my panel is redrawed, because Panel.Location is changed, and when I move mouse right and down, location is not changed, only size is changed, so it is not redrawed, just some pixels are added to panel. What is standart solution for this?
It's not easy trying to see what you are trying to do, but I guess you are using a panel as a draggable control to drag over the picturebox surface capturing the portion of image below (like a lens) - yes?
If so, then this is not the best way to do it. It is better to just draw a rectangle on the picturebox surface and "drag" that around - this is simple with just using the mouse events to sets the top left corner and use the onpaint to draw the unfilled rectangle over the image. Capturing the image when you are ready is simple too using whatever event you wish, then copy the image giving the same positions to the new bitmap.
Putting one control over another often causes flickers - even with double buffering. It also takes far more code.
Since you are describing a drawing issue when resizing the panel, probably the easiest fix is to replace the panel you are using with one that is double buffered and will invalidate on resize a event:
public class BufferedPanel : Panel {
public BufferedPanel() {
this.DoubleBuffered = true;
this.ResizeRedraw = true;
}
}

Categories

Resources