redrawing code in C# - c#

i am creating a drawing programe which Suppose to take the parameters from the user
(Radius,height,width,....etc)
i have created a class with one paramter (radius)
public int faceoutline(int r)
{
Graphic = pictureBox1.CreateGraphics();
Graphic.DrawEllipse(myPen, 0, 0, r, r);
return r;
}
then i call it :
private void button1_Click(object sender, EventArgs e)
{
faceoutline(int.Parse(textBox1.Text));
pictureBox1.Invalidate();
}
....and nothing happens
i copied the button code to a timer but it keep balnking
WHAT I AM DOING WRONG ?!

You should place the drawing code in the Paint event handler of the PictureBox, and use the Graphics provided in the event args. This way, your custom drawing code will be executed every time the control is redrawn.
If you don't do it this way, anything you draw will disappear the next time the control is redrawn. In your code, you call Invalidate right after you draw your ellipse, so the control is redrawn without the ellipse...

Related

Refreshing image on panel creates infinite loop (C# - Winforms)

I'm having a problem with refreshing graphics on panels and forms.
When I draw the image it works fine but when I want to replace it with another image using Panel.Refresh it makes the event handler auto activate itself without end. If I use Panel.Update it will just draw the second image onto the first. A lot of people recommended that I use the Invalidate method but that has the same infinite loop problem.
Bitmap bitmap = new Bitmap(Resources.Image1);
private void panel1_Paint(object sender, PaintEventArgs e)
{
if (parameter == 0) { bitmap = new Bitmap(Resources.Image1); }
if (parameter >= 2) { bitmap = new Bitmap(Resources.Image2); }
e.Graphics.DrawImage(bitmap, 60, 10);
panel1.Refresh();
}
panel1.Refresh();
Causes the paint event to trigger. I put the refresh code where the parameter value is changed.

C# Draw Line OnPaint() vs CreateGraphics()

Question:
How do you properly draw on a winform from a method other than the OnPaint() method?
Additional Information:
The code I have now draws some background lines for a TicTacToe game in the OnPaint() method. Then I use the Mouse_Click event and am running this code which apparently is not proper:
private void TicTacToe_MouseClick(object sender, MouseEventArgs e)
Graphics g = this.CreateGraphics();
g.DrawEllipse(this.penRed, this.Rectangle);
For reasons I do not understand, it does draw the circle, but when minimizing or moving the form off screen it erases the circles but not the lines from the OnPaint() method.
You are doing a lot of "view" but no "model".
When you want to create a shape, when the mouse button goes down/up, create some DATA representing the shape.
Your data structures represent the persistent information (it is the data that allows you to save and load this information between sessions).
All your paint function needs to do is look at the DATA structures and paint it. This will therefore persist between sizing/hiding/showing.
The problem is that Windows windows (that includes WinForms) have no graphical memory of their own unless their creator provides such memory and it is only a matter of time before that particular window wilk get overwritten or hidden and eventually need to be repainted. You're painting to the screen ( you might say ) and others can do the same. The only convention you can rely on is that the OnPaint will get called when needed. Basically it's alright to use your philosophy and draw whenever you need to (not on some misterious and unpredictable schedule). For that check out my solution.
You should use a "backbuffer bitmap" like:
private Bitmap bb;
protected override void OnResize(EventArgs e) {
this.bb = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
this.InitBackBuffer();
}
private void InitBackBuffer() {
using (var g = Graphics.FromImage(this.bb)) {
// do any of the "non dissapearing line" drawing here
}
}
private void TicTacToe_MouseClick(object sender, MouseEventArgs e)
using (Graphics g = Graphics.FromImage(this.bb))
g.DrawEllipse(this.penRed, this.Rectangle);
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
e.Graphics.DrawImageUnscaled(this.bb);
}
Try that. That should do it :)
What you are doing is drawing on the form "asynchronously" (from the OnPaint method). You see, the OnPaint method is what Windows Forms relies on to draw your entire form. When something happens to your From, it is invalidated and OnPaint is called again. If something isn't drawn in that method, then it will not be there after that happens.
If you want a button to trigger something to appear permanently then what you need to do is Add that object to a collection somewhere, or set a variable related to it. Then call Refresh() which calls Invalidate() and Update() Then, during OnPaint, draw that object (ellipis).
If you want it to still be there after something happens to your form, such as minimize, you have to draw it during OnPaint.
Here's my suggestion:
public partial class Form1 : Form
{
Rectangle r = Rectangle.Empty;
Pen redPen = new Pen(Color.Red);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
r = new Rectangle(50, 50, 100, 100);
Refresh();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (r != Rectangle.Empty)
{
e.Graphics.DrawRectangle(redPen, r);
}
}
}

C# - Code in form constructor not executed

Relatively new to C#; hopefully I'm just overlooking something simple.
I have a form named 'Exercise1' which contains a picture box called 'drawingArea' and a few buttons. The code for the constructor of Exercise1 is as follows:
public Exercise1()
{
InitializeComponent();
paper = drawingArea.CreateGraphics();
balloon = new Balloon("redBalloon", Color.Red, drawingArea.Width / 2,
drawingArea.Height / 2, 30);
paper.Clear(Color.White);
balloon.Display(paper);
}
...
'paper' and 'balloon' are created as globals above the constructor for use in the other methods on the form. Both 'paper' and 'balloon' work as initialized in the constructor in the other methods defined on the form.
For whatever reason, the commands
paper.Clear(Color.White);
and
balloon.Display(paper);
Which should clear the picture box and show a red ellipse, don't execute (at least visibly). What gives?
UPDATE:
Think I'm going to like this website... You guys are quick!
#Nitesh: The constructor for Exercise1 is called from another form. Code is as follows:
private void button1_Click(object sender, EventArgs e)
{
int exSelector = (int)numericUpDown1.Value;
switch (exSelector)
{
case 1:
Exercise1 form1 = new Exercise1();
form1.Show();
break;
...
#Sean Dunford: Yes and yes it is.
#RBarryYoung: Was playing around with that a bit, but had no luck. What command triggers a Form_Load event for Exercise1?
UPDATE: This altered code works as expected:
public Exercise1()
{
InitializeComponent();
paper = drawingArea.CreateGraphics();
drawingArea.BackColor = Color.White;
drawingArea.Paint += new PaintEventHandler(this.drawingArea_Paint);
balloon = new Balloon("redBalloon", Color.Red, drawingArea.Width / 2, drawingArea.Height / 2, 30);
}
private void drawingArea_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.White);
balloon.Display(e.Graphics);
}
...
Thanks for all the help!
You cannot do drawing in the constructor. To do proper drawing, you need to have the form shown on the screen. You can try using the Shown event to do your rendering (this may get lost when the form is redrawn, though).
Usually the best way is to set whatever flags you need in the constructor and then use the Paint event of the form to do all painting. Later on, when you need to repaint something, set up whatever state needs to be rendered, invalidate your form (this results in a Paint event) and then you can repaint the new state.
If you try to do customized drawing (outside your Paint event) you'll run the risk of things randomly going blank or your drawing may disapper when you resize/minimize your form.
You use Graphics in a constructor, that means that you draw on the paper only once, any redraw for whatever reason that happens after constructor will draw the drawingArea in its original way. Try to add PaintEventHandler to drawingArea and then call inside balloon.Display(e.Graphics);
public Exercise1()
{
InitializeComponent();
balloon = new Balloon("redBalloon", Color.Red, drawingArea.Width / 2,
drawingArea.Height / 2, 30);
drawingArea.Paint += new PaintEventHandler(drawingArea_Paint);
}
void drawingArea_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.White);
baloon.Display(e.Graphics);
}
You should be overriding the forms OnPaint event handler. In doing so, you are able to get the graphics context which will redraw your paper and balloon areas.

Invisible controls drawing over graphic object

I have a method where I disable or enable some custom controls and then use a graphics object to draw lines and rectangles.
The gist of the method:
void MyMethod()
{
//...
mycontrol.enabled = false;
mycontrol.visible = false;
mycontrol.Invalidate();
mycontrol.Update();
GraphicsObject.DrawLines();
//...
}
Right after this method returns, the screen looks great. I have rectangles and lines where controls used to be.
However, after the click event handler returns (which called the above method). The controls which should be invisible draw over the lines and rectangles (leaving those area's blank - the same color as the background form).
Is there any way to fix this?
Thanks
As I mentioned in my comment if you are drawing on an object if you do not use the OnPaint Method or the Paint Event your custom drawing will not be automatically redrawn. Depending on what you are drawing on you can do something like( I am assuming you are drawing on a Form).
void MyMethod()
{
//...
mycontrol.enabled = false;
mycontrol.visible = false;
mycontrol.Invalidate();
mycontrol.Update();
this.Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
//Conditional Logic to determine what you are drawing
// myPoints is a Point array that you fill elsewhere in your program
e.Graphics.DrawLines(new Pen(Brushes.Red), myPoints);
}

Draw an image out of a control

I have a control. It's a text box. I want to draw an image at the left of the control. The image should be painted outside the control. I could paint it one but inside.
Here is the code:
private static Image requiredIcon = Resources.Icon_required;
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (base.Enabled && string.IsNullOrEmpty(base.Text))
{
e.Graphics.DrawImage(requiredIcon, 0, 0);
}
}
Instead of drawing the image, you could create an appropriate control, e.g. PictureBox, with it's Image property set to the appropriate image resource.
It may be easier to do this at design time rather than run time. If the image should not be shown intitially, set it's Visible property to false at design time and set it to true at run time when the image should be shown.
Create a user control composed of a TextBox and a PictureBox. Then in the OnPaint event of your user control you will be able to draw outside the textbox (in the PictureBox control).
Here's a picture of what the UserControl could look like. It contains a PictureBox and a TextBox.
If you just want to draw an icon you just have to assigned it to the PictureBox. So the OnPaint may not be necessary in your case.
Instead of overloading the TextBox.OnPaint method, you have to overload the Form's (or whatever is the parent component of the TextBox) OnPaint method, and paint the Image at the left hand side of the TextBox. You can't have the TextBox draw to an area outside its own bounds.
I can get a parent and use it for painting.
protected override void OnParentChanged(EventArgs e)
{
base.OnParentChanged(e);
base.Parent.Paint += new PaintEventHandler(Parent_Paint);
}
private void Parent_Paint(object sender, PaintEventArgs e)
{
if (base.Enabled && string.IsNullOrEmpty(base.Text))
{
e.Graphics.DrawImage(requiredIcon, 0, 0);
}
}

Categories

Resources