i tried to draw some boxes right after form is Initialized
however they didn't appeared.
i put the code under the InitializeComponent();
like this
public Form2()
{ InitializeComponent();
System.Drawing.SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.LimeGreen);
System.Drawing.Graphics formGraphics = this.CreateGraphics();
formGraphics.FillRectangle(myBrush, new Rectangle(0, 0, 200, 300)); }
but when i drew them after the form is initialized they worked!
So i thought i should wait a moment and draw the boxes.
Then i put the thread to make the draw function wait for 10ms
In short i modified the code like this
public Form2()
{
InitializeComponent();
Thread t1 = new Thread(new ThreadStart(Run));
t1.Start();
}
void Run()
{
Thread.Sleep(10);
System.Drawing.SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.LimeGreen);
System.Drawing.Graphics formGraphics = this.CreateGraphics();
formGraphics.FillRectangle(myBrush, new Rectangle(0, 0, 200, 300));
}
and i succeed
So my question is why i have to wait for a moment to draw something right after the form is initialized?
and is there any way to solve this problem not using thread?
I find your question interesting and did some experiments myself. I managed to get it to work in Form1_Paint callback :)
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
System.Drawing.SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.LimeGreen);
System.Drawing.Graphics formGraphics = e.Graphics; //this.CreateGraphics();
formGraphics.FillRectangle(myBrush, new Rectangle(0, 0, 200, 300));
}
}
Edit: Edited based on Idle_Mind's comment
using paint event works
plus don't use CreateGraphics instead use e.Graphics
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.
I'm trying to call a method which draws something in a panel from another class, but something doesn't work.
This is the drawing method:
class Dibujo
{
public void Dibujar(Object sender, PaintEventArgs e)
{
Form2 ventana2 = new Form2();
Graphics g = ventana2.panel1.CreateGraphics();
Pen Boli = new Pen(Brushes.Green);
Point Inicio = new Point(200, 100);
Point Final = new Point(400, 300);
g.DrawLine(Boli, Inicio, Final);
}
}
}
And here is were I call it:
private void btnDibujar_Click(object sender, EventArgs e){
Graphics g = panel1.CreateGraphics();
Rectangle rect = new Rectangle();
PaintEventArgs pe = new PaintEventArgs(g,rect);
Pen Boli = new Pen(Brushes.Red);
g.DrawLine(Boli,100,100,100,300);
Dibujo panel = new Dibujo();
panel.Dibujar(sender,pe);
}
So the idea is that when I click the button btnDibujar_click a simple line is drawn in the panel but it doesn't work. I know that the code probably has a lot of mistakes but I'm a beginner and I'm learning by myself so all kinds of advice is welcome.
After seeing that drawing to the desktop is extremely messy, I decided just to research around. I figured out that many people suggest creating a transparent WinForm that is the size of the screen and smacking a panel on there and using that to draw graphics. So I tested it out but ran into many errors. At first, my second form (Form2) wouldn't show, so I had to put it into another thread and put Form2.ShowDialog(); on that thread. After I got that problem out of the way, I actually drew to the panel. Now my form will never show, but I can see it running on my taskbar. Everytime I try to make it the focused window, it never works, and whenever I hover the task I can see the graphics being created. My question is, is it possible to draw to a panel on a transparent WinForm and make it visible? Here's the code I used, it's mostly for looking for errors (drawing the states and stuff).
void Draw()
{
while (true)
{
SolidBrush redpen = new SolidBrush(Color.Red);
Font font = new Font("Arial", 16);
PointF point = new PointF(700, 150);
Graphics g = panel1.CreateGraphics();
g.DrawString(Main.state.ToString(), font, redpen, point);
Main.beginTime.Stop();
Main.TimeRan = Main.beginTime.Elapsed;
string amountOfTime = string.Format("{0:00}:{1:00}:{2:00}.{3:00}", Main.TimeRan.Hours, Main.TimeRan.Minutes, Main.TimeRan.Seconds, Main.TimeRan.Milliseconds / 10);
point = new PointF(700, 200);
g.DrawString(amountOfTime, font, redpen, point);
Thread.Sleep(10);
panel1.Refresh();
}
}
private void Form2_Shown(object sender, EventArgs e)
{
Draw();
}
Somewhere in my main class
// In a method
Thread F2T = new Thread(FormHandlers);
F2T.Start();
private void FormHandlers()
{
Form2 Form2 = new Form2();
Form2.Opacity = 0.00;
Form2.ShowDialog();
}
Edit: After some testing, I noticed that with the decrease of opacity the letter's opacity decreases as well, can I make it so the panel is transparent but the string I'm drawing to draw inside of it is not?
I guess you want to draw a message on a transparent child form? if that, I think you could do as follow: because the form.Opacity =0.00 makes all the controls in it be transparent, so we can't see anything. Another way, we use form.TransparencyKey to get that. code like this:
public Form2()
{
InitializeComponent();
//hide the border of form
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.BackColor = Color.White;
//set the TransparencyKey the same as the back color
this.TransparencyKey = this.BackColor;
}
protected override void OnPaint(PaintEventArgs e)
{
SolidBrush redpen = new SolidBrush(Color.Red);
Font font = new Font("Arial", 16);
PointF point = new PointF(400, 150);
Graphics g = e.Graphics;
string state = "running";
g.DrawString(state, font, redpen, point);
string amountOfTime = string.Format("{0:00}:{1:00}:{2:00}.{3:00}", 1, 2, 3, 11111 / 10);
PointF point2 = new PointF(500, 150);
g.DrawString(amountOfTime, font, redpen, point2);
//base.OnPaint(e);
}
by the way, you want to show message in a child form, I don't prefer to use multi-threading, you just invoke the Form2 in Show() not in ShowDialog(), and set Form2.TopMost=True, than you can operate your main form as well. try it.
my result is bellow:
Im trying to draw a graphic on a form upon form startup. I've tried putting the graphic components inside the form constructer, but i cannot seem to get it working. This is what i've got so far.
public partial class Form3 : Form
{
public Form3()
{
System.Drawing.Graphics graphics = this.CreateGraphics();
System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle(100, 100, 200, 200);
graphics.DrawEllipse(System.Drawing.Pens.Black, rectangle);
graphics.DrawRectangle(System.Drawing.Pens.Red, rectangle);
}
}
Any and all help will be awesome,
Thanks guys
One solution would be to use a Bitmap, e.g.
Bitmap b = new Bitmap(this.Width, this.Height);
Graphics g = Graphics.FromImage(b);
... // Draw
this.BackgroundImage = b;
Otherwise, you'll need to handle the Paint event, whereat you can draw directly to the graphics context each time the form is invalidated. e.g.
this.Paint += Form1_Paint;
...
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle(100, 100, 200, 200);
g.DrawEllipse(System.Drawing.Pens.Black, rectangle);
g.DrawRectangle(System.Drawing.Pens.Red, rectangle);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle(100, 100, 200, 200);
e.Graphics.DrawEllipse(System.Drawing.Pens.Black, rectangle);
e.Graphics.DrawRectangle(System.Drawing.Pens.Red, rectangle);
}
im having some problems... code is below:
delegate void SetCanvasDelegate(PictureBox canvas);
public void SetCanvas(PictureBox canvas)
{
if (this.canvas.InvokeRequired)
this.canvas.Invoke(new SetCanvasDelegate(SetCanvas), new object[] { canvas });
else
this.canvas = canvas;
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
PictureBox canvas = new PictureBox();
Graphics g = Graphics.FromHwnd(canvas.Handle);
RadarElement player = new RadarElement(new Point(150, 150), RadarElementType.Player);
List<Enemy> enemies = new List<Enemy>();
ores.Add(new Enemy(new Point(100, 100)));
g.DrawLine(new Pen(Color.Black), new Point(0, 0), new Point(100, 100));
if (trackEnemies.Checked)
foreach (Enemy e in enemies)
g.DrawImage(Image.FromFile("enemy.png"), e.Position);
SetCanvas(canvas);
Thread.Sleep(500);
}
}
this.canvas is the PictureBox in my Form1.
All of this is within my Form1 class... but the pictureBox in my form is not updated to show enemy.png as above in the code. What is wrong and how do i correct it?
Looks like you're trying to replace the PictureBox of your form with one that's being created within your bw_DoWork method. This won't work the way you expect it to. You need to do your painting on an image object and then stick that painted image into your form's picturebox. If it still doesn't show, use Invalidate as Daren Thomas suggested.
You probably need to do something along the lines of
Bitmap canvas = new Bitmap(width, height);
using(Graphics g = Graphics.FromImage(canvas))
{
// paint here
}
SetCanvas(canvas);
and then modify your SetCanvas method accordingly to accept an Image instead of a PictureBox.
Did you Invalidate the pictureBox?