?
Solved

Trouble Updating Controls From Within a While Loop

Posted on 2004-08-12
3
Medium Priority
?
161 Views
Last Modified: 2010-04-15
I've written a function that is supposed to update a listbox and a label every time I iterate through a while loop. For some reason, the controls are not being updated. However, when I terminate the loop prematurely (with a return statement) both controls update correctly.

Is this typical behavior for a while loop, or is there something odd going on with the controls?
0
Comment
Question by:nh_capricorn
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
3 Comments
 
LVL 2

Expert Comment

by:davidastle
ID: 11790277
To make a long story short, it has to with windows.  To force your controls to be shown as they truly are, call the Update() function on your window or on a control.

The weird behavior has to do with the way windows works.

Your application knows when to redraw itself because windows will send it a message called WM_PAINT.  The caveat is that windows will only send this message if your messages queue is empty, and when you are constantly changing controls in a while loop, your message queue is never empty.

It does not have to with while loops.   Lets say that you have an infinite loop that starts when you click on your window and updates your textbox.  To test to see if its doing anything, lets make it do something more than just update the text data.
Make sure your project properties are set so to console application to follow my code.

while (true)
{
    myTextBox.Text += "Foo";
    Console.WriteLine(myTextBox.Text);
}

If you run this, you will see that your text box data is in fact getting updated.  The reason why it is not displaying is because of windows!  Microsoft is not sending you WM_PAINT messages.  To prove this, lets track all the windows messages that are sent your app.  Make a new windows form project, and set it to console application.  Now, create a new class below your form class called MyFilter and make it inherit IMessageFilter.  This will be used to track the windows messages that are passed to your window.  Next, you have to add the filter when the application loads.  Here is an example that will start your loop when you click the mouse button.  It will show all the windows messages past in a console window:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace WindowsApplication1
{
      /// <summary>
      /// Summary description for Form1.
      /// </summary>
      public class Form1 : System.Windows.Forms.Form
      {
            private System.Windows.Forms.TextBox textBox1;
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.Container components = null;

            public Form1()
            {
                  //
                  // Required for Windows Form Designer support
                  //
                  InitializeComponent();

                  //
                  // TODO: Add any constructor code after InitializeComponent call
                  //
                  this.Load +=new EventHandler(Form1_Load);
                  this.MouseDown +=new MouseEventHandler(Form1_MouseDown);
            }

            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            protected override void Dispose( bool disposing )
            {
                  if( disposing )
                  {
                        if (components != null)
                        {
                              components.Dispose();
                        }
                  }
                  base.Dispose( disposing );
            }

            #region Windows Form Designer generated code
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                  this.textBox1 = new System.Windows.Forms.TextBox();
                  this.SuspendLayout();
                  //
                  // textBox1
                  //
                  this.textBox1.Location = new System.Drawing.Point(88, 112);
                  this.textBox1.Name = "textBox1";
                  this.textBox1.Size = new System.Drawing.Size(376, 20);
                  this.textBox1.TabIndex = 0;
                  this.textBox1.Text = "textBox1";
                  //
                  // Form1
                  //
                  this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
                  this.ClientSize = new System.Drawing.Size(600, 478);
                  this.Controls.Add(this.textBox1);
                  this.Name = "Form1";
                  this.Text = "Form1";
                  this.ResumeLayout(false);

            }
            #endregion

            /// <summary>
            /// The main entry point for the application.
            /// </summary>
      
            static void Main()
            {
                  Application.Run(new Form1());
            }

            private void Form1_Load(object sender, EventArgs e)
            {
                  Application.AddMessageFilter(new MyFilter());
            }

            private void Form1_MouseDown(object sender, MouseEventArgs e)
            {
                  while (true)
                  {
                        this.textBox1.Text += "A";
                        Console.WriteLine(this.textBox1.Text);
                  }
            }
      }
      public class MyFilter : IMessageFilter
      {
            #region IMessageFilter Members

            public bool PreFilterMessage(ref Message m)
            {
                  // TODO:  Add MyFilter.PreFilterMessage implementation
                  Console.WriteLine(m.Msg);
                  return false;
            }

            #endregion

      }

}

As you will see, windows stops sending messages once your loop starts, including the WM_PAINT message.  The reason why windows will not send the message is because your application message queue is never empty, and windows is waiting for it to be empty.  For more info on WM_PAINT, go to http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/pantdraw_88ac.asp

If you call the Update() function on your control or form, it will force the window to be repainted.
0
 
LVL 2

Accepted Solution

by:
davidastle earned 1200 total points
ID: 11790295
So instead of:
while (true)
{
   myTextBox.Text += "A";
}
Do:
while (true)
{
   myTextBox.Text += "A";
   myTextBox.Update();
}
You could also call the Update function on the current window (this.Update()).  This will automatically update every child control as well.
0
 

Author Comment

by:nh_capricorn
ID: 11800858
Thanks David!

I really appreciate all of the detail you put into your answer. Guess I'm just going to have to get used to programming with windows (Java was a lot simpler, IMO).

- nhc
0

Featured Post

Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: Najam
Having new technologies does not mean they will completely replace old components.  Recently I had to create WCF that will be called by VB6 component.  Here I will describe what steps one should follow while doing so, please feel free to post any qu…
This article introduced a TextBox that supports transparent background.   Introduction TextBox is the most widely used control component in GUI design. Most GUI controls do not support transparent background and more or less do not have the…
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA: https://www.percona.com/resources/we…
Suggested Courses

650 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question