It is as simple as it sounds I need to draw a rectangle but no matter what I do I cant seem to get it to work. This is done on a windows form and all I want is to output one rectangle, I managed to do this at school but now at home it doesn't work.
using System.Drawing;
namespace Rectanglr
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void FormPaint(object sender, PaintEventArgs e)
{
Pen pen = new Pen(Color.Red, 3);
Rectangle rect = new Rectangle(0, 0, 100, 100);
e.Graphics.DrawRectangle(pen, rect);
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
any help would be greatly appreciated.
You can try overriding the OnPaint method of your form:
This code should do the trick:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (Pen pen = new Pen(Color.Red))
{
Rectangle rect = new Rectangle(0, 0, 100, 100);
e.Graphics.DrawRectangle(pen, rect);
}
}
}
It's also recommended to wrap it with a using block to ensure that the Pen resource will be properly disposed of when you are finished drawing.
Here's a project that I set up to draw a rectangle:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
using (Pen pen = new Pen(Color.Red, 3))
{
Rectangle rect = new Rectangle(0, 0, 100, 100);
e.Graphics.DrawRectangle(pen, rect);
}
}
}
The important part to recognize here is the partial keyword. That's a hint that there is a second file, or maybe more, that defines this class. In this case, it's the designer file - Form1.Designer.cs.
If I look in the designer I can see this line:
this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
That's the magic that makes sure this works. Without it the event isn't wired up.
Now, having said that, events are usually used by external classes to your form. The preferred approach to modify the Paint method is to override it.
That looks like this:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (Pen pen = new Pen(Color.Red, 3))
{
Rectangle rect = new Rectangle(0, 0, 100, 100);
e.Graphics.DrawRectangle(pen, rect);
}
}
There's no need to wire this up as an event handler.
As a sidenote, please make sure you dispose every disposable in your code. A Pen is disposable and the using statement does the disposing for you.
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 :-)
I am using BufferedGraphics to redraw my form. I wish to redraw the form's controls all by myself, so I can draw lines wherever I want while I can still use the Form Designer to align my controls.
I've tried SuspendLayout but it make no use here.
Code:
using System;
using System.Drawing;
using System.Windows.Forms;
public partial class Form1 : Form
{
BufferedGraphicsContext context;
BufferedGraphics grafx;
PictureBox pic1, pic2;
public Form1()
{
SetStyle((ControlStyles)(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint), true);
InitializeComponent();
//Add picturebox
pic1 = new PictureBox();
pic1.BackColor = Color.Black;
pic1.SetBounds(50, 50, 100, 50);
Controls.Add(pic1);
pic2 = new PictureBox();
pic2.BackColor = Color.Gray;
pic2.SetBounds(75, 50, 50, 100);
Controls.Add(pic2);
}
private void Form1_Load(object sender, EventArgs e)
{
context = BufferedGraphicsManager.Current;
context.MaximumBuffer = new Size(Width, Height);
grafx = context.Allocate(CreateGraphics(), new Rectangle(0, 0, Width, Height));
}
public override void Refresh() { }
protected override void OnPaintBackground(PaintEventArgs e) { }
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = grafx.Graphics;
g.Clear(BackColor);
Bitmap bmp = new Bitmap(Width, Height);
foreach (Control c in Controls)
c.DrawToBitmap(bmp, new Rectangle(c.Left, c.Top, c.Width, c.Height));
g.DrawImage(bmp, 0, 0);
g.DrawLine(new Pen(Color.Red, 4), 0, 0, ClientSize.Width, ClientSize.Height);
grafx.Render(Graphics.FromHwnd(Handle));
}
private void Form1_Resize(object sender, EventArgs e)
{
context.MaximumBuffer = new Size(this.Width, this.Height);
if (grafx != null)
{
grafx.Dispose();
grafx = null;
}
grafx = context.Allocate(this.CreateGraphics(), new Rectangle(0, 0, Width, Height));
base.Refresh();
}
}
I need the line to be drawn at the top of the controls (picturebox), but the code turns out to be drawn below the controls.
I want to be able to draw Graphics to the Form Window instead of a picturebox. But it doesn't seem that the form window captures the mousemove event.
namespace CollisionTest
{
public partial class Form1 : Form
{
private Graphics paper;
private Pen pen;
public Form1()
{
InitializeComponent();
//paper = pictureBox1.CreateGraphics();
paper = this.CreateGraphics();
pen = new Pen(Color.Blue);
pen.Width = 5;
this.MouseMove += new System.Windows.Forms.MouseEventHandler(Form1_MouseMove);
}
private void Form1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
paper.Clear(Form1.ActiveForm.BackColor);
paper.DrawRectangle(pen, e.X + 10, this.Height - 20, 50, 10);
}
}
}
paper.Clear method Clears the entire drawing surface and fills it with the specified background color.
so when you move your mouse you first clear the graphic object and draw something so you cant see anything.
test with removing :
paper.Clear(Form1.ActiveForm.BackColor);
from your code
Looks like you want a "pong paddle" going across the bottom of your form?
Just change this.Height to this.ClientRectangle.Height:
public partial class Form1 : Form
{
private Pen pen;
private Graphics paper;
public Form1()
{
InitializeComponent();
pen = new Pen(Color.Blue, 5);
paper = this.CreateGraphics();
this.MouseMove += new System.Windows.Forms.MouseEventHandler(Form1_MouseMove);
}
private void Form1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
paper.Clear(this.BackColor);
paper.DrawRectangle(pen, e.X + 10, this.ClientRectangle.Height - 20, 50, 10);
}
}
I want to customize ToolStripMenuItem by overriding OnPaint function. This is a MyToolStripMenuItem:
public class MyToolStripMenuItem : ToolStripMenuItem
{
public MyToolStripMenuItem()
:base()
{
}
public MyToolStripMenuItem(string t)
:base(t)
{
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
Rectangle r = this.Bounds;
g.FillRectangle(Brushes.Blue, r);
g.DrawString(this.Text, this.Font, Brushes.Red, r);
}
}
In my code, I will fill a blue color in item's bound. Now, I will create a list of items on menustrip:
MyToolStripMenuItem1
|___MyToolStripMenuItem2
|___MyToolStripMenuItem3
I don't know why MyToolStripMenuItem3 don't have a blue background.
This is my source code:
http://www.mediafire.com/?2qhmjzzfzzn
Please help me. Thanks.
It's not the way it is done with a ToolStripMenuItem. You give the MenuStrip a custom renderer. For example:
For example:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
menuStrip1.Renderer = new MyRenderer();
}
private class MyRenderer : ToolStripProfessionalRenderer {
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) {
if (!e.Item.Selected) base.OnRenderMenuItemBackground(e);
else {
Rectangle rc = new Rectangle(Point.Empty, e.Item.Size);
e.Graphics.FillRectangle(Brushes.Beige, rc);
e.Graphics.DrawRectangle(Pens.Black, 1, 0, rc.Width - 2, rc.Height - 1);
}
}
}
}
The problem with using OnRenderMenuItemBackground() is that it applies to the whole menu and not just the one ToolStripMenuItem.
The error in the code lies in Rectangle r = this.Bounds; which produces the wrong area. Change this to Rectangle r = e.ClipRectangle and it should work ok. (For some reason the Bounds has the wrong Y component).