I'm very new in C#
I want a rectangle to appear wherever there's a mouseclick on a panel
Here's my code:
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
int x = e.Location.X;
int y = e.Location.Y;
if (radioButton1.Checked == false)
{
((Panel)sender).Invalidate(new Rectangle(x * 40, y * 40, 40, 40));
}
else if (radioButton2.Checked == true)
{
return;
}
}
I wonder how to change the color of the rectangle?
Please advise me if my code is wrong.
Thanks.
Your drawing should be performed in the panel's Paint event handler. When you click the panel, create the rectangle (in the MouseUp event of the panel) and store it in a collection of rectangles (such as a dictionary). Then refresh the panel. In the panel's Paint event, draw all the rectangles. Here is a simple example:
Dictionary<Color, List<Rectangle>> rectangles = new Dictionary<Color, List<Rectangle>>();
private void panel1_Paint(object sender, PaintEventArgs e)
{
//The key value for the dictionary is the color to use to paint with, so loop through all the keys (colors)
foreach (var rectKey in rectangles.Keys)
{
using (var pen = new Pen(rectKey)) //Create the pen used to draw the rectangle (using statement makes sure the pen is disposed)
{
//Draws all rectangles for the current color
//Note that we're using the Graphics object that is passed into the event handler.
e.Graphics.DrawRectangles(pen, rectangles[rectKey].ToArray());
}
}
}
//This method just adds the rectangle to the collection.
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
Color c = getSelectedColor(); //Gets a color for which to draw the rectangle
//Adds the rectangle using the color as the key for the dictionary
if (!rectangles.ContainsKey(c))
{
rectangles.Add(c, new List<Rectangle>());
}
rectangles[c].Add(new Rectangle(e.Location.X - 12, e.Location.Y - 12, 25, 25)); //Adds the rectangle to the collection
}
//Make the panel repaint itself.
panel1.Refresh();
}
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
Graphics g = panel1.CreateGraphics();
g.DrawRectangle(new Pen(Brushes.Black),
new Rectangle(new Point(e.X, e.Y), new
Size(100, 100)));
}
you can change the color in Brushes.Black part of code, change it as you desire
Related
I am creating a Graphics Form where objects with coordinates x,y are being drawn into the Graphics. It works properly for small x and y, but when I want to draw them in different place (f.e. x = 500, y = 300) they disappear.
public WindowHandler()
{
dc = this.CreateGraphics();
this.Size = new Size(sizeX, sizeY); // 800x600
startSimulation = new Button
{
// button properties
};
this.Controls.Add(startSimulation);
startSimulation.Click += new EventHandler(StartSimulationClick);
}
private void CreationsMethods()
{
creations.PaintAllAnimals(dc);
}
public void PaintAllAnimals(Graphics g)
{
foreach (var animal in ecoStructure.world.animals)
{
animal.PaintAnimal(g);
}
}
public void PaintAnimal(Graphics graphics)
{
Rectangle rectangle = new Rectangle(x, y, 3, 3);
Pen pen = new Pen(colour);
graphics.DrawRectangle(pen, rectangle);
graphics.FillRectangle(colour, rectangle);
}
I want to put all the objects onto the window. Is there any way to make the Graphics "bigger"? Do I need to make another one? Or should I use different tool to draw rectangles?
Thanks to #Chris Dunaway for posting an answer in comment.
So I deleted the CreateCraphics, and instead of that i am now using an OnPaint method. It works slowly, but works. So I will try to make it as fast as i can. For now, I just created this. NextStepClick is how I use the OnPaint to paint the rectangles.
private void CreationsMethods(object sender, PaintEventArgs e)
{
dc = e.Graphics;
base.OnPaint(e);
creations.PaintAllAnimals(dc);
}
private void NextStepClick(object sender, EventArgs e)
{
this.Refresh();
picBox.Paint += new System.Windows.Forms.PaintEventHandler(CreationsMethods);
}
Trying to draw a shape over existing panels for a good while, but by now out of ideas. Could somebody help me out, please? It ends up always behind the panels (and pictureBox /the grey one/). I tried 3 different ways, whithout success. this is my code:
namespace DrawingOnFront
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void panel11_MouseClick(object sender, MouseEventArgs e)
{
DrawIt(90, 70);
}
private void DrawIt(int x, int y)
{
Rectangle Circle = new Rectangle(x,y,40,40);
SolidBrush Red = new SolidBrush(Color.Red);
Graphics g = this.CreateGraphics();
g.FillEllipse(Red, Circle);
/*
Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
Graphics g = Graphics.FromImage(bmp);
int width = pictureBox1.Width /4;
int height = pictureBox1.Height /2;
int diameter = Math.Min(width, height);
g.FillEllipse(Red, x, y, width, height);
pictureBox1.Image = bmp;
*/
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (Graphics g = e.Graphics)
{
Rectangle Circle = ClientRectangle;
Circle.Location = new Point(100, 60);
Circle.Size = new Size(40, 40);
using (SolidBrush Green = new SolidBrush(Color.Green))
{
g.FillEllipse(Green, Circle);
}
}
}
}
}
Sorry for this basic lama question, probably for most of you it is very easy, I am still learning it. Thanks a lot in advance.
My comments above apply. Here is an example of how to draw onto each control and the form separately:
We best have a common drawing routine that we can call from the Paint event of each participating element, in our case a Panel, a PictureBox and the Form.
The trick is for all nested elements to draw the circle shifted by their own location. To do so we pass these things into the drawing routine:
a valid Graphics object. We get it from the Paint events.
and a reference to the control; we use it to offset the drawing on each control (except the form) with Graphics.TranslateTransform..:
Result:
As you can see it looks as if we painted one circle over all elements but actually we drew three circles, each onto one element..:
private void canvasForm_Paint(object sender, PaintEventArgs e)
{
draw(sender as Control, e.Graphics);
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
draw(sender as Control, e.Graphics);
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
draw(sender as Control, e.Graphics);
}
private void draw(Control ctl, Graphics g)
{
Rectangle r = new Rectangle(200, 100, 75, 75);
if (ctl != canvasForm) g.TranslateTransform(-ctl.Left, -ctl.Top);
g.FillEllipse(Brushes.Green, r);
g.ResetTransform();
}
Note that the same result could be created with three calls, one FillRectangle, one DrawImage and one FillEllipse :-)
This question already has answers here:
Draw a rectangle on mouse click
(4 answers)
Closed 7 years ago.
So I've been trying lately to make a paint application to practice C#.
My problem for the past 2 days is in the creation of rectangles.
I made a panel so all the drawing are going there. The user selects the shape he wants to draw using a menu and he can start drawing with the mouse.
I encounter 2 problems which are the following:
1) Even though my starting point was inside the panel, I moved the mouse and went outside the panel and the rectangle was drawn outside the panel as shown in the picture below.
2) After I create this rectangle and I try to draw another, the previous one is deleted. So in a way I can't draw 2 rectangles at once.
Here's a part of my source code.
Graphics mygraphics;
Pen lPen = new Pen(Color.Black); //Left Pen
Pen rPen = new Pen(Color.White); //Right pen
Point sp = new Point(0, 0);
private bool isRectangle;
private bool isLeft, isRight; //isLeft -- Left Click, isRight -- Right Click
private void drawPanel_MouseMove(object sender, MouseEventArgs e)
{
if (isRectangle == true)
{
if (e.Button == MouseButtons.Left)
{
isLeft = true;
Point p = e.Location;
int x = Math.Min(sp.X, p.X);
int y = Math.Min(sp.Y, p.Y);
int w = Math.Abs(p.X - sp.X);
int h = Math.Abs(p.Y - sp.Y);
mRect = new Rectangle(x, y, w, h);
this.Invalidate();
}
}
}
private void drawPanel_MouseDown(object sender, MouseEventArgs e)
{
sp = e.Location;
}
private void drawPanel_MouseUp(object sender, MouseEventArgs e)
{
isLeft = false;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawRectangle(lPen, mRect);
}
What I want to accomplish is my rectangles not getting deleted after I try to draw another one and to draw them inside the panel.
What do you guys suggest?
Here are the minimal changes I suggest:
List<Rectangle> rectangles = new List<Rectangle>();
Rectangle mRect = Rectangle.Empty;
private void drawPanel_MouseUp(object sender, MouseEventArgs e)
{
isLeft = false;
rectangles.Add(mRect);
mRect = Rectangle.Empty;
drawPanel.Invalidate();
}
private void drawPanel_Paint(object sender, PaintEventArgs e)
{
foreach (Rectangle rect in rectangles) e.Graphics.DrawRectangle(lPen, rect );
e.Graphics.DrawRectangle(Pens.Orange, mRect); // or whatever..
}
Note that the Paint event now is the one of the Panel. Do make sure you hook it up with the Panel!!
Also note how I draw the current rectangle mRect in a different color than the list of the other rectangles; this is of course optional..
I have created a small application in C#, in which I draw a rectangle when the mouse is moved.
However, when the form is minimized or maximized, the drawing is erased. Also, when I draw a second time, the drawing of the first rectangle is erased.
How can I solve this problem? Here is the code that I currently have:
int X, Y;
Graphics G;
Rectangle Rec;
int UpX, UpY, DwX, DwY;
public Form1()
{
InitializeComponent();
//G = panel1.CreateGraphics();
//Rec = new Rectangle(X, Y, panel1.Width, panel1.Height);
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
UpX = e.X;
UpY = e.Y;
//Rec = new Rectangle(e.X, e.Y, 0, 0);
//this.Invalidate();
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
DwX = e.X;
DwY = e.Y;
Rec = new Rectangle(UpX, UpY, DwX - UpX, DwY - UpY);
Graphics G = pictureBox1.CreateGraphics();
using (Pen pen = new Pen(Color.Red, 2))
{
G.DrawRectangle(pen, Rec);
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
// Draws the rectangle as the mouse moves
Rec = new Rectangle(UpX, UpY, e.X - UpX, e.Y - UpY);
Graphics G = pictureBox1.CreateGraphics();
using (Pen pen = new Pen(Color.Red, 2))
{
G.DrawRectangle(pen, Rec);
}
G.Save();
pictureBox1.SuspendLayout();
pictureBox1.Invalidate();
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
pictureBox1.Update();
}
The reason why your drawings are getting erased is because you're drawing into a Graphics object you obtained by calling the CreateGraphics method. In particular, this line of your code is incorrect:
Graphics G = pictureBox1.CreateGraphics();
As you've discovered, whenever the form is repainted (which happens when it is maximized, minimized, covered by another object on the screen, or in a number of other possible situations), everything that you've drawn into that temporary Graphics object is lost. The form completely repaints itself with its internal painting logic; it's completely forgotten about what you temporarily drew on top of it.
The correct way to draw persistent images in WinForms is to override the OnPaint method of the control that you want to draw onto (or, you could also handle the Paint event). So, if you wanted to paint onto your form, you would place your drawing code into the following method:
protected override void OnPaint(PaintEventArgs e)
{
// Call the base class first
base.OnPaint(e);
// Then insert your custom drawing code
Rec = new Rectangle(UpX, UpY, DwX - UpX, DwY - UpY);
using (Pen pen = new Pen(Color.Red, 2))
{
e.Graphics.DrawRectangle(pen, Rec);
}
}
And to trigger a re-paint, you just call the Invalidate method in any of the mouse events (MouseDown, MouseMove, and MouseUp):
this.Invalidate();
Note, however, that there's absolutely no reason to call the Update method in the Paint event handler. All that calling the Update method does is force the control to repaint itself. But that is already happening when the Paint event gets raised!
I want to draw a rectangle. Thing what I want is that show the user to rectangle on the mouse event.
Like in the image. This is for C# .net Forms application.
Help me to achieve this. Any help is appreciated.
Thank You
Yohan
You can do that in three steps:
First check if mouse is pressed down
If it is then on mouse move event keep initializing the rectangle with new positions while mouse is being dragged
Then on paint event draw the rectangle. (It will be raised for almost every mouse event, depends mouse refresh rate and dpi)
You can do somthing like this (in your Form):
public class Form1
{
Rectangle mRect;
public Form1()
{
InitializeComponents();
//Improves prformance and reduces flickering
this.DoubleBuffered = true;
}
//Initiate rectangle with mouse down event
protected override void OnMouseDown(MouseEventArgs e)
{
mRect = new Rectangle(e.X, e.Y, 0, 0);
this.Invalidate();
}
//check if mouse is down and being draged, then draw rectangle
protected override void OnMouseMove(MouseEventArgs e)
{
if( e.Button == MouseButtons.Left)
{
mRect = new Rectangle(mRect.Left, mRect.Top, e.X - mRect.Left, e.Y - mRect.Top);
this.Invalidate();
}
}
//draw the rectangle on paint event
protected override void OnPaint(PaintEventArgs e)
{
//Draw a rectangle with 2pixel wide line
using(Pen pen = new Pen(Color.Red, 2))
{
e.Graphics.DrawRectangle(pen, mRect);
}
}
}
later if you want to check if Buttons (shown in diagram) are in rectangle or not , you can do that by checking the Button's region and check if they lie in your drawn rectangle.
The solution by Shekhar_Pro draws a rectangle just in one direction (top to bottom, left to right) if you want to draw a rectangle regardless of the mouse position and the direction of the movement the solution is:
Point selPoint;
Rectangle mRect;
void OnMouseDown(object sender, MouseEventArgs e)
{
selPoint = e.Location;
// add it to AutoScrollPosition if your control is scrollable
}
void OnMouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Point p = e.Location;
int x = Math.Min(selPoint.X, p.X)
int y = Math.Min(selPoint.Y, p.Y)
int w = Math.Abs(p.X - selPoint.X);
int h = Math.Abs(p.Y - selPoint.Y);
mRect = new Rectangle(x, y, w, h);
this.Invalidate();
}
}
void OnPaint(object sender, PaintEventArgs e)
{
e.Graphics.DrawRectangle(Pens.Blue, mRect);
}
Those blue rectangles look a lot like controls. Drawing a line on top of a control is hard to do in Winforms. You have to create a transparent window that overlays the design surface and draw the rectangle on that window. This is also the way the Winforms designer works. Sample code is here.