Why does the Form_Paint event run continuously and only draw once ?
-
I have the following code, I put a label in Form_Paint to track the number jump, I see the label jumping continuously but e.Graphics.DrawString(...) only looks once, does anyone know why ?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//progressBar1.Visible = false;
progressBar1.Minimum = 0;
progressBar1.Maximum = 100;this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1\_Paint); } int iNum = 0; private void btnDrawText\_Click(object sender, EventArgs e) //PaintEventArgs e { progressBar1.Value = 0; progressBar1.Visible = true; this.timer1.Interval = 100; this.timer1.Enabled = true; } private void ShadowedTextPaint(PaintEventArgs e, int num) { using (Font font1 = new Font("Times New Roman", 250, FontStyle.Bold, GraphicsUnit.Pixel)) { PointF pointF1 = new PointF(310, 270); e.Graphics.DrawString(num.ToString(), font1, Brushes.LightGreen, pointF1); lblNum.Text = num.ToString(); } } private void Form1\_Paint(object sender, PaintEventArgs e) { ShadowedTextPaint(e, iNum); } private void timer1\_Tick(object sender, EventArgs e) { if (progressBar1.Value < 100) { Random rd = new Random(); iNum = rd.Next(0, 999); progressBar1.Value++; } else { this.timer1.Enabled = false; progressBar1.Visible = false; } }
}
-
I have the following code, I put a label in Form_Paint to track the number jump, I see the label jumping continuously but e.Graphics.DrawString(...) only looks once, does anyone know why ?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//progressBar1.Visible = false;
progressBar1.Minimum = 0;
progressBar1.Maximum = 100;this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1\_Paint); } int iNum = 0; private void btnDrawText\_Click(object sender, EventArgs e) //PaintEventArgs e { progressBar1.Value = 0; progressBar1.Visible = true; this.timer1.Interval = 100; this.timer1.Enabled = true; } private void ShadowedTextPaint(PaintEventArgs e, int num) { using (Font font1 = new Font("Times New Roman", 250, FontStyle.Bold, GraphicsUnit.Pixel)) { PointF pointF1 = new PointF(310, 270); e.Graphics.DrawString(num.ToString(), font1, Brushes.LightGreen, pointF1); lblNum.Text = num.ToString(); } } private void Form1\_Paint(object sender, PaintEventArgs e) { ShadowedTextPaint(e, iNum); } private void timer1\_Tick(object sender, EventArgs e) { if (progressBar1.Value < 100) { Random rd = new Random(); iNum = rd.Next(0, 999); progressBar1.Value++; } else { this.timer1.Enabled = false; progressBar1.Visible = false; } }
}
My first guess would be it's because you're setting the Text property of a Label control in your paint event, which will cause the label to Invalidate and require painting, which may be generating another WM_PAINT message for your form. Handle the paint event, but only do painting in it, not messing with other controls that have nothing to do with drawing content. Also, your in Tick event handler, the else clause of the If statement is unnecessary. The Timer control in the ToolBox does not need to be re-enabled on every tick, and the ProgressBar is always going to be visible since you never set it to not be visible. Your Random really shouldn't be recreated on every tick of the timer. You can just create a single instance as the class level and just keep using that. But, since you're not even using the random numbers you're getting, why even have it in there?
Asking questions is a skill CodeProject Forum Guidelines Google: C# How to debug code Seriously, go read these articles.
Dave Kreskowiak -
My first guess would be it's because you're setting the Text property of a Label control in your paint event, which will cause the label to Invalidate and require painting, which may be generating another WM_PAINT message for your form. Handle the paint event, but only do painting in it, not messing with other controls that have nothing to do with drawing content. Also, your in Tick event handler, the else clause of the If statement is unnecessary. The Timer control in the ToolBox does not need to be re-enabled on every tick, and the ProgressBar is always going to be visible since you never set it to not be visible. Your Random really shouldn't be recreated on every tick of the timer. You can just create a single instance as the class level and just keep using that. But, since you're not even using the random numbers you're getting, why even have it in there?
Asking questions is a skill CodeProject Forum Guidelines Google: C# How to debug code Seriously, go read these articles.
Dave KreskowiakThe Label Control I put in the Form_Paint event is for me to troubleshoot it without affecting or messing up the information in the Form_Paint event or argument, I verified this with the Debug.Print debugger ("..." ); My Random function gets a random number and the Tick event determines the time to stop redrawing, the ideas you give me are incorrect. What do you think is the use of Form_Paint to draw random numbers continuously over time ?
-
The Label Control I put in the Form_Paint event is for me to troubleshoot it without affecting or messing up the information in the Form_Paint event or argument, I verified this with the Debug.Print debugger ("..." ); My Random function gets a random number and the Tick event determines the time to stop redrawing, the ideas you give me are incorrect. What do you think is the use of Form_Paint to draw random numbers continuously over time ?
The Label control was a bad idea because it changes the behavior of your code. When you set the value of the Text property, the label does not get repainted at that time. It forces the label to Invalidate itself, telling Windows that it needs to repaint. Windows will get around to posting a WM_PAINT message to the applications message queue. When the UI thread finally goes back to idle, the queue will get processed and the paint message makes it way to the label control, telling it that it is now OK to paint itself. That is when the label actually changes on screen. Moving on, you never use the value of the Random so it's never being painted anywhere. Form_Paint is a bit much for this. I'd create a Control specifically for the purpose. This makes the code reusable and easily maintained. The control would have it's own Random, it's own Timer, and a couple of methods to Start and Stop it's behavior.
Asking questions is a skill CodeProject Forum Guidelines Google: C# How to debug code Seriously, go read these articles.
Dave Kreskowiak -
The Label control was a bad idea because it changes the behavior of your code. When you set the value of the Text property, the label does not get repainted at that time. It forces the label to Invalidate itself, telling Windows that it needs to repaint. Windows will get around to posting a WM_PAINT message to the applications message queue. When the UI thread finally goes back to idle, the queue will get processed and the paint message makes it way to the label control, telling it that it is now OK to paint itself. That is when the label actually changes on screen. Moving on, you never use the value of the Random so it's never being painted anywhere. Form_Paint is a bit much for this. I'd create a Control specifically for the purpose. This makes the code reusable and easily maintained. The control would have it's own Random, it's own Timer, and a couple of methods to Start and Stop it's behavior.
Asking questions is a skill CodeProject Forum Guidelines Google: C# How to debug code Seriously, go read these articles.
Dave KreskowiakI use the label control to debug the program instead of the Debug.Print("..."), I think the label control doesn't affect as you say. you say: "i never use the value of the Random so it's never being painted anywhere." What do I use to generate random numbers ? you say: "Form_Paint is a bit much for this. I'd create a Control specifically for the purpose ..." I haven't seen you create a Control specifically posted by you for everyone to see ?
-
I use the label control to debug the program instead of the Debug.Print("..."), I think the label control doesn't affect as you say. you say: "i never use the value of the Random so it's never being painted anywhere." What do I use to generate random numbers ? you say: "Form_Paint is a bit much for this. I'd create a Control specifically for the purpose ..." I haven't seen you create a Control specifically posted by you for everyone to see ?
Member 2458467 wrote:
I use the label control to debug the program instead of the Debug.Print("..."), I think the label control doesn't affect as you say.
Actually, it does work as I say, and it WILL lie to you when you have the UI thread tied up doing other things instead of letting it process the message pump so forms and controls can repaint themselves. Don't believe me? Start a new Windows form project and drop a label and a button on the form. Double click the button to create an event handler and drop the following code into the button handler:
for (int i = 1; i < 20000000; i++) label1.Text = i.ToString();
Run it and click the button. Notice the label doesn't update? Also, you can't move the form around the screen either. It's doing this because you've got the UI thread tied up doing a long-running operation. It's can't process messages, like WM_PAINT, until that operation completes.
Member 2458467 wrote:
you say: "i never use the value of the Random so it's never being painted anywhere." What do I use to generate random numbers ?
You use Random to generate the values, but you're not understanding how Random works. When you create a new instance of Random and do not supply it with a seed value, it will use the current timer value. Do this multiple times in a row quick enough, and each one of the Random instances will return the exact same value! Create a single class-level instance of Random and you can use it throughout the rest of your class code and not have to worry about consecutive instances returning the same values.
public class Form1 : Form { private Random RNG = new Random(); . . . private void SomeMethod() { ... int x = RNG.Next(10000); ... } }
In your code, you're getting the next random value and putting it in a variable, but then you never use that value in your paint code!
Member 2458467 wrote:
you say: "Form_Paint is a bit much for this. I'd create a Control specifically for the purpose ..." I haven't seen you create a Control specifically posted by you for everyone to see ?
Because I've got my own code to write that nobody is going to write for me and I'm not in the business of writing other peoples code for them. But, yeah, I wrote