Problems when canceling OnClosing

G

Guest

I want to prevent a form from closing when the user clicks the form's Close button in the form's ControlBox (i.e., the button with the "X" in the upper-right corner of the form). Instead, I just want to hide the form. My idea is to do something like the following

Protected Overrides Sub OnClosing(ByVal e As System.ComponentModel.CancelEventArgs
e.Cancel = Tru
MyBase.OnClosing(e
Me.Visible = Fals
End Su

This technique seems to work fine if the form is shown as a modeless dialog (i.e., via Form.Show). But, if I show the form as a modal dialog (i.e., via Form.ShowDialog) then the form's controls become corrupt after the form is hidden (by the user clicking the Cancel ControlBox button) and then reshown (by calling the form's ShowDialog method). Note that I need to show the form as a modal dialog

The corruption is most apparent for controls that inherit from ButtonBase and have their FlatStyle property set to Flat. In this case, when the form is reshown the controls' graphics freeze in the "MouseOver" state

I imagine that I must be doing something wrong. Any advice

Thanks
Lance
 
H

Herfried K. Wagner [MVP]

* "=?Utf-8?B?TGFuY2U=?= said:
I want to prevent a form from closing when the user clicks the form's Close button in the form's ControlBox (i.e., the button with the "X" in the upper-right corner of the form). Instead, I just want to hide the form. My idea is to do something like the following:

Protected Overrides Sub OnClosing(ByVal e As System.ComponentModel.CancelEventArgs)
e.Cancel = True
MyBase.OnClosing(e)
Me.Visible = False
End Sub

This technique seems to work fine if the form is shown as a modeless dialog (i.e., via Form.Show). But, if I show the form as a modal dialog (i.e., via Form.ShowDialog) then the form's controls become corrupt after the form is hidden (by the user clicking the Cancel ControlBox button) and then reshown (by calling the form's ShowDialog method). Note that I need to show the form as a modal dialog.

Did you try to show the form again by setting its 'Visible' property to 'True'?
 
M

[MSFT]

Hi Lance,

Thank you for using the community. Currently we are finding proper resource
to assist you on this issue, and will update this post as soon as posible.

Regards

Luke
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
C

Cor

Hi Lance,

Beside if it works or not, is this the right solution you choose.

When there is an X box in top the program should do as the user expect.
Otherwise you can wait on it that there will somebody in future who tells
you that there is a bug in it.

But just my thought about this problem and I thought that it was right to
share that with you.


Cor
 
P

Peter Huang

Hi Lance,

Thanks for your quickly reply!

I agree with Herfried's suggestion, if you want to hide an dialog form and
reshow it, I think you may try to set the visible property.


If the problem is still persists.
Also can you provide some simple demo code for me to reproduce the problem.
It seems that I can not reproduce the problem.
Here is my test code.
[Form1, the startup form, has three buttons on the form]
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
fm = New Form2
fm.ShowDialog()
End Sub

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button3.Click
fm.ShowDialog()
End Sub

[Form2, which will be shown modally, has a button and a textbox on the form
]
Dim bflag As Boolean
Protected Overrides Sub OnClosing(ByVal e As
System.ComponentModel.CancelEventArgs)
e.Cancel = bflag
MyBase.OnClosing(e)
Me.Visible = False
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
bflag = Not bflag
End Sub

Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
bflag = True
End Sub

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

"I agree with Herfried's suggestion, if you want to hide an dialog form and
reshow it, I think you may try to set the visible property.

Yes, what I need to do is hide the form, but what is the proper technique for hiding a modal dialog window when the user clicks the Close ControlBox button

Here is an app that demonstrates the problem. Note that instructions are in the label on the main form

#Region " MainForm

Public Class MainFor
Inherits System.Windows.Forms.For

#Region " Windows Form Designer generated code

Public Sub New(
MyBase.New(

'This call is required by the Windows Form Designer
InitializeComponent(

'Add any initialization after the InitializeComponent() cal

End Su

'Form overrides dispose to clean up the component list
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean
If disposing The
If Not (components Is Nothing) The
components.Dispose(
End I
End I
MyBase.Dispose(disposing
End Su

'Required by the Windows Form Designe
Private components As System.ComponentModel.IContaine

'NOTE: The following procedure is required by the Windows Form Designe
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor
Friend WithEvents Button1 As System.Windows.Forms.Butto
Friend WithEvents Label1 As System.Windows.Forms.Labe
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent(
Me.Button1 = New System.Windows.Forms.Butto
Me.Label1 = New System.Windows.Forms.Labe
Me.SuspendLayout(

'Button

Me.Button1.Location = New System.Drawing.Point(12, 16
Me.Button1.Name = "Button1
Me.Button1.TabIndex =
Me.Button1.Text = "Button1

'Label

Me.Label1.Location = New System.Drawing.Point(12, 44
Me.Label1.Name = "Label1
Me.Label1.Size = New System.Drawing.Size(276, 208
Me.Label1.TabIndex =
Me.Label1.Text = "Instructions: Click Button1, close TestForm by clicking the ""Close"" button in th" &
"e ControlBox, then click Button1 again. Now, move your mouse over the controls " &
"in TestForm. Note that the controls in TestForm will not update their graphics " &
"when the mouse leaves them.

'MainFor

Me.AutoScaleBaseSize = New System.Drawing.Size(6, 15
Me.ClientSize = New System.Drawing.Size(292, 258
Me.Controls.Add(Me.Label1
Me.Controls.Add(Me.Button1
Me.Name = "MainForm
Me.Text = "MainForm
Me.ResumeLayout(False

End Su

#End Regio

Public Shared SharedTestForm As TestFor

Shared Sub New(
SharedTestForm = New TestFor
End Su

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Clic
SharedTestForm.ShowDialog(
End Su

End Clas

#End Regio

#Region " TestForm

Public Class TestFor
Inherits System.Windows.Forms.For

#Region " Windows Form Designer generated code

Public Sub New(
MyBase.New(

'This call is required by the Windows Form Designer
InitializeComponent(

'Add any initialization after the InitializeComponent() cal

End Su

'Form overrides dispose to clean up the component list
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean
If disposing The
If Not (components Is Nothing) The
components.Dispose(
End I
End I
MyBase.Dispose(disposing
End Su

'Required by the Windows Form Designe
Private components As System.ComponentModel.IContaine

'NOTE: The following procedure is required by the Windows Form Designe
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor
Friend WithEvents Button1 As System.Windows.Forms.Butto
Friend WithEvents Button2 As System.Windows.Forms.Butto
Friend WithEvents Button3 As System.Windows.Forms.Butto
Friend WithEvents RadioButton1 As System.Windows.Forms.RadioButto
Friend WithEvents RadioButton2 As System.Windows.Forms.RadioButto
Friend WithEvents RadioButton3 As System.Windows.Forms.RadioButton
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.Button2 = New System.Windows.Forms.Button
Me.Button3 = New System.Windows.Forms.Button
Me.RadioButton1 = New System.Windows.Forms.RadioButton
Me.RadioButton2 = New System.Windows.Forms.RadioButton
Me.RadioButton3 = New System.Windows.Forms.RadioButton
Me.SuspendLayout()
'
'Button1
'
Me.Button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat
Me.Button1.Location = New System.Drawing.Point(160, 40)
Me.Button1.Name = "Button1"
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
'
'Button2
'
Me.Button2.FlatStyle = System.Windows.Forms.FlatStyle.Flat
Me.Button2.Location = New System.Drawing.Point(160, 76)
Me.Button2.Name = "Button2"
Me.Button2.TabIndex = 1
Me.Button2.Text = "Button2"
'
'Button3
'
Me.Button3.FlatStyle = System.Windows.Forms.FlatStyle.Flat
Me.Button3.Location = New System.Drawing.Point(160, 112)
Me.Button3.Name = "Button3"
Me.Button3.TabIndex = 2
Me.Button3.Text = "Button3"
'
'RadioButton1
'
Me.RadioButton1.FlatStyle = System.Windows.Forms.FlatStyle.Flat
Me.RadioButton1.Location = New System.Drawing.Point(8, 36)
Me.RadioButton1.Name = "RadioButton1"
Me.RadioButton1.TabIndex = 3
Me.RadioButton1.Text = "RadioButton1"
'
'RadioButton2
'
Me.RadioButton2.FlatStyle = System.Windows.Forms.FlatStyle.Flat
Me.RadioButton2.Location = New System.Drawing.Point(8, 68)
Me.RadioButton2.Name = "RadioButton2"
Me.RadioButton2.TabIndex = 4
Me.RadioButton2.Text = "RadioButton2"
'
'RadioButton3
'
Me.RadioButton3.FlatStyle = System.Windows.Forms.FlatStyle.Flat
Me.RadioButton3.Location = New System.Drawing.Point(8, 100)
Me.RadioButton3.Name = "RadioButton3"
Me.RadioButton3.TabIndex = 5
Me.RadioButton3.Text = "RadioButton3"
'
'TestForm
'
Me.AutoScaleBaseSize = New System.Drawing.Size(6, 15)
Me.ClientSize = New System.Drawing.Size(292, 258)
Me.Controls.Add(Me.RadioButton3)
Me.Controls.Add(Me.RadioButton2)
Me.Controls.Add(Me.RadioButton1)
Me.Controls.Add(Me.Button3)
Me.Controls.Add(Me.Button2)
Me.Controls.Add(Me.Button1)
Me.Name = "TestForm"
Me.Text = "TestForm"
Me.ResumeLayout(False)

End Sub

#End Region

#Region " OnEvents "

#Region " OnEvents - OnClosing "

Protected Overrides Sub OnClosing(ByVal e As System.ComponentModel.CancelEventArgs)
'Cancel the closing.
e.Cancel = True

'Call the base method.
Call MyBase.OnClosing(e)

'Hide the form.
Me.Hide()
End Sub

#End Region

#End Region

End Class

#End Region
 
P

Peter Huang

Hi,

Thanks for your quickly reply!

I think to set the visible property will be a proper approach to hide and
reshow the dialog form.

If you print out the handle of the TestForm, you will find that it will
change when call the showdialog twice which will cause problem.

Try to change the code line below
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
SharedTestForm.ShowDialog()
End Sub
with the code line below.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
SharedTestForm.Visible = True
End Sub


You may have a test by add the code line in the TestForm, you will find
that the handle of the testform you showdialog in the first time will be
changed when you showdialog the second time, that is to the window has been
recreated which will cause problem.

Private Sub Button1_Click(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Button1.Click
MsgBox(Me.Handle.ToString)
End Sub

If you still have any concern on this issue, please feel free to post here.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
P

Peter Huang

Hi Lance,

Thanks for your quickly reply!

The design of a modal dialog(form) is used to hold the focus and wait for
the UI interative operation on the modal dialog.
If we hide it, and the focus will go the mainform, in this way the oringal
modal dialog will no longer be modal.

Did you have any concern that why you need to display the form modal and
then hide it and then show it modal again?

Since usually a modal dialog will be used to accept the user input and
store in the database or a variable and then close it. In you want to hide
a modal form and show it again the behavior seems to similar with show the
form modalessly. Can you tell me what do you want to use the modal form for
and what operation you need to do after you hide the modal dialog?

I look forward to hearing from you.


Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Thank you for your continued help on this issue. I need the form to be modal so that the user is unable to interact with objects on the MainForm while the form is visible. But, I also want to always use the same instance of the form throughout the life of the program so that I can persist the state of the form (i.e., so that all of the controls are exactly as they were at the time the form was hidden). The technique that I am using (i.e., call ShowDialog and then cancel OnClosing) is the only ideal I can come up with for how to achieve both of these requirements. Is there some other way to make a form act as if it is modal? Note that the following technique also does not work (although it does illustrate what I would like to do)

Protected _HaveShown As Boolean = Fals

Public Shadows Function ShowDialog() As Windows.Forms.DialogResul
If (Not Me._HaveShown) The
Me._HaveShown = Tru
Return MyBase.ShowDialo
Els
Me.Visible = Tru
End I
End Functio

Protected Overrides Sub OnClosing(ByVal e As System.ComponentModel.CancelEventArgs
'Cancel the closing
e.Cancel = Tru

'Call the base method
Call MyBase.OnClosing(e

'Hide the form
Me.Visible = Fals
End Su

Thanks again
Lance
 
P

Peter Huang

Hi Lance,


Based on my further researching, this may be caused by a known issue that
the MouseLeave event is not fired for button control hosted on modal dialog
when the dialog is displayed again.

So far the workaround is to dispose the form when the Modal Dialog is
closed and recreating the form before ShowDialog(). I suggest you try to
save the states of the Modal Dialog you wants to perserve to variables
before closing the dialog form and then dispose the dialog form. When you
wants to show it again you may try to read the variables and make
accordingly setting to the form before you call ShowDialog of the form.

Thank you for your understanding!

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Thanks a lot for the info. Not what I wanted to hear, but good to know nonetheless

Now I have a couple of followup questions

1. Do you know if this is or will be fixed in Visual Studio 2005
2. The most relavant control on the form is a PropertyGrid. Is there a way to store the state of a PropertyGrid, including how the properties are sorted, which properties are expanded, the index of the selected property, etc.

Thanks again
Lance
 
P

Peter Huang

Hi Lance,

For the known issue, I have reported to our product group, but I can not
guarantee if it will be fixed in the next release version of .net.

For the state saving of PropertyGrid, because some of the property of
propertygrid is private , we cannot save it. For how the properties are
sorted, we can stored the propertysort property, but we can not save all
the UI setting. Do you have any concern on about just save the important
data only?

I suggest you do not use the FlatStyle.Flat in the Button or other
controls. Or I think we may have to wait for the fix of the issue.

Thank for your understanding.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 

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