Resize and move a drawn rectangle in win forms - c#

I am trying to move and resize a drawn rectangle using mouse events, the new starting location of x, y is calculated but the rectangle position doesn't update:
My form source code:
public partial class Form3 : Form
{
Rectangle rect;
Point StartXY;
Point EndXY;
int x = 0;
int y = 0;
int height = 0;
int width = 0;
bool m_mouseDown = false;
bool m_movingRect = false;
Pen rectPen = new Pen(Color.Red, 1);
public Form3()
{
InitializeComponent();
this.DoubleBuffered = true;
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Graphics gObj = e.Graphics;
rect = new Rectangle(x, y, height, width);
rectPen.DashStyle = DashStyle.Dash;
gObj.DrawRectangle(rectPen, rect);
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
m_mouseDown = true;
// Moving rectangle
if (rect.Contains(e.Location))
{
m_movingRect = true;
Console.WriteLine("m_mouseDown");
}
StartXY = e.Location;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (rect.Contains(e.Location))
this.Cursor = Cursors.SizeAll;
else
this.Cursor = Cursors.Default;
if (m_mouseDown && rect.Contains(e.Location))
{
rect.X += e.X - StartXY.X; // <---- it is calculated correctly but doesn't update rectangle position
rect.Y += e.Y - StartXY.Y;
StartXY = e.Location;
Console.WriteLine("pictureBox1_MouseMove StartXY " + StartXY.X);
Console.WriteLine("pictureBox1_MouseMove StartXY " + StartXY.Y);
Console.WriteLine("pictureBox1_MouseMove rect " + rect.X);
Console.WriteLine("pictureBox1_MouseMove rect " + rect.Y);
}
if (m_mouseDown && !rect.Contains(e.Location))
{
EndXY = e.Location;
x = Math.Min(StartXY.X, EndXY.X);
y = Math.Min(StartXY.Y, EndXY.Y);
height = Math.Abs(StartXY.X - EndXY.X);
width = Math.Abs(StartXY.Y - EndXY.Y);
//Console.WriteLine("pictureBox1_MouseMove XXXX: " + " --- " + e.X.ToString());
//Console.WriteLine("pictureBox1_MouseMove YYYY: " + " --- " + e.Y.ToString());
}
Invalidate(true);
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (!m_movingRect)
{
EndXY = e.Location;
}
m_mouseDown = false;
m_movingRect = false;
Invalidate();
}
}

Related

Resize Line by mouse

I'm drawing a line on a Form and when it finished will be draw a rectangle on line. I need to resize the line after clicking on the rectangle. Any way to do that?
This before:
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawLine(Pens.Red, start.X, start.Y, end.X, end.Y);
if (isMouse == false )
{
rect1.X = start.X - 5;
rect1.Y = start.Y - 5;
rect1.Width = 10;
rect1.Height = 10;
rect2.X = end.X - 5;
rect2.Y = end.Y - 5;
rect2.Width = 10;
rect2.Height = 10;
e.Graphics.DrawRectangle(Pens.Blue, rect1.X, rect1.Y,rect1.Width, rect1.Height);
e.Graphics.DrawRectangle(Pens.Blue, rect2.X, rect2.Y, rect2.Width, rect2.Height);
}
base.OnPaint(e);
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (start.X == 0 && start.Y == 0)
{
isMouse = true;
start = e.Location;
}
else {
resize = true;
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (isMouse == true) {
end = e.Location;
}
if (rect1.Contains(e.Location)&&resize ) {
start = e.Location;
}
else if (rect2.Contains(e.Location)&&resize) {
end = e.Location;
}
Refresh();
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (isMouse == true)
{
end = e.Location;
isMouse = false;
}
}
This will be after:

MouseKeyHook c# path of relocation of a mouse

How to receive a path of relocation of a mouse between the 1st clicking and the 2nd?
private void OnMouseDown(object sender, MouseEventArgs e)
{
Log(string.Format("MouseDown \t\t {0}\n", e.Button));
LogMousePosition(string.Format("\n\nx={0:0000}\ny={1:0000}", e.X, e.Y));
if (lastX != -100 && lastY != -100)
{
shortestDistanse = Convert.ToInt64(Math.Sqrt((Math.Pow(e.X - lastX, 2)) + (Math.Pow(e.Y - lastY, 2))));
LogMousePosition(string.Format("\nshortDistanse\t\t {0}\n", shortestDistanse));
}
lastX = e.X;
lastY = e.Y;
}
If you just want the distance between the two points use pythagora.
Example:
private double GetDistance(Point p1, Point p2) {
int x = Math.Abs(p1.X - p2.X);
int y = Math.Abs(p1.Y - p2.Y);
return Math.Sqrt( Math.Pow(x, 2) + Math.Pow(y, 2));
}
You may try something like
// form fields
bool pressed;
List<Point> path;
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (!pressed)
{
pressed = true;
path = new List<Point>();
path.Add(e.Location);
}
else
{
pressed = false;
// calculate distance from List
// log distance
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (pressed)
{
path.Add(e.Location);
}
}
However, the MouseMove event will be triggered only above the form. If the mouse is outside of it - distance is not taken into account. It also doesn't work when moving over other controls, but we can add to them MouseMove handlers too.
I could make
string pathMList = "C:\\logs/testMList.txt";`
private void HookManager_MouseMove(object sender, MouseEventArgs e)
{
labelMousePosition.Text = string.Format("x={0:0000}; y={1:0000}", e.X, e.Y);
if (mouseDownMove == 2)
{
LogMList(string.Format("\nx={0:0000} y={1:0000}", e.X, e.Y));
}
}
private void OnMouseDown(object sender, MouseEventArgs e)
{
Log(string.Format("MouseDown \t\t {0}\n", e.Button));
LogMousePosition(string.Format("\n\nx={0:0000}\ny={1:0000}", e.X, e.Y));
if (lastX != -100 && lastY != -100)
{
shortestDistanse = Convert.ToInt64(Math.Sqrt((Math.Pow(e.X - lastX, 2)) + (Math.Pow(e.Y - lastY, 2))));
LogMousePosition(string.Format("\nshortDistanse\t\t {0}\n", shortestDistanse));
LogMList(string.Format("\n\n NEW CLICK\n\nx={0:0000} y={1:0000}", e.X, e.Y));
}
lastX = e.X;
lastY = e.Y;
mouseDownMove = 2;
}

How can i cut drawn rectangle and display it in a pictureBox according to button click event?

What i want is that if i drawed a rectangle on one of the items in the pictureBox next time i click the button it will display those items when i click on them in the listBox only the rectangles i drawed.
This is what i tried so far:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using DannyGeneral;
using System.Diagnostics;
namespace MinimizeCapture
{
public partial class Form1 : Form
{
Point p1 = new Point(0, 0);
Rectangle recttest;
private Rectangle Rect;
private Rectangle[] rectangles;
private Rectangle RectClone;
private bool btn = false;
private Point RectStartPoint = Point.Empty;
private Point RectEndPoint = Point.Empty;
private Brush selectionBrush = new SolidBrush(Color.Red);
private Pen pen;
private string selectedIndex;
private List<string> drawnItems = new List<string>();
private bool ClearGraphics;
public Form1()
{
InitializeComponent();
var windows = OpenWindowGetter.FindWindowsWithText();
ClearGraphics = false;
this.DoubleBuffered = true;
btn = false;
pen = new Pen(selectionBrush);
buttonSnap.Enabled = false;
backgroundWorker1.RunWorkerAsync();
}
private void buttonSnap_Click(object sender, EventArgs e)
{
ClearGraphics = true;
this.listBoxSnap.Items.Clear();
this.pictureBoxSnap.Image = null;
backgroundWorker1.RunWorkerAsync();
}
private void CutRectangle()
{
for (int i = 0; i < rectangles.Length; i++)
{
if (!rectangles[i].IsEmpty)
{
}
}
}
private void listBoxSnap_SelectedIndexChanged(object sender, EventArgs e)
{
WindowSnap snap = this.listBoxSnap.SelectedItem as WindowSnap;
selectedIndex = this.listBoxSnap.SelectedIndex.ToString();
this.pictureBoxSnap.Image = snap.Image;
for (int i = 0; i < rectangles.Length; i++)
{
if (rectangles[i] != RectClone)
{
ClearGraphics = false;
}
else
{
ClearGraphics = true;
}
}
}
private void checkBoxForceMDI_CheckedChanged(object sender, EventArgs e)
{
WindowSnap.ForceMDICapturing = (sender as CheckBox).Checked;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
listBoxSnap.Invoke(new MethodInvoker(delegate { this.listBoxSnap.Items.Add("Minimized Windows"); }));
listBoxSnap.Invoke(new MethodInvoker(delegate { this.listBoxSnap.Items.AddRange(WindowSnap.GetAllWindows(true,true).ToArray()); }));
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
rectangles = new Rectangle[listBoxSnap.Items.Count];
buttonSnap.Enabled = true;
}
private void pictureBoxSnap_Paint(object sender, PaintEventArgs e)
{
if (pictureBoxSnap.Image != null)
{
{
if (ClearGraphics == false)
{
if (rectangles[listBoxSnap.SelectedIndex] != Rectangle.Empty)
{
e.Graphics.DrawRectangle(Pens.Firebrick, rectangles[listBoxSnap.SelectedIndex]);
}
if (recttest.Width > 10 && recttest.Height > 10)
e.Graphics.DrawRectangle(Pens.Firebrick, recttest);
}
}
}
}
private void pictureBoxSnap_MouseMove(object sender, MouseEventArgs e)
{
if (btn == true)
{
ClearGraphics = false;
RectEndPoint = e.Location;
int currentindex = listBoxSnap.SelectedIndex;
rectangles[currentindex] = RectClone;
Rect = getRect(RectStartPoint, RectEndPoint);
RectClone = Rect;
pictureBoxSnap.Invalidate();
}
}
private void pictureBoxSnap_MouseDown(object sender, MouseEventArgs e)
{
RectStartPoint = e.Location;
btn = true;
Rect = Rectangle.Empty;
RectClone = Rectangle.Empty;
p1 = e.Location;
}
private void pictureBoxSnap_MouseUp(object sender, MouseEventArgs e)
{
recttest = rectangles[listBoxSnap.SelectedIndex];
ClearGraphics = false;
btn = false;
RectEndPoint = e.Location;
pictureBoxSnap.Invalidate();
int currentindex = listBoxSnap.SelectedIndex;
rectangles[currentindex] = RectClone;
if (e.Location.X > p1.X)
{
recttest.X = p1.X;
recttest.Width = e.Location.X - p1.X;
}
else
{
recttest.X = e.Location.X;
recttest.Width = p1.X - e.Location.X;
}
//Top and Height
if (e.Location.Y > p1.Y)
{
recttest.Y = p1.Y;
recttest.Height = e.Location.Y - p1.Y;
}
else
{
recttest.Y = e.Location.Y;
recttest.Height = p1.Y - e.Location.Y;
}
if (recttest.Width > 10 && recttest.Height > 10)
pictureBoxSnap.Invalidate();
}
Rectangle getRect(Point p1, Point p2)
{
Point p = new Point(Math.Min(p1.X, p2.X), Math.Min(p1.Y, p2.Y));
Size s = new Size(Math.Abs(p1.X - p2.X), Math.Abs(p1.Y - p2.Y));
return new Rectangle(p, s);
}
private void ConfirmRectangle_Click(object sender, EventArgs e)
{
ConfirmRectangle.ForeColor = Color.Red;
ConfirmRectangle.Enabled = false;
StreamWriter w = new StreamWriter(#"c:\temp\Settings.txt", true);
w.WriteLine("Rectangle Location: " + RectClone.Location + " Rectangle Size: " + RectClone.Size + " Selected Index: " + selectedIndex);
textBoxIndex.Text = selectedIndex.ToString();
w.Close();
pictureBoxSnap.Image = CropImage();
}
private Bitmap CropImage()
{
Bitmap pic = pictureBoxSnap.Image as Bitmap;
Bitmap cropped = new Bitmap(recttest.Width, recttest.Height);
using (Graphics g = Graphics.FromImage(cropped))
{
g.DrawImage(pic, new Rectangle(0, 0, recttest.Width, recttest.Height),
recttest, GraphicsUnit.Pixel);
}
return cropped;
}
}
}
For the test i called the rectangle variable recttest.
In the mouse up event i'm getting the rectangle i drawed in the current selected item in the listBox.
I can't upload here images but what i get is when i click the ConfirmRectangle button i see the the rectangle i drawed in the pictureBox the same as it was and the image in the pictureBox get resize get very very big from the inside like it was zoom in.
Instead what i wanted to get is the part of the image in the pictureBox that was marked/drawed by the rectangle. Like the rectangle is the border so when i click on the ConfirmRectangle i will see the part of the image was in the pictureBox in the rectangle and only this all the rest should not be shown.
I should see rectangle with inside the part of the image. Not to resize or zoom in the image only to cut the part was marked/drawn on by the rectangle.
try following method.
Boolean bHaveMouse;
Point ptOriginal = new Point();
Point ptLast = new Point();
private void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
bHaveMouse = true;
// Store the "starting point" for this rubber-band rectangle.
ptOriginal.X = e.X;
ptOriginal.Y = e.Y;
// Special value lets us know that no previous
// rectangle needs to be erased.
ptLast.X = -1;
ptLast.Y = -1;
}
// Convert and normalize the points and draw the reversible frame.
private void MyDrawReversibleRectangle(Point p1, Point p2)
{
Rectangle rc = new Rectangle();
// Convert the points to screen coordinates.
p1 = pictureBox.PointToScreen(p1);
p2 = pictureBox.PointToScreen(p2);
// Normalize the rectangle.
if (p1.X < p2.X)
{
rc.X = p1.X;
rc.Width = p2.X - p1.X;
}
else
{
rc.X = p2.X;
rc.Width = p1.X - p2.X;
}
if (p1.Y < p2.Y)
{
rc.Y = p1.Y;
rc.Height = p2.Y - p1.Y;
}
else
{
rc.Y = p2.Y;
rc.Height = p1.Y - p2.Y;
}
// Draw the reversible frame.
rect = new Rectangle(pictureBox.PointToClient(rc.Location), rc.Size);
ControlPaint.DrawReversibleFrame(rc, Color.Gray, FrameStyle.Dashed);
}
Rectangle rect = Rectangle.Empty;
private void pictureBox_MouseUp(object sender, MouseEventArgs e)
{
// Set internal flag to know we no longer "have the mouse".
bHaveMouse = false;
// If we have drawn previously, draw again in that spot
// to remove the lines.
if (ptLast.X != -1)
{
Point ptCurrent = new Point(e.X, e.Y);
MyDrawReversibleRectangle(ptOriginal, ptLast);
}
// Set flags to know that there is no "previous" line to reverse.
ptLast.X = -1;
ptLast.Y = -1;
ptOriginal.X = -1;
ptOriginal.Y = -1;
pictureBox.Invalidate();
}
private void pictureBox_Paint(object sender, PaintEventArgs e)
{
if (rect.Width > 10 && rect.Height > 10)
{
e.Graphics.DrawRectangle(Pens.Gray, rect);
pictureBox1.Image = CropImage();
}
}
private Bitmap CropImage()
{
Bitmap pic = pictureBox.Image as Bitmap;
Bitmap cropped = new Bitmap(rect.Width, rect.Height);
using (Graphics g = Graphics.FromImage(cropped))
{
g.DrawImage(pic, new Rectangle(0, 0, rect.Width, rect.Height),
rect, GraphicsUnit.Pixel);
}
return cropped;
}
private void pictureBox_MouseMove(object sender, MouseEventArgs e)
{
Point ptCurrent = new Point(e.X, e.Y);
// If we "have the mouse", then we draw our lines.
if (bHaveMouse)
{
// If we have drawn previously, draw again in
// that spot to remove the lines.
if (ptLast.X != -1)
{
MyDrawReversibleRectangle(ptOriginal, ptLast);
}
// Update last point.
ptLast = ptCurrent;
// Draw new lines.
MyDrawReversibleRectangle(ptOriginal, ptCurrent);
}
}
Output
I am using ControPaint.DrawReversibleFrame method to draw rubber band. To read more about this method u can refere this tutorial

How to get the x, y, on a specific form.

I'v been making a program where the user clicks, and wherever they drag their mouse, it draws a line to. It works, but it draws the lines in the wrong place. I think its because I am getting the x y of the whole form, not my panel. Heres the code:
private void panel2_MouseDown(object sender, MouseEventArgs e)
{
vars.x = MousePosition.X;
vars.y = MousePosition.Y;
label1.Text = vars.x + ", " + vars.y;
vars.isDrawing = true;
}
private void panel2_MouseMove(object sender, MouseEventArgs e)
{
if (vars.isDrawing == true)
{
if (e.Button == MouseButtons.Left)
{
int x2 = MousePosition.X;
int y2 = MousePosition.Y;
Random randomGen = new Random();
Color randomColor = Color.FromArgb(randomGen.Next(255), randomGen.Next(255), randomGen.Next(255));
Pen line = new Pen(randomColor, 1);
System.Drawing.Graphics formGraphics = panel2.CreateGraphics();
formGraphics.DrawLine(line, vars.x, vars.y, x2, y2);
}
}
}
Use e.X and e.Y instead of MousePosition.X and MousePosition.Y

Move the rectangle with the mouse

I wrote this code:
private struct MovePoint
{
public int X;
public int Y;
}
private void Image_MouseDown(object sender, MouseEventArgs e)
{
FirstPoint = new MovePoint();
FirstPoint.X = e.X;
FirstPoint.Y = e.Y;
}
private void Image_MouseMove(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
if(FirstPoint.X > e.X)
{
Rectangle.X = FirstPoint.X - e.X;
//Rectangle.Width -= FirstPoint.X - e.X;
} else
{
Rectangle.X = FirstPoint.X + e.X;
//Rectangle.Width += FirstPoint.X + e.X;
}
if(FirstPoint.Y > e.Y)
{
Rectangle.Y = FirstPoint.Y - e.Y;
//Rectangle.Height -= FirstPoint.Y - e.Y;
} else
{
Rectangle.Y = FirstPoint.Y + e.Y;
//Rectangle.Height += FirstPoint.Y + e.Y;
}
Image.Invalidate();
}
}
private void Image_Paint(object sender, PaintEventArgs e)
{
if(Pen != null) e.Graphics.DrawRectangle(Pen, Rectangle);
}
Rectangle moves, but with inversion (it should not be). Can you help?
The mathematics in your mouse-move handler for moving the rectangle based on the mouse-movements seems quite off; I think you want something like this:
private void Image_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
int initialX = 0, initialY = 0; // for example.
Rectangle.X = (e.X - FirstPoint.X) + initialX;
Rectangle.Y = (e.Y - FirstPoint.Y) + initialY;
Image.Invalidate();
}
}
This way, the rectangle's upper left corner will follow the mouse by tracking the delta between the initial mouse-down location and the current mouse location. Note however that each time you re-click and drag, the rectangle will move back to its original location.
If, instead, you want the Rectangle to 'remember' its position across multiple click-and-drag operations (i.e. not to be reinitialized to its initial location on mouse-down) you can do:
private void Image_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
// Increment rectangle-location by mouse-location delta.
Rectangle.X += e.X - FirstPoint.X;
Rectangle.Y += e.Y - FirstPoint.Y;
// Re-calibrate on each move operation.
FirstPoint = new MovePoint { X = e.X, Y = e.Y };
Image.Invalidate();
}
}
One other suggestion: There's no need to create your own MovePoint type when there's already the System.Drawing.Point type. Also, in general, try not to create mutable structs.

Categories

Resources