Can't exit Windows after removing a control from a form

G

Greg Patrick

This problem occurs on Windows 2000 but NOT on Windows XP:
If you programmatically remove a control from the Controls collection of a
panel on another form, then that form's default WndProc will return FALSE to
the WM_QUERYENDSESSION message!

Is there anything that can be done to fix this other than overriding the
WndProc (which I don't want to do for performance reasons)?

Please help!

To reproduce: (on Win 2000 obviously)

VS.Net 2003, Framework 1.1 w/ service packs:

In VS.Net, create a C# win forms application with two Forms (e.g. Form1 and
Form2):

On Form1, drop two buttons.
On Form2, drop a panel, drop a button inside the panel. In Form2 code, make
panel1 be public.

In Form1, add a Form2 private variable (e.g. call it "form2"), then write
the first button's click handler:

if (this.form2 == null) this.form2 = new Form2();
this.form2.Show();

The second button's click handler:

this.form2.panel1.Controls.RemoveAt(0);


Then run it... click the first button, click the second button. You should
see the button disappear from the panel of form2. Then try to exit Windows
(or, a bit nicer, write something to FindWindow of the Form2 window and send
it WM_QUERYENDSESSION).

Thanks!,

Greg Patrick
 
S

Stoitcho Goutsev \(100\) [C# MVP]

Hi Greg,

I'm surprised that it doesn't happen in XP.

I believe this is one well know bug in windows forms. The bug shows up when
you remove a focused control. The framework doesn't clean up correctly and
tries to validate the control upon closing. It fails because the control is
not there. Because of this closing gets cancel.

To workaround this you have options:
1. To swhitch the focus on another control before taking the control off - 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.

HTH
 
D

Dmytro Lapshyn [MVP]

Hi all,

#2, as far as I remember, is a kind of 'official' workaround (I even believe
it's documented somewhere in the KB).
Well, at least it works great for me :)

--
Sincerely,
Dmytro Lapshyn [Visual Developer - Visual C# MVP]


Stoitcho Goutsev (100) said:
Hi Greg,

I'm surprised that it doesn't happen in XP.

I believe this is one well know bug in windows forms. The bug shows up
when you remove a focused control. The framework doesn't clean up
correctly and tries to validate the control upon closing. It fails because
the control is not there. Because of this closing gets cancel.

To workaround this you have options:
1. To swhitch the focus on another control before taking the control off -
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.

HTH

--
Stoitcho Goutsev (100) [C# MVP]
Greg Patrick said:
This problem occurs on Windows 2000 but NOT on Windows XP:
If you programmatically remove a control from the Controls collection of
a panel on another form, then that form's default WndProc will return
FALSE to the WM_QUERYENDSESSION message!

Is there anything that can be done to fix this other than overriding the
WndProc (which I don't want to do for performance reasons)?

Please help!

To reproduce: (on Win 2000 obviously)

VS.Net 2003, Framework 1.1 w/ service packs:

In VS.Net, create a C# win forms application with two Forms (e.g. Form1
and Form2):

On Form1, drop two buttons.
On Form2, drop a panel, drop a button inside the panel. In Form2 code,
make panel1 be public.

In Form1, add a Form2 private variable (e.g. call it "form2"), then write
the first button's click handler:

if (this.form2 == null) this.form2 = new Form2();
this.form2.Show();

The second button's click handler:

this.form2.panel1.Controls.RemoveAt(0);


Then run it... click the first button, click the second button. You
should see the button disappear from the panel of form2. Then try to
exit Windows (or, a bit nicer, write something to FindWindow of the Form2
window and send it WM_QUERYENDSESSION).

Thanks!,

Greg Patrick
 
G

Greg Patrick

Thanks very much, I'll try out your suggestions.

Greg

Stoitcho Goutsev (100) said:
Hi Greg,

I'm surprised that it doesn't happen in XP.

I believe this is one well know bug in windows forms. The bug shows up
when you remove a focused control. The framework doesn't clean up
correctly and tries to validate the control upon closing. It fails because
the control is not there. Because of this closing gets cancel.

To workaround this you have options:
1. To swhitch the focus on another control before taking the control off -
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.

HTH

--
Stoitcho Goutsev (100) [C# MVP]
Greg Patrick said:
This problem occurs on Windows 2000 but NOT on Windows XP:
If you programmatically remove a control from the Controls collection of
a panel on another form, then that form's default WndProc will return
FALSE to the WM_QUERYENDSESSION message!

Is there anything that can be done to fix this other than overriding the
WndProc (which I don't want to do for performance reasons)?

Please help!

To reproduce: (on Win 2000 obviously)

VS.Net 2003, Framework 1.1 w/ service packs:

In VS.Net, create a C# win forms application with two Forms (e.g. Form1
and Form2):

On Form1, drop two buttons.
On Form2, drop a panel, drop a button inside the panel. In Form2 code,
make panel1 be public.

In Form1, add a Form2 private variable (e.g. call it "form2"), then write
the first button's click handler:

if (this.form2 == null) this.form2 = new Form2();
this.form2.Show();

The second button's click handler:

this.form2.panel1.Controls.RemoveAt(0);


Then run it... click the first button, click the second button. You
should see the button disappear from the panel of form2. Then try to
exit Windows (or, a bit nicer, write something to FindWindow of the Form2
window and send it WM_QUERYENDSESSION).

Thanks!,

Greg Patrick
 
G

Greg Patrick

One more note... it appears the reason it wasn't happening in XP is
basically the same reason it *was* happening in 2000... the 2000 machine I
was using didn't have the framework 1.1 service pack, while the XP machine
did.

It is not a problem on either platform with the service pack...

Still, I might want to support pre-service pack users, so thanks again...

Greg Patrick said:
Thanks very much, I'll try out your suggestions.

Greg

Stoitcho Goutsev (100) said:
Hi Greg,

I'm surprised that it doesn't happen in XP.

I believe this is one well know bug in windows forms. The bug shows up
when you remove a focused control. The framework doesn't clean up
correctly and tries to validate the control upon closing. It fails
because the control is not there. Because of this closing gets cancel.

To workaround this you have options:
1. To swhitch the focus on another control before taking the control
off - 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.

HTH

--
Stoitcho Goutsev (100) [C# MVP]
Greg Patrick said:
This problem occurs on Windows 2000 but NOT on Windows XP:
If you programmatically remove a control from the Controls collection of
a panel on another form, then that form's default WndProc will return
FALSE to the WM_QUERYENDSESSION message!

Is there anything that can be done to fix this other than overriding the
WndProc (which I don't want to do for performance reasons)?

Please help!

To reproduce: (on Win 2000 obviously)

VS.Net 2003, Framework 1.1 w/ service packs:

In VS.Net, create a C# win forms application with two Forms (e.g. Form1
and Form2):

On Form1, drop two buttons.
On Form2, drop a panel, drop a button inside the panel. In Form2 code,
make panel1 be public.

In Form1, add a Form2 private variable (e.g. call it "form2"), then
write the first button's click handler:

if (this.form2 == null) this.form2 = new Form2();
this.form2.Show();

The second button's click handler:

this.form2.panel1.Controls.RemoveAt(0);


Then run it... click the first button, click the second button. You
should see the button disappear from the panel of form2. Then try to
exit Windows (or, a bit nicer, write something to FindWindow of the
Form2 window and send it WM_QUERYENDSESSION).

Thanks!,

Greg Patrick
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top