Why this does not work?

  • Thread starter Thread starter Juan C. Olivares
  • Start date Start date
J

Juan C. Olivares

Hi:

This is a little program. It has a thread that calls trough Invoke to a
method called Draw. The Draw method draw elements within the Panel control.

For some reason, the program does not close sometimes. Please semd me
comments about this.

Thanks!
Juan C. Olivares

// project created on 11-07-2003 at 0:31
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace MyFormProject
{
delegate void DelegateCallDraw ();
class MainForm : System.Windows.Forms.Form
{
private System.Windows.Forms.Panel panel;
private DelegateCallDraw CallDraw;
public MainForm()
{
InitializeComponent();
panel.AutoScroll = true;
// Add controls
this.Draw ();
// Create delegate
CallDraw = new DelegateCallDraw (Draw);
// StartThread
Thread thread = new Thread (new ThreadStart (StartTimer));
thread.Start ();
}
// This method is used in the forms designer.
// Change this method on you own risk
void InitializeComponent() {
this.panel = new System.Windows.Forms.Panel();
this.SuspendLayout();
//
// panel
//
this.panel.Location = new System.Drawing.Point(16, 16);
this.panel.Name = "panel";
this.panel.Size = new System.Drawing.Size(264, 128);
this.panel.TabIndex = 0;
//
// MainForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 161);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.panel});
this.Name = "MainForm";
this.Text = "This is my form";
this.ResumeLayout(false);
}
private void Draw ()
{
panel.Controls.Clear ();
panel.SuspendLayout ();
for (int i = 1; i <= 20; i++) {
TextBox tb = new TextBox ();
tb.Text = i.ToString ();
tb.Location = new Point (0, (i - 1) * tb.Height);
panel.Controls.Add (tb);
}
panel.ResumeLayout ();
}
private void StartTimer ()
{
while (true) {
// Sleep 10 secs
Thread.Sleep (1000 * 10);
// Call draw
this.Invoke (this.CallDraw);
}
}
[STAThread]
public static void Main(string[] args)
{
Application.Run(new MainForm());
}
}
}
 
Hi Juan,
The problem probably is one well known bug in the frame work, which (as far
as I know) MS doesn't recognize as a bug so far.

The bad line is:
panel.Controls.Clear ();
and control validation

If you remove control which is currently focused the form fails to clear
some internal stuff and tries to validate this control. As a result of this,
Form.Closing event receives event args with Cancel property set to 'true',
which stops the form and the application from closing.
There are couple of work arounds:
1. To swhitch the focus on something that is not going to be removed prior
to removing - I personally dislike this.
2. To call Form.OnControlRemoved (and pass a reference to the control) prior
or after removing the control. If you call control.Dispose you have to call
OnControlRemove before disposing the control.

in your case something like
foreach(Control ctrl in panle.Controls)
{
this.OnControlRemove(new ControlEventArgs(ctrl));
}
panel.Controls.Clear()

HTH
B\rgds
100

Juan C. Olivares said:
Hi:

This is a little program. It has a thread that calls trough Invoke to a
method called Draw. The Draw method draw elements within the Panel control.

For some reason, the program does not close sometimes. Please semd me
comments about this.

Thanks!
Juan C. Olivares

// project created on 11-07-2003 at 0:31
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace MyFormProject
{
delegate void DelegateCallDraw ();
class MainForm : System.Windows.Forms.Form
{
private System.Windows.Forms.Panel panel;
private DelegateCallDraw CallDraw;
public MainForm()
{
InitializeComponent();
panel.AutoScroll = true;
// Add controls
this.Draw ();
// Create delegate
CallDraw = new DelegateCallDraw (Draw);
// StartThread
Thread thread = new Thread (new ThreadStart (StartTimer));
thread.Start ();
}
// This method is used in the forms designer.
// Change this method on you own risk
void InitializeComponent() {
this.panel = new System.Windows.Forms.Panel();
this.SuspendLayout();
//
// panel
//
this.panel.Location = new System.Drawing.Point(16, 16);
this.panel.Name = "panel";
this.panel.Size = new System.Drawing.Size(264, 128);
this.panel.TabIndex = 0;
//
// MainForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 161);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.panel});
this.Name = "MainForm";
this.Text = "This is my form";
this.ResumeLayout(false);
}
private void Draw ()
{
panel.Controls.Clear ();
panel.SuspendLayout ();
for (int i = 1; i <= 20; i++) {
TextBox tb = new TextBox ();
tb.Text = i.ToString ();
tb.Location = new Point (0, (i - 1) * tb.Height);
panel.Controls.Add (tb);
}
panel.ResumeLayout ();
}
private void StartTimer ()
{
while (true) {
// Sleep 10 secs
Thread.Sleep (1000 * 10);
// Call draw
this.Invoke (this.CallDraw);
}
}
[STAThread]
public static void Main(string[] args)
{
Application.Run(new MainForm());
}
}
}
 
Thanks ;)

100 said:
Hi Juan,
The problem probably is one well known bug in the frame work, which (as far
as I know) MS doesn't recognize as a bug so far.

The bad line is:
panel.Controls.Clear ();
and control validation

If you remove control which is currently focused the form fails to clear
some internal stuff and tries to validate this control. As a result of this,
Form.Closing event receives event args with Cancel property set to 'true',
which stops the form and the application from closing.
There are couple of work arounds:
1. To swhitch the focus on something that is not going to be removed prior
to removing - I personally dislike this.
2. To call Form.OnControlRemoved (and pass a reference to the control) prior
or after removing the control. If you call control.Dispose you have to call
OnControlRemove before disposing the control.

in your case something like
foreach(Control ctrl in panle.Controls)
{
this.OnControlRemove(new ControlEventArgs(ctrl));
}
panel.Controls.Clear()

HTH
B\rgds
100

Juan C. Olivares said:
Hi:

This is a little program. It has a thread that calls trough Invoke to a
method called Draw. The Draw method draw elements within the Panel control.

For some reason, the program does not close sometimes. Please semd me
comments about this.

Thanks!
Juan C. Olivares

// project created on 11-07-2003 at 0:31
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace MyFormProject
{
delegate void DelegateCallDraw ();
class MainForm : System.Windows.Forms.Form
{
private System.Windows.Forms.Panel panel;
private DelegateCallDraw CallDraw;
public MainForm()
{
InitializeComponent();
panel.AutoScroll = true;
// Add controls
this.Draw ();
// Create delegate
CallDraw = new DelegateCallDraw (Draw);
// StartThread
Thread thread = new Thread (new ThreadStart (StartTimer));
thread.Start ();
}
// This method is used in the forms designer.
// Change this method on you own risk
void InitializeComponent() {
this.panel = new System.Windows.Forms.Panel();
this.SuspendLayout();
//
// panel
//
this.panel.Location = new System.Drawing.Point(16, 16);
this.panel.Name = "panel";
this.panel.Size = new System.Drawing.Size(264, 128);
this.panel.TabIndex = 0;
//
// MainForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 161);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.panel});
this.Name = "MainForm";
this.Text = "This is my form";
this.ResumeLayout(false);
}
private void Draw ()
{
panel.Controls.Clear ();
panel.SuspendLayout ();
for (int i = 1; i <= 20; i++) {
TextBox tb = new TextBox ();
tb.Text = i.ToString ();
tb.Location = new Point (0, (i - 1) * tb.Height);
panel.Controls.Add (tb);
}
panel.ResumeLayout ();
}
private void StartTimer ()
{
while (true) {
// Sleep 10 secs
Thread.Sleep (1000 * 10);
// Call draw
this.Invoke (this.CallDraw);
}
}
[STAThread]
public static void Main(string[] args)
{
Application.Run(new MainForm());
}
}
}
 
Back
Top