I have made a draw method in a separate class to that of the form.
public class Object : Form1
{
public void Draw()
{
SolidBrush brush = new SolidBrush(Color.Yellow);
Graphics mapGraphics = this.CreateGraphics();
mapGraphics.FillEllipse(brush, new Rectangle(0, 0, 12, 12));
pacBrush.Dispose();
mapGraphics.Dispose();
}
}
There are no exceptions thrown, nor errors. I have tried to call the Draw method from the Form_Paint method, but nothing happens at all. How can I fix this?
Thanks
To draw into a window, you need to use the Graphics object for that window. Your method creates a new Graphics object, so it draws "somewhere else".
Pass the e.Graphics object that you have in your Form_Paint handler into the method as a parameter, and draw using that instead.
Related
I have the problem that I want to draw on a pictureBox with an image loaded before the user gets to see it. The drawing in principle works, but if I do it in the constructor it doesn't show up. It does work if I call the same function with a button.
public Form1()
{
InitializeComponent();
draw();
}
public void draw()
{
pictureBox1.Refresh();
Graphics g = pictureBox1.CreateGraphics();
Rectangle rect = new Rectangle(new Point(20, 20), new Size(40, 40));
rect.Offset(8, 8);
g.DrawEllipse(new Pen(Brushes.Black, 2), rect);
g.Dispose();
}
private void button1_Click(object sender, EventArgs e)
{
draw();
}
I would have assumed that the circle would show up when the Form loads but it only does when I press the button. The code itself gets executed, as tested with a Message box.
The control paints itself in its Paint event, so as soon as it's shown on screen (ie, after your code), it will paint itself in dull gray as normal.
If you want to custom paint a control, any control, you either override its OnPaint function or subscribe to its exposed Paint event.
A hint should be the fact that you had to create your own Graphics object, as opposed to using the object constructed during normal painting operations, that also includes proper clipping handling.
I have created a customized textbox which has border in red color. I then launch my application but this OnPaint never gets called.
My code is this:
public partial class UserControl1 : TextBox
{
public string disable, disableFlag;
public string Disable
{
get
{
return disable;
}
set
{
disable = value;
disableFlag = disable;
//OnPaint(PaintEventArgs.Empty);
}
}
public UserControl1()
{
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
this.Text = "testing 1";
if (disable == "true")
{
Pen redPen = new Pen(Color.Red);
Graphics graphics = this.CreateGraphics();
graphics.DrawRectangle(redPen, this.Location.X,
this.Location.Y, this.Width, this.Height);
// base.DrawFrame(e.Graphics);
}
}
}
Please let me know what is the problem (Here is the snapshot of the winform http://prntscr.com/ceq7x5 )?
You shouldn't create a new Graphics object. Use e.Graphics.DrawRectangle to be able to draw on the control using the already existing Graphics object like this:
Pen redPen = new Pen(Color.Red);
e.Graphics.DrawRectangle(redPen, this.Location.X,
this.Location.Y, this.Width, this.Height);
Also, to repeat my comment here about the Disabled flag. There's no point adding a custom Disable flag. Use the Enabled property that is already provided by the Windows Forms TextBox control.
Edit: Please notice that the above code doesn't work in TextBox's case, because it handles drawing differently. TextBox is basically just a wrapper around the native Win32 TextBox so you need to listen to quite a few messages that tell it to repaint itself. You also need to get the handle to the device context and transform it to a managed Graphics object to be able to draw.
Take a look at this article for code and explanations on how to draw on top of TextBox. Especially part 2. Drawing Onto the TextBox on the bottom of the page.
I played with some custom Controls created by me and I wanted to draw some Graphics for them.
I achieved everything I wanted but I have a question because something seems strange to me.
I tried for example to make a new control like this:
public class Square : Control
{
public Square(Point location)
{
this.Size = new Size(100, 100);
this.Location = location;
Draw();
}
public void Draw()
{
Graphics g = this.CreateGraphics();
g.DrawRectangle(Pens.Black, 5, 5, 20, 20);
}
}
This doesn't draw anything, but, if I call the "Draw" method from another action like a button press on the form it works.
It also works if I override the OnPaint method of my control and call the "Draw" method here. (I know that I should make all the drawing in the Paint/OnPaint but I did this just to try other things)
What's the difference ? Why can't I just call my "Draw" method anywhere I want?
When you call Draw() method in constructor, the control has not yet been added to the parent, is just an object in memory, so the call has no effect.
If you make the call as you say in the OnPaint() method, then is drawed since this method is called whenever render the control is needed.
I am trying to draw to a PictureBox from another function which is not the paint event!
Here is what it looks like:
public void Draw(ref PictureBox picture_box)
{
Graphics graphics = picture_box.CreateGraphics();
for (int i = 0; i < ship.Count; ++i)
{
if (ship[i].form == FORM.RECTANGLE)
{
graphics.FillRectangle(ship[i].color, ship[i].rectangle);
}
else if (ship[i].form == FORM.ELLIPSE)
{
graphics.FillEllipse(ship[i].color, ship[i].rectangle);
}
}
graphics.Dispose();
picture_box.Refresh();
}
(ship is a List of ship_part classes, which contain a Rectangle, a FORM enum (RECTANGLE, ELLIPSE) and a Brush)
I call Draw in the Form's constructor :
public Form1()
{
InitializeComponent();
spaceship ship;
ship_part part;
ship = new spaceship();
part = new ship_part(); //constructor initializes form to RECTANGLE and color to Brushes.Black
part.rectangle = new Rectangle(50, 50, 10, 10);
ship.ship.Add(part);
ship.Draw(ref pictureBox1);
}
The problem is that the Rectangle is not drawn.
What I have tried so far :
I thought there might be a problem with this line :
Graphics graphics = picture_box.CreateGraphics();
I think that I am not writing to the actual Graphics object that belongs to the PictureBox so I made my Draw function return the Graphics object that gets modified. Then I called the Draw function from the Picture Box Paint Event and tried to assign that Graphics object to the one that gets passed as parameter in the PaintEventArgs. But the PaintEvenArgs.Graphics object is read only.
Thanks!
I have a pictureBox on a Windows Form.
I do the following to load a PNG file into it.
Bitmap bm = (Bitmap)Image.FromFile("Image.PNG", true);
Bitmap tmp;
public Form1() {
InitializeComponent();
this.tmp = new Bitmap(bm.Width, bm.Height);
}
private void pictureBox1_Paint(object sender, PaintEventArgs e) {
e.Graphics.DrawImage(this.bm, new Rectangle(0, 0, tmp.Width, tmp.Height), 0, 0, tmp.Width, tmp.Height, GraphicsUnit.Pixel);
}
However, I need to draw things on the image and then have the result displayed again. Drawing rectangles can only be done via the Graphics class.
I'd need to draw the needed rectangles on the image, make it an instance of the Image class again and save that to this.bm
I can add a button that executes this.pictureBox1.Refresh();, forcing the pictureBox to be painted again, but I can't cast Graphics to Image. Because of that, I can't save the edits to the this.bm bitmap.
That's my problem, and I see no way out.
What you need to do is use the Graphics.FromImage method, which will allow you to draw directly on the image instead of the temporary Graphics object create from within the Paint method:
using (Graphics g = Graphics.FromImage(this.bm))
{
g.DrawRectangle(...);
}
Do this instead of (or in addition to) hooking the Paint method of the PictureBox. This way, you won't need to use a temporary image or Graphics object at all, and when you're finished modifying the original bitmap (this.bm) then you can invoke pictureBox1.Refresh to force the image to be re-displayed.