Drawing a rectangle on a picture box - c#

When this form opens, it has a background image of the fullscreen and the user can mouse down and draw a rectangle which will be used later to crop the background image. The problem I am getting is that when the form paints, it's not drawing a rectangle so the user doesnt know the the area they are selecting
This is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Quick_Screenshot
{
public partial class Crop : Form
{
private Rectangle croprect = Rectangle.Empty;
private bool mouseDown = false;
private bool selectedArea = false;
Point sp, ep;
Bitmap background;
public Rectangle CropArea
{
get { return croprect; }
}
public bool SelectedArea
{
get { return selectedArea; }
}
public Crop(Bitmap image)
{
InitializeComponent();
background = image;
picBox.MouseDown += new MouseEventHandler(Crop_MouseDown);
picBox.MouseUp += new MouseEventHandler(Crop_MouseUp);
picBox.MouseMove += new MouseEventHandler(Crop_MouseMove);
picBox.Paint += new PaintEventHandler(Crop_Paint);
}
private void Crop_Load(object sender, EventArgs e)
{
picBox.Image = (Image)background;
}
private void Crop_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
this.Close();
else
{
mouseDown = true;
sp = ep = e.Location;
}
}
private void Crop_MouseUp(object sender, MouseEventArgs e)
{
ep = e.Location;
mouseDown = false;
croprect = GetRectangle(sp, ep);
if (croprect.Width > 10 && croprect.Height > 10)
{
selectedArea = true;
}
else
{
croprect = Rectangle.Empty;
Taskbar.Balloon("Selected area too small", "Quick Screenshot", ToolTipIcon.Error);
}
this.Close();
}
private void Crop_MouseMove(object sender, MouseEventArgs e)
{
if (mouseDown)
{
ep = e.Location;
Update();
}
}
private void Crop_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawRectangle(Pens.Red, GetRectangle(sp, ep));
e.Graphics.Save();
}
private Rectangle GetRectangle(Point p1, Point p2)
{
return new Rectangle(
Math.Min(p1.X, p2.X),
Math.Min(p1.Y, p2.Y),
Math.Abs(p1.X - p2.X),
Math.Abs(p1.Y - p2.Y)
);
}
}
}

You should call the Invalidate() method on the picBox variable to refresh the control.
Instead of this:
private void Crop_MouseMove(object sender, MouseEventArgs e)
{
if (mouseDown)
{
ep = e.Location;
Update();
}
}
Use this:
private void Crop_MouseMove(object sender, MouseEventArgs e)
{
if (mouseDown)
{
ep = e.Location;
picBox.Invalidate();
}
}

You should call Invalidate() instead of Update()

Related

C# Graphics DrawLine Deletion

my drawings are deleted in the code I wrote. If "refresh" is not used, the drawing does not appear. Is there a mistake in my drawing? I don't understand
How can I draw a new line without erasing my lines ?
Here's the code
Pen pen;
Point startXY;
Point endXY;
bool ismoving = false;
string choice = "Line";
public Form1(){
InitializeComponent();}
private void drawArea_MouseDown(object sender, MouseEventArgs e){
startXY = e.Location;
ismoving = true;}
private void drawArea_MouseMove(object sender, MouseEventArgs e){
if (ismoving == true){
endXY = e.Location;
drawArea.Refresh();}}
private void drawArea_MouseUp(object sender, MouseEventArgs e){
endXY = e.Location;
ismoving = false;}
private void Form1_Load(object sender, EventArgs e){
//Graphics graph = drawArea.CreateGraphics();
//graph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
pen = new Pen(Color.White,1);
pen.StartCap = pen.EndCap = System.Drawing.Drawing2D.LineCap.Round;}
private void drawArea_Paint(object sender, PaintEventArgs e){
switch (choice){
case "Line":{
e.Graphics.DrawLine(pen, startXY, endXY);
break;}}}
Your code needs to know how to recreate the entire graphics window at any time, because windows may ask it to redraw at any time.
So you need to keep track of the things to be drawn in a list and use this list in the Paint event to render to the screen.
Below is an example code that does this. The result looks like this
public enum Tool
{
Line,
PolyLine,
Circle,
}
public partial class Form1 : Form
{
Point startXY;
Point endXY;
bool isMoving;
Tool next;
public Form1()
{
InitializeComponent();
this.Drawing = new List<IDrawObject>();
this.isMoving = false;
this.next = Tool.Line;
this.drawArea.BackColor = Color.Black;
this.drawArea.BorderStyle = BorderStyle.FixedSingle;
}
public List<IDrawObject> Drawing { get; }
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
drawArea.Resize += (s, ev) => drawArea.Refresh();
drawArea.Paint += pictureBox1_Paint;
drawArea.MouseDown += PictureBox1_MouseDown;
drawArea.MouseMove += PictureBox1_MouseMove;
drawArea.MouseUp += PictureBox1_MouseUp;
this.KeyDown += (s, ev) =>
{
switch (ev.KeyCode)
{
case Keys.Space:
next = NextTool(next);
UpdateFormTitle();
break;
}
};
UpdateFormTitle();
}
public void UpdateFormTitle()
{
this.Text = $"Draw Area. Tool={next}. Press [SPACE] to switch.";
}
private void PictureBox1_MouseUp(object sender, MouseEventArgs e)
{
isMoving = false;
endXY = e.Location;
Drawing.Add(NextDrawObject());
drawArea.Invalidate();
}
private void PictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (isMoving)
{
endXY = e.Location;
drawArea.Invalidate();
}
}
private void PictureBox1_MouseDown(object sender, MouseEventArgs e)
{
isMoving = true;
startXY = e.Location;
}
protected void pictureBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
using (var pen = new Pen(Color.White, 1))
{
pen.EndCap = LineCap.Round;
pen.StartCap = LineCap.Round;
foreach (var item in Drawing)
{
item.Draw(e.Graphics, pen);
}
if (isMoving)
{
pen.Color = Color.SteelBlue;
pen.DashStyle = DashStyle.Dash;
NextDrawObject().Draw(e.Graphics, pen);
}
}
}
public static float Distance(Point from, Point to)
{
var dx = (float)(to.X-from.X);
var dy = (float)(to.Y-from.Y);
return (float)Math.Sqrt(dx*dx+dy*dy);
}
public Tool NextTool(Tool current)
{
switch (current)
{
case Tool.Line:
return Tool.Circle;
case Tool.Circle:
return Tool.Line;
case Tool.PolyLine:
throw new NotImplementedException();
default:
throw new NotSupportedException();
}
}
public IDrawObject NextDrawObject()
{
switch (next)
{
case Tool.Line:
return new Line(startXY, endXY);
case Tool.PolyLine:
throw new NotImplementedException();
case Tool.Circle:
var radius = Distance(startXY, endXY);
return new Circle(startXY, radius);
default:
throw new NotSupportedException();
}
}
}
public interface IDrawObject
{
void Draw(Graphics g, Pen pen);
}
public struct Line : IDrawObject
{
public Line(PointF from, PointF to)
{
this.From=from;
this.To=to;
}
public PointF From { get; }
public PointF To { get; }
public void Draw(Graphics g, Pen pen)
{
g.DrawLine(pen, From, To);
}
}
public struct PolyLine : IDrawObject
{
public PolyLine(params PointF[] nodes)
{
this.Nodes=nodes;
}
public PointF[] Nodes { get; }
public void Draw(Graphics g, Pen pen)
{
g.DrawLines(pen, Nodes);
}
}
public struct Circle : IDrawObject
{
public Circle(PointF center, float radius)
{
this.Center=center;
this.Radius=radius;
}
public PointF Center { get; }
public float Radius { get; }
public void Draw(Graphics g, Pen pen)
{
g.DrawEllipse(pen, Center.X-Radius, Center.Y-Radius, 2*Radius, 2*Radius);
}
}

saving my graphic drawing panel as png or jpg image format

I make a graphic drawing panel [my own paint program] and I want save my own drawing. This is my all code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace pezeshk
{
public partial class pen : Form
{
private SolidBrush myBrush;
private Graphics myGraphics;
private bool isDrawing = false;
public pen()
{
InitializeComponent();
}
private void pen_Load(object sender, EventArgs e)
{
myBrush = new SolidBrush(panel2.BackColor);
myGraphics = panel1.CreateGraphics();
}
private void panel2_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (colorDialog1.ShowDialog() == DialogResult.OK)
{
panel2.BackColor = colorDialog1.Color;
myBrush.Color = panel2.BackColor;
}
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
isDrawing = true;
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
isDrawing = false;
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (isDrawing == true)
{
myGraphics.FillEllipse(myBrush, e.X, e.Y, trackBar1.Value, trackBar1.Value);
}
}
}
for everyone that need this code
this code works [thx to #Taw]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace pezeshk
{
public partial class pen : Form
{
private SolidBrush myBrush;
private Pen myPen;
private Graphics myGraphics;
private bool isDrawing = false;
public pen()
{
InitializeComponent();
myPen = new Pen(Color.ForestGreen);
myBrush = new SolidBrush(Color.DarkSlateBlue);
}
void panel1_paint(object sender, PaintEventArgs e)
{
if (rb_pen.Checked)
{
if (points.Count > 1) e.Graphics.DrawCurve(myPen, points.ToArray());
foreach (List<Point> lp in curves)
if (lp.Count > 1)
e.Graphics.DrawCurve(myPen, lp.ToArray());
}
}
private void pen_Load(object sender, EventArgs e)
{
myBrush = new SolidBrush(panel2.BackColor);
myGraphics = panel1.CreateGraphics();
}
private void panel2_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (colorDialog1.ShowDialog() == DialogResult.OK)
{
panel2.BackColor = colorDialog1.Color;
myBrush.Color = panel2.BackColor;
}
}
Point mDown = Point.Empty;
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
mDown = e.Location;
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
if (rb_pen.Checked)
{
if (points.Count > 1) curves.Add(points.ToList()); // copy!!
points.Clear();
panel1.Invalidate();
}
panel1.Invalidate();
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
if (rb_pen.Checked)
{
points.Add(e.Location);
}
panel1.Invalidate();
}
}
List<Rectangle> circles = new List<Rectangle>();
List<Point> points = new List<Point>();
List<List<Point>> curves = new List<List<Point>>();
private void button1_Click(object sender, EventArgs e)
{
string somefolder = "D:\\"; using (Bitmap bmp = new Bitmap(panel1.ClientSize.Width, panel1.ClientSize.Height))
{
panel1.DrawToBitmap(bmp, panel1.ClientRectangle); bmp.Save(somefolder + panel1.Name + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
private void button2_Click(object sender, EventArgs e)
{
curves.Clear(); points.Clear(); panel1.Invalidate();
}
}
class DrawPanel : Panel
{
public DrawPanel() { DoubleBuffered = true; }
}
}

My shape will appear for a few seconds

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Engine : Form
{
int x, y;
int w, h;
Boolean running = false;
public Engine()
{
InitializeComponent();
}
private void Engine_Load(object sender, EventArgs e)
{
}
private void Engine_Paint(object sender, PaintEventArgs e)
{
}
private void XTB_TextChanged(object sender, EventArgs e)
{
if (XTB.Text.Equals("10"))
{
x = 10;
}
if (XTB.Text.Equals("20"))
{
x = 20;
}
}
private void YTB_TextChanged(object sender, EventArgs e)
{
if (YTB.Text.Equals("10"))
{
y = 10;
}
}
private void WTB_TextChanged(object sender, EventArgs e)
{
if (WTB.Text.Equals("8"))
{
w = 8;
}
if (WTB.Text.Equals("16"))
{
w = 16;
}
if (WTB.Text.Equals("32"))
{
w = 32;
}
}
private void HTB_TextChanged(object sender, EventArgs e)
{
if (HTB.Text.Equals("8"))
{
h = 8;
}
if (HTB.Text.Equals("16"))
{
h = 16;
}
if (HTB.Text.Equals("32"))
{
h = 32;
}
}
private void drawShapeOnForm()
{
Graphics g = this.CreateGraphics();
g.DrawRectangle(new Pen(Brushes.Blue), x, y, w, h);
g.FillRectangle(Brushes.Blue, x, y, w, h);
}
//Button draws square
private void COIN_Click(object sender, EventArgs e)
{
drawShapeOnForm();
}
private void Engine_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.A)
{
x--;
}
}
private void button1_Click(object sender, EventArgs e)
{
running = true;
if (running)
{
PlayerCreator.Enabled = false;
EnemyCreator.Enabled = false;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
Invalidate();
}
}
}
My shape only appears for a few secs when I press the button to make it, I'm not to sure how to fix this.
When I press the button it appears and then disappears, but if the function is put on the void Engine_Paint() it will work just fine. Please help me fix this problem.
You need to do your drawing in the Paint handler, using e.Graphics. Do not use CreateGraphics.
From your button click, you can just call this.Invalidate(); to trigger a repaint.

Moving a control by dragging it with the mouse in C#

I'm trying to move the control named pictureBox1 by dragging it around. The problem is, when it moves, it keeps moving from a location to another location around the mouse, but it does follow it...
This is my code. and I would really appreciate it if you could help me
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
bool selected = false;
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
selected = true;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (selected == true)
{
pictureBox1.Location = e.Location;
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
selected = false;
}
}
All you need:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Point MouseDownLocation;
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
MouseDownLocation = e.Location;
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
pictureBox1.Left = e.X + pictureBox1.Left - MouseDownLocation.X;
pictureBox1.Top = e.Y + pictureBox1.Top - MouseDownLocation.Y;
}
}
}
You can also use the extension:
public static class CmponentsExtensions
{
//Management of mouse drag and drop
#region Menu and Mouse
private static bool mouseDown;
private static Point lastLocation;
/// <summary>
/// To enable control to be moved around with mouse
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="control"></param>
public static void moveItselfWithMouse<T>(this T control) where T: Control
{
control.MouseDown += (o, e)=> { mouseDown = true; lastLocation = e.Location; };
control.MouseMove += (o, e) =>
{
if (mouseDown)
{
control.Location = new Point((control.Location.X - lastLocation.X) + e.X, (control.Location.Y - lastLocation.Y) + e.Y);
control.Update();
}
};
control.MouseUp += (o, e) => { mouseDown = false; } ;
}
public static void moveOtherWithMouse<T>(this T control, Control movedObject) where T : Control
{
control.MouseDown += (o, e) => { mouseDown = true; lastLocation = e.Location; };
control.MouseMove += (o, e) =>
{
if (mouseDown)
{
movedObject.Location = new Point((movedObject.Location.X - lastLocation.X) + e.X, (movedObject.Location.Y - lastLocation.Y) + e.Y);
movedObject.Update();
}
};
control.MouseUp += (o, e) => { mouseDown = false; };
}
#endregion
}
Then you need to use it with some control:
In this case pictureBox1 moved the whole Form
pictureBox1.moveOtherWithMouse(this);
In this case you move only pictureBox:
pictureBox1.moveItselfWithMouse();
try this to move pictureBox control at runtime using mouse
private void pictureBox7_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
xPos = e.X;
yPos = e.Y;
}
}
private void pictureBox7_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
PictureBox p = sender as PictureBox;
if (p != null)
{
if (e.Button == MouseButtons.Left)
{
p.Top += (e.Y - yPos);
p.Left += (e.X - xPos);
}
}
}

simple move-after-cursor problem c# winforms

I have a winform app and when i click on a button, i would like to have a string text move after my cursor. I've written some code but it doesn't seem to work . please Help !
Here is the code :
private void corectionBrushToolStripMenuItem_Click(object sender, EventArgs e)
{
this.MouseMove += new MouseEventHandler(On_MouseMove);
this.Paint += new PaintEventHandler(DrawRect);
}
private void DrawRect(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawString("da",Font,Brushes.Black,new Point(mouseMoveX,mouseMoveY));
}
public void On_MouseMove(object sender, MouseEventArgs mouseEv)
{
mouseMoveX = mouseEv.X;
mouseMoveY = mouseEv.Y;
this.Invalidate();
}
Regards,
Alex Badescu
This is an example that does what you want I think. the offset in the mouse move is so that it shows up not under the mouse.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace winap
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private bool DrawText = false;
private void button1_Click(object sender, EventArgs e)
{
DrawText = !DrawText;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
if(DrawText)
{
if (lp != p)
{
this.Invalidate();
}
e.Graphics.DrawString("hi", SystemFonts.DefaultFont, Brushes.Green, p);
lp = p;
}
}
private PointF p;
private PointF lp;
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
p = new PointF(e.X -10, e.Y);
this.Invalidate();
}
}
}
How about:
Add the desired text to a label control, and change the position in MouseMove.
Following works fine:
int mX = 0;
int mY = 0;
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
mX = e.X;
mY = e.Y;
this.Invalidate();
}
Random rr = new Random(123123);
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawString("This a test"+rr.Next().ToString(), Font, Brushes.Black, new Point(mX, mY));
}

Categories

Resources