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);
}
}
Related
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.
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 :-)
After button click event I want the program to draw a rectangle inside a picturebox. I don't know how to do that. So far I made only a rectangle outside of picture box like this. Afterwards I want to implement a flood fill algorithm to fill the rectangle with a color. That's why I have to have those bitmaps there.
namespace howto_floodfill
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// The background image.
private Bitmap bm;
private Bitmap32 bm32;
// Make a rectangle
private void button1_Click(object sender, EventArgs e)
{
bm = new Bitmap(ClientSize.Width, ClientSize.Height);
using (Graphics gr = Graphics.FromImage(bm))
{
gr.Clear(Color.Silver);
gr.DrawRectangle(Pens.Black, 5, 5, 100, 60);
}
bm32 = new Bitmap32(bm);
this.BackgroundImage = bm;
}
}
}
You can set a Paint event handler for the PictureBox that will allow you to do drawing over the top of the PictureBox contents:
public partial class Form1 : Form
{
private bool _drawRectangle = false;
public Form1()
{
InitializeComponent();
pictureBox1.Paint += new PaintEventHandler(this.pictureBox1_Paint);
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (_drawRectangle) {
Graphics g = e.Graphics;
// use g to do your drawing
}
}
}
Just set _drawRectangle to true in your button click handler and call pictureBox1.Invalidate(). Doing your drawing in the Paint event handler guarantees that whenever the PictureBox is redrawn (say, because another window was over it), your rectangle gets drawn as well.
This will let you draw a rectangle over the PictureBox's contents. Rather than a flood fill algorithm, have you considered just using FillRectangle?
If you really want to do a flood fill, you'll have to work with an image as you're already doing, so you can read pixels from the image to know if a boundary has been reached. Then you could set the PictureBox's Image property with the resulting bitmap. (In this case, it wouldn't be necessary to do the graphics work in the Paint event handler, since the PictureBox will make sure its Image is drawn on every paint.)
You can use the control.CreateGraphics() method invoked from your picturebox.
namespace WindowsFormsApplication_Test
{
public partial class Form1 : Form
{
private Bitmap bm;
public Form1()
{
InitializeComponent();
bm = new Bitmap(pB.ClientRectangle.Width, pB.ClientRectangle.Height);
}
private void btn_Click(object sender, EventArgs e)
{
Graphics gF = pB.CreateGraphics();
gF.Clear(Color.Silver);
gF.DrawRectangle(Pens.Black, 5, 5, 100, 60);
}
private void button1_Click(object sender, EventArgs e)
{
Graphics gF = Graphics.FromImage(bm);
gF.Clear(Color.Silver);
gF.DrawRectangle(Pens.Black, 5, 5, 100, 60);
pB.Image = bm;
}
}
}
btn_click() is an example of getting the graphics context from the control and drawing directly.
Form prior to clicking...
Clicking the button will draw on the control directly - note that by default it gives you the clientRectangle portion of the control, which is nice...
Clicking on the button gives you this.
Now I resized the form.
Unfortunately, drawing on the form this way makes you responsible for redrawing your data any time the window is invalidated.
You can also just set the Image property of the form to be your private bitmap and then the framework handles redrawing for you. This is shown in the button1_Click() method.
You can still draw directly on the control if you wish, but you'll need to hook into the control events and redraw when the form does. For example, adding a flag as a private bool to the form class, overriding the OnPaint method, and adding code to your button event to swap the flag. Rather than duplicating the drawing code in the button event, you can just flip the flag and call this.Invalidate();
public partial class Form1 : Form
{
private Bitmap bm;
private bool bDrawn = false;
public Form1()
{
InitializeComponent();
bm = new Bitmap(pB.ClientRectangle.Width, pB.ClientRectangle.Height);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (bDrawn)
{
Graphics gF = pB.CreateGraphics();
gF.Clear(Color.Silver);
gF.DrawRectangle(Pens.Black, 5, 5, 100, 60);
}
}
private void btn_Click(object sender, EventArgs e)
{
//Graphics gF = pB.CreateGraphics();
//gF.Clear(Color.Silver);
///gF.DrawRectangle(Pens.Black, 5, 5, 100, 60);
bDrawn = true;
this.Invalidate();
}
Assign the created bitmap to the Image property of the picture box. Now you can draw whatever you want on the bitmap, and then manipulate it's data.
namespace howto_floodfill {
public partial class Form1 : Form {
private Bitmap bitmap;
public Form1() {
InitializeComponent();
this.bitmap = new Bitmap(100, 100);
this.pictureBox1.Image = this.bitmap;
}
// Make a rectangle
private void button1_Click(object sender, EventArgs e) {
if (this.bitmap != null) {
this.bitmap.Dispose();
}
this.bitmap = new Bitmap(ClientSize.Width, ClientSize.Height);
using (Graphics gr = Graphics.FromImage(bitmap)) {
gr.Clear(Color.Silver);
gr.DrawRectangle(Pens.Black, 5, 5, 100, 60);
}
this.pictureBox1.Image = this.bitmap;
}
}
}
Note that you may not need to re-create the bitmap each time if it has a fixed size.
So this should be very simple but I have looked at some similar questions and can't find an answer.
I have a Form1 class and a Resistor class. Inside the Form1 class I have a Panel(I changed the name to Canvas), inside the Canvas_Paint method I am calling the method Draw from the Resistor class but is not drawing anything.
Form1 Class:
public partial class Form1 : Form
{
static float lineWidth = 2.0F;
static float backgroundLineWidth = 2.0F;
static Pen pen = new Pen(Color.Yellow, lineWidth);
static Pen backgroundPen = new Pen(Color.LightGray, backgroundLineWidth);
private bool drawBackground = true;
private List<Resistor> resistors = new List<Resistor>();
public Form1()
{
InitializeComponent();
}
private void Canvas_Paint(object sender, PaintEventArgs e)
{
if (drawBackground)
{
Console.WriteLine("Drawing background...");
Draw_Background(e.Graphics, backgroundPen);
}
if (resistors != null)
{
foreach (Resistor r in resistors)
{
//This does not work.
r.Draw(e.Graphics);
}
}
//The line below draws the line fine.
e.Graphics.DrawLine(pen, 0, 0, 100, 100);
}
private void Draw_Background(Graphics g, Pen pen)
{
for (int i = 0; i < Canvas.Width; i += 10)
{
g.DrawLine(pen, new Point(i, 0), new Point(i, Canvas.Height));
}
for (int j = 0; j < Canvas.Height; j += 10)
{
g.DrawLine(pen, new Point(0, j), new Point(Canvas.Width, j));
}
drawBackground = false;
}
private void AddResistor_Click(object sender, EventArgs e)
{
resistors.Add(new Resistor());
Console.WriteLine("Added a Resistor...");
}
}
Resistor Class:
public class Resistor
{
static private Point startingPoint;
static Pen defaultPen;
private Point[] points;
public Resistor()
{
startingPoint.X = 100;
startingPoint.Y = 100;
defaultPen = new Pen(Color.Yellow, 2.0F);
points = new Point[] {
new Point( 10, 10),
new Point( 10, 100),
new Point(200, 50),
new Point(250, 300)
};
}
public void Draw(Graphics g)
{
//Is this drawing somewhere else?
g.DrawLines(defaultPen, points);
}
}
I have looked at this question which suggests to pass the e.Graphics object in this case to the Draw method in the Resistor class but is not working.
I am new to C# so I would really appreciate any help.
EDIT :
I put the project on github if you want to download and try it out.
EDIT :
So the problem was that after clicking the button the panel Paint method was not being called. The solution was to add Canvas.Invalidate inside the AddResistor_Click method
Run your code in the debugger and put a breakpoint in your event handler and you'll be able to check that your code is actually trying to draw something. If not, then is your event handler ever called? is there anything in your list of resistors? If it is drawing but you don't see anything, then you're not using the correct Graphics context or you're not drawing things in the visible part of your control, or you're drawing over things with subsequent drawing code.
The problem was that when the button was clicked the panel's paint method was not getting called because I tough that the paint method was always getting called. The solution was to add Canvas.Invalidate inside the AddResistor_Click method.
private void AddResistor_Click(object sender, EventArgs e)
{
resistors.Add(new Resistor());
Console.WriteLine("Added a Resistor...");
Canvas.Invalidate();
}
I am extremely new to c# and I have a simple question:
I am supposed to draw a white particle (rectangle) on a black background and move it horizontally from one of the screen to another.
I did it but the problem is it blinks too much (i.e. it is not smooth even when the speed is high, I can easily see the black background between each move and another)
t.Interval = 1000 / speed;
t.Tick += new EventHandler(t_Tick);
t.Start();
....
void t_Tick(object sender, EventArgs e)
{
//g.Clear(Color.Black);
g.DrawRectangle(new Pen(Brushes.Black, 20), r); //draw a black rectangle in the old position...20 is the thickness of the pen
r.X += move_x;
g.DrawRectangle(new Pen(Brushes.White, 20), r); //draw a white rectangle in the new position...20 is the thickness of the pen
if (r.X >= 1700) ///this means it reached the end of the screen
t.Stop();
}
I used g.Clear to clear the graphics but this also did not work, so I drew a black rectangle in the old position before moving it to the new position.
Any Idea how to remove this blinking or even do it in another way?
Try this out...add a Panel (panel1) to a form:
public partial class Form1 : Form
{
private Rectangle r;
private const int rSize = 50;
private const int move_x = 10;
private System.Windows.Forms.Timer tmr;
public Form1()
{
InitializeComponent();
panel1.BackColor = Color.Black;
r = new Rectangle(0, panel1.Height / 2 - rSize / 2, rSize, rSize);
tmr = new System.Windows.Forms.Timer();
tmr.Interval = 50;
tmr.Tick += new EventHandler(tmr_Tick);
tmr.Start();
panel1.Paint += new PaintEventHandler(panel1_Paint);
}
void tmr_Tick(object sender, EventArgs e)
{
r.X += move_x;
panel1.Refresh();
if (r.X > panel1.Width)
{
tmr.Stop();
MessageBox.Show("Done");
}
}
void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawRectangle(Pens.White, r);
}
}