How to draw a rectangle on a button click? - c#

I want when I click button, add one rectangle to the form
I can add in form paint how much I want but I can't add shape like rectangle by click button and I searched about it but I didn't find a solution for it
is here somebody know how to do it?
This is my code in form paint
private void Form1_Paint(object sender, PaintEventArgs e)
{
locationX = locationX + 20;
locationY = locationY + 20;
e.Graphics.DrawRectangle(Pens.Black,
new Rectangle(10 + locationX, 10 + locationY, 50, 30));
}
and this one is my button code
private void button1_Click(object sender, EventArgs e)
{
this.Paint += Form1_Paint;
}
but its not working when I click button. why its not working?

The line
this.Paint += Form1_Paint;
Associate the event Paint of your Form to your function Form1_Paint. It doesn't trigger it. This is something you want to do only 1 time, not everytime you hit a button.
To trigger the Paint event, the usual way is to call the Invalidate() method of the Form class. In fact, Invalidate is a method of Control. But Form derivate from Control, so we have access to the method in Form too.
So the right way to trigger a repaint in Windows Forms is to put the subscribe in the Load method :
private void Form1_Load(object sender, EventArgs e)
{
this.Paint += Form1_Paint;
}
It should already be hidden in the auto generated code.
Your method Form1_Paint is ok.
Finally, the button click method should be :
private void button1_Click(object sender, EventArgs e)
{
this.Invalidate(); // force Redraw the form
}
From the doc :
Invalidate() : Invalidates the entire surface of the control and causes the control to be redrawn.
Edit :
With this method, you can draw only 1 rectangle at a time, because the whole surface is redrawn, so the surface is completly erase, and then it draws only what you asked in the Form1_Paint method.
For the answer on how to draw multiple rectangles, you should create a List of Rectangle. At each click button, you add a Rectangle to the list, and you redraw all the rectangles.
List<Rectangle> _rectangles = new List<Rectangle>();
private void button1_Click(object sender, EventArgs e)
{
locationX = locationX + 20;
locationY = locationY + 20;
var rectangle = new Rectangle(locationX, locationY, 50, 30));
this._rectangles.Add(rectangle);
this.Invalidate(); // force Redraw the form
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
foreach(var rectangle in this._rectangles)
{
e.Graphics.DrawRectangle(Pens.Black, rectangle);
}
}

to call a method you need the parenthesys.
private void button1_Click(object sender, EventArgs e)
{
Form1_Paint(sender, e);
}

Related

How to draw border for panel which is continously resizing c#

Using panel as a selection indicator . The panel changes its size according to cursor position on MouseMove event . However when I draw the border as below , previous borders leave their mark on the panel and it displays too many border within same panel . Even tried refresh() before every draw but that makes it glitchy and slow
private void panel1_Paint(object sender, PaintEventArgs e)
{
this.panel1.Refresh();
ControlPaint.DrawBorder(e.Graphics, this.panel1.ClientRectangle, Color.DarkBlue, ButtonBorderStyle.Solid);
}
private void drawboard_MouseMove(object sender, MouseEventArgs e)
{
panel1.Width = e.Location.X - panel1.Left;
panel1.Height = e.Location.Y - panel1.Top;
}
First off, you should never call control paint affecting methods like Invalidate or Refresh inside the control paint handler.
You can solve the original issue by calling Invalidate or Refresh after modifying the size of the panel. Note that it's better to set the Size property with one call rather than Width and Height separately:
private void panel1_Paint(object sender, PaintEventArgs e)
{
ControlPaint.DrawBorder(e.Graphics, this.panel1.ClientRectangle, Color.DarkBlue, ButtonBorderStyle.Solid);
}
private void drawboard_MouseMove(object sender, MouseEventArgs e)
{
var size = new Size(Math.Max(e.Location.X - panel1.Left, 0),
Math.Max(e.Location.Y - panel1.Top, 0));
if (panel1.Size != size)
{
panel1.Size = size;
panel1.Invalidate();
}
}
A better option is to set ResizeRedraw property of the selection panel to true. Since it's a protected property, you need to create and use your own Panel subclass. As a bonus, you can also set DoubleBuffered property to true to avoid the flickering, and also move the painting code inside:
class SelectionBox : Panel
{
public SelectionBox()
{
ResizeRedraw = true;
DoubleBuffered = true;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
ControlPaint.DrawBorder(e.Graphics, ClientRectangle, Color.DarkBlue, ButtonBorderStyle.Solid);
}
}
Make your panel1 to be SelectionBox, remove the Paint event handler, and then the mouse move handler could be simple
private void drawboard_MouseMove(object sender, MouseEventArgs e)
{
panel1.Size = new Size(Math.Max(e.Location.X - panel1.Left, 0),
Math.Max(e.Location.Y - panel1.Top, 0));
}

C# How to disable paint event of a panel when called using panel.BringToFront() method? [duplicate]

This question already has answers here:
Double Buffering when not drawing in OnPaint(): why doesn't it work?
(2 answers)
Closed 7 years ago.
I have two Panels stacked in Form, When one panel1 is showing,the panel2 is in background and If i call Panel2 using BringToFront() method to View the Panel2, The paint Event of the Panel2 is calling. So i want to prevent Panel2 from calling Paint Event to Disable Redrawing of the Panel.
I think the paint method is a default event that has any regard to "display", hmm have you tried doing a workaround like creating a separate static flag for the purpose of preventing your paint events?
(again this is just a workaround)
Sample :
public bool displayed {get; set;}
private void Form1_Load(object sender, EventArgs e)
{
displayed = false;
}
private void Panel1_Paint(object sender, PaintEventArgs e)
{
if(!displayed) {
// do paint functions
displayed = true;
}
}
EDIT : Please try this one.
private void Form1_Load(object sender, EventArgs e)
{
}
private void panel2_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawRectangle(
new Pen(Color.Green, 3),
new Rectangle(10, 10, 50, 50));
//Drawing an ellipse
e.Graphics.FillEllipse(Brushes.Green, new Rectangle(60, 60, 100, 100));
//Drawing text
e.Graphics.DrawString("Text", new Font("Verdana", 14), new SolidBrush(Color.Green), 200, 200);
}
private void button1_Click_1(object sender, EventArgs e)
{
panel1.Visible = true;
panel2.Visible = false;
}
private void button2_Click_1(object sender, EventArgs e)
{
panel1.Visible = false;
panel2.Visible = true;
}
// code described below
public class MyDisplay : Panel
{
public MyDisplay()
{
this.DoubleBuffered = true;
}
}
As mentioned here Gets or sets a value indicating whether this control should redraw its surface using a secondary buffer to reduce or prevent flicker. This should now work regardless if SendToBack() BringToFront() or Visible set.

How can I add events to a PictureBox dynamically created by clicking button? (C#)

I'm creating dynamically a bunch of PictureBoxes by clicking a button in my form, but I'm not clear on how can I add an event to each one. Here's my idea
private void insertarBloqueToolStripMenuItem_Click(object sender, EventArgs e)
{
pbA = new PictureBox{
Name = "picturebox" + contB,
Image = new Bitmap(bloque),
Size = pbA.Image.Size,
};
pbA.MouseDown += new MouseEventHandler(pbA_MouseDown);
pbA.MouseUp += new MouseEventHandler(pbA_MouseUp);
pbA.MouseMove += new MouseEventHandler(pbA_MouseMove);
pbA.Paint += new PaintEventHandler(pbA_Paint);
pbA.Cursor = Cursors.Hand;
listaBloques.Add(pbA);
panel1.Controls.Add(pbA);
}
That's what I got, can you help me with that idea? And How can I can create a single method to move one PictureBox on the list? Thank you
Your idea is quite good!
But it would be enought to write (but yours works also fine):
pbA.Paint += pbA_Paint;// generally: ... += methodName;
And you have to create the event itselve. For example:
void pbA_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
//do some cool stuff!
}
If it is painted on any of the PictureBoxes then this method will be called. If you want to know which PictureBox has been painted on then simply write:
void pbA_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
PictureBox picBox_active = sender as PictureBox;
//do some cool stuff!
}
And for making one single method to move just one PictureBox you could give the desired object as a parameter:
void move(PictureBox picBox, int moveX, int moveY)
{
picBox.Location = new Point(moveX, moveY);
}
And you can call this method by:
PictureBox picBoxTest = new PictureBox();
move(picBoxTest, 5, 5);
And to make it clearer with an example:
void pbA_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
PictureBox picBox_active = sender as PictureBox;
move(picBox_active, 5, 5);
}
The PictureBox that has been painted will be moved to the coordinates 5,5.

Drawn line isn't shown on a combobox

I need your help in following question (using .Net 3.5 and Windows Forms):
I just simply want to draw a line on a middle of a combobox (Windows Forms) that is situated on a form.
The code I use is:
void comboBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawLine(new Pen(Brushes.DarkBlue),
this.comboBox1.Location.X,
this.comboBox1.Location.Y + (this.comboBox1.Size.Height / 2),
this.comboBox1.Location.X + this.comboBox1.Size.Width,
this.comboBox1.Location.Y + (this.comboBox1.Size.Height / 2));
}
To fire a paint event:
private void button1_Click(object sender, EventArgs e)
{
comboBox1.Refresh();
}
When I execute the code and press button the line isn't drawn. In debug the breakpoint at the paint handler isn't being hit. The strange thing is that on MSDN there is a paint event in ComBox's events list, but in VS 2010 IntelliSense doesn't find such event in ComboBox's members
Thanks.
public Form1()
{
InitializeComponent();
comboBox1.DrawMode = DrawMode.OwnerDrawFixed;
comboBox1.DrawItem += new DrawItemEventHandler(comboBox1_DrawItem);
}
void comboBox1_DrawItem(object sender, DrawItemEventArgs e) {
e.DrawBackground();
e.Graphics.DrawLine(Pens.Black, new Point(e.Bounds.Left, e.Bounds.Bottom-1),
new Point(e.Bounds.Right, e.Bounds.Bottom-1));
TextRenderer.DrawText(e.Graphics, comboBox1.Items[e.Index].ToString(),
comboBox1.Font, e.Bounds, comboBox1.ForeColor, TextFormatFlags.Left);
e.DrawFocusRectangle();
}
Paint event will not fire.
What do you want is possible only when DropDownStyle == ComboBoxStyle.DropDownList:
comboBox1.DrawMode = DrawMode.OwnerDrawFixed;
comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
comboBox1.DrawItem += (sender, args) =>
{
var ordinate = args.Bounds.Top + args.Bounds.Height / 2;
args.Graphics.DrawLine(new Pen(Color.Red), new Point(args.Bounds.Left, ordinate),
new Point(args.Bounds.Right, ordinate));
};
This way you can draw selected item area yourself.

Obtaining the parameters of the winform form (Width & height)

I want to obtain the height and width properties of a winforms form to be able to color all of it?
I've tried this code..
private void Form1_Load(object sender, EventArgs e)
{
using (Graphics g = this.CreateGraphics())
{
Rectangle r=this.DisplayRectangle;
g.DrawRectangle(Pens.Black, new Rectangle(0, 0, r.X, r.Y));
}
}
But it doesn't do the job. How do I color the whole form in black with the graphics object and Rectangle object?
If you do like that, you will just be painting on the screen where the window happens to be. The window is not aware of that, and when the window is updated for any reason it will be redrawn without the color.
Use the Paint event to draw graphics on the window. Add an event handler for the event, and it will be called whenever the window has to be redrawn. The event arguments contains a Graphics object that you should use for drawing.
Use the Width and Height properties of the DisplayRectangle as width and height, not the X and Y properties. However, as the Graphics object is clipped to the area that is to be updated, you could just use the Clear method to fill it with a color.
I have two buttons on my form(in design view) button1_Click is to paint it black, and button2_Click is to paint form back to Control color.
public partial class Form2 : Form
{
private Brush brushToPaint;
public Form2()
{
InitializeComponent();
brushToPaint = SystemBrushes.Control;
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.FillRectangle(brushToPaint, this.DisplayRectangle);
}
private void button1_Click(object sender, EventArgs e)
{
brushToPaint = Brushes.Black;
InvokePaint(this, new PaintEventArgs(this.CreateGraphics(), this.DisplayRectangle));
}
private void button2_Click(object sender, EventArgs e)
{
brushToPaint = SystemBrushes.Control;
InvokePaint(this, new PaintEventArgs(this.CreateGraphics(), this.DisplayRectangle));
}
}
Do you have to do this using Graphics and DisplayRectangle?
The form has a property called BackColor, which you could simply set to black:
private void Form1_Load(object sender, EventArgs e)
{
this.BackColor = Color.Black;
}

Categories