By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,265 Members | 1,731 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,265 IT Pros & Developers. It's quick & easy.

Memory corruption, problem closing multiple forms.

P: n/a
Hi, I'm using VS2005 and .net 2.0. I'm creating an application that has 3
forms. I want allow users to move forward and backward with the forms and
retain the data users have entered. I thought I'll make the inactive forms
invisible but this is creating a memory corruption problem when user close
the form2 or form3 and not the formMain.

My main form has a Next button which makes the main form invisible and
starts a new form which I'll call form2. The form 2 has a Previous and Next
button. The previous button would make the main form visiable again. The
next button would invoke a form3. both of these buttons would make form2
invisible. The form3 has a previous button to go back to form2 vislble and
make itself invisible. User can go forward and backward with these 3 forms.

Actually, I have a boolean variable in formMain and form2 to indicate if
form2 or form3 has been created. Since my application allows them to go back
and forward with these 3 forms I only want to make form2 and form3 visible if
they're already created.

I already tried have code in the closing event of form2 and form3 to try to
close it's calling form, namely form2 or formMain. But this doesn't work,
you see, when my code sets the calling form to visible=false, it
automatically callsing the form's Closing event. So, doesn't matter what
code I put there, it will get executed when I'm just setting the form to be
not visible.

My question is, if the user is closing the application either at form2 or
form3 then how do I make sure all forms are closed? Would coding to close
the main form automatically close all the chidren form in the approperate
order? If not, how can I address this? Becuase right now it's causing
memory correuption in my application. Thanks.
--
Thanks.
Mar 28 '07 #1
Share this Question
Share on Google+
14 Replies


P: n/a
On Tue, 27 Mar 2007 23:16:03 -0700, Pucca
<Pu***@discussions.microsoft.comwrote:
[...]
My question is, if the user is closing the application either at form2 or
form3 then how do I make sure all forms are closed? Would coding to
close the main form automatically close all the chidren form in the
approperate order? If not, how can I address this? Becuase right now
it's causing memory correuption in my application. Thanks.
Some thoughts:

It's not clear from your post what "memory corruption" problem you're
having. You mention having one, but other than that, there's nothing.

I don't see how the visible/closing issue is related to the memory
corruption issue. Memory corruption shouldn't happen in any case, no
matter what you're doing with the forms, and there's not any reason that
changing the visible property or closing a form should in and of itself
corrupt memory.

I also don't see why your Closing event gets fired when all you're doing
is setting the Visible property to false. Hiding the form isn't the same
as closing it, and it doesn't seem right that the Closing event would get
fired (note that the converse is not necessarily true...for example, when
a form is displayed as a modal dialog, clicking the close button on the
form results in the form being hidden rather than actually disposed).

Also note that as of .NET 2.0, you should use the FormClosing event,
rather than the Closing event. For that matter, in your situation it
seems to me that the Closed event is actually more appropriate. There's
probably no practical difference, but it just seems like a better choice
to me here, since at the point in time that the FormClosing event is
received, it is not guaranteed that the form will actually be closed.

Basically, there's a bit in your post that doesn't add up, at least at
first read. If you could clarify your situation a bit, that would be
helpful.

Pete
Mar 28 '07 #2

P: n/a
Hi ,

I'm not sure whether design-wise what you have is the cleanest way to
achieve what you're looking for - this might also explain why you're running
into the kind of issues that you describe... I can suggest three other ways
that might make coding this a little more straightforward:

(1) A lightweight option could be to have one form, but with three separate
groupBoxes that 'simulate' a form each, each groupBox of which contains the
controls that you want to collect data in. Put a close, next and previous
button on the form, and as the user clicks through next/previous, hide/unhide
the groupBoxes. You could even create a sorted list populated with an enum
code + groupBox, and cycle over to the first groupbox 'form' when the user
clicks next past the third groupbox, or cycles backwards to the last groupbox
'form' when the user clicks previous past the first entry.. This is the most
simple to implement, however is probably the least amenable to change.

As an example, your next/previous button click events might look something
like (not compiled/tested):

private void btnNext_Click(object sender, EventArgs e)
{
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = false;
m_currentFormEnum++;
if (m_currentFormEnum == FormEnum.End)
m_currentFormEnum = FormEnum.Form1;
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = true;
}

private void btnPrevious_Click(object sender, EventArgs e)
{
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = false;
m_currentFormEnum--;
if (m_currentFormEnum == FormEnum.Begin)
m_currentFormEnum = FormEnum.Form3;
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = true;
}
(2) Another option, might be to represent each 'form' as a custom user
control, which each contain the native .NET controls used to capture your
required data. The user controls could have public properties that expose the
data that the user entersin them. Again, a single form will host the three
instantiated user controls, and you would have hide/unhide your custom user
controls as the user clicks through next/previous. This is a little bit more
work, however your new user controls will be re-useable elsewhere, and also
would have a nice separation from the hosting Form (which is a good thing).

(3) A third much more heavyweight option could be to use something like the
User Interface Process Application Block from Microsoft which enables you to
do what you're looking for, along with a whole lot more! You can find out
about the UIPAB from:
(1) http://msdn2.microsoft.com/en-us/library/ms979217.aspx
(2) http://www.codeproject.com/dotnet/UIPAB1.asp

Not sure why, but something tells me that there are many other possibilities
as well ;-).. Hope this helps you though...

Kind regards,
Patrick
--
Patrick Simpe-Asante
MCAD, MSCD.Net
"Pucca" wrote:
Hi, I'm using VS2005 and .net 2.0. I'm creating an application that has 3
forms. I want allow users to move forward and backward with the forms and
retain the data users have entered. I thought I'll make the inactive forms
invisible but this is creating a memory corruption problem when user close
the form2 or form3 and not the formMain.

My main form has a Next button which makes the main form invisible and
starts a new form which I'll call form2. The form 2 has a Previous and Next
button. The previous button would make the main form visiable again. The
next button would invoke a form3. both of these buttons would make form2
invisible. The form3 has a previous button to go back to form2 vislble and
make itself invisible. User can go forward and backward with these 3 forms.

Actually, I have a boolean variable in formMain and form2 to indicate if
form2 or form3 has been created. Since my application allows them to go back
and forward with these 3 forms I only want to make form2 and form3 visible if
they're already created.

I already tried have code in the closing event of form2 and form3 to try to
close it's calling form, namely form2 or formMain. But this doesn't work,
you see, when my code sets the calling form to visible=false, it
automatically callsing the form's Closing event. So, doesn't matter what
code I put there, it will get executed when I'm just setting the form to be
not visible.

My question is, if the user is closing the application either at form2 or
form3 then how do I make sure all forms are closed? Would coding to close
the main form automatically close all the chidren form in the approperate
order? If not, how can I address this? Becuase right now it's causing
memory correuption in my application. Thanks.
--
Thanks.
Mar 28 '07 #3

P: n/a
Hi Pucca,

Forgot to mention - in the first option below, the group boxes would be
overlaid over each other... Just in case that wasn't obvious from my post...

regards,
Patrick

--
Patrick Simpe-Asante
MCAD, MSCD.Net
"Patrick Simpe-Asante" wrote:
Hi Pucca,

I'm not sure whether design-wise what you have is the cleanest way to
achieve what you're looking for - this might also explain why you're running
into the kind of issues that you describe... I can suggest three other ways
that might make coding this a little more straightforward:

(1) A lightweight option could be to have one form, but with three separate
groupBoxes that 'simulate' a form each, each groupBox of which contains the
controls that you want to collect data in. Put a close, next and previous
button on the form, and as the user clicks through next/previous, hide/unhide
the groupBoxes. You could even create a sorted list populated with an enum
code + groupBox, and cycle over to the first groupbox 'form' when the user
clicks next past the third groupbox, or cycles backwards to the last groupbox
'form' when the user clicks previous past the first entry.. This is the most
simple to implement, however is probably the least amenable to change.

As an example, your next/previous button click events might look something
like (not compiled/tested):

private void btnNext_Click(object sender, EventArgs e)
{
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = false;
m_currentFormEnum++;
if (m_currentFormEnum == FormEnum.End)
m_currentFormEnum = FormEnum.Form1;
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = true;
}

private void btnPrevious_Click(object sender, EventArgs e)
{
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = false;
m_currentFormEnum--;
if (m_currentFormEnum == FormEnum.Begin)
m_currentFormEnum = FormEnum.Form3;
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = true;
}
(2) Another option, might be to represent each 'form' as a custom user
control, which each contain the native .NET controls used to capture your
required data. The user controls could have public properties that expose the
data that the user entersin them. Again, a single form will host the three
instantiated user controls, and you would have hide/unhide your custom user
controls as the user clicks through next/previous. This is a little bit more
work, however your new user controls will be re-useable elsewhere, and also
would have a nice separation from the hosting Form (which is a good thing).

(3) A third much more heavyweight option could be to use something like the
User Interface Process Application Block from Microsoft which enables you to
do what you're looking for, along with a whole lot more! You can find out
about the UIPAB from:
(1) http://msdn2.microsoft.com/en-us/library/ms979217.aspx
(2) http://www.codeproject.com/dotnet/UIPAB1.asp

Not sure why, but something tells me that there are many other possibilities
as well ;-).. Hope this helps you though...

Kind regards,
Patrick
--
Patrick Simpe-Asante
MCAD, MSCD.Net
"Pucca" wrote:
Hi, I'm using VS2005 and .net 2.0. I'm creating an application that has 3
forms. I want allow users to move forward and backward with the forms and
retain the data users have entered. I thought I'll make the inactive forms
invisible but this is creating a memory corruption problem when user close
the form2 or form3 and not the formMain.

My main form has a Next button which makes the main form invisible and
starts a new form which I'll call form2. The form 2 has a Previous and Next
button. The previous button would make the main form visiable again. The
next button would invoke a form3. both of these buttons would make form2
invisible. The form3 has a previous button to go back to form2 vislble and
make itself invisible. User can go forward and backward with these 3 forms.

Actually, I have a boolean variable in formMain and form2 to indicate if
form2 or form3 has been created. Since my application allows them to go back
and forward with these 3 forms I only want to make form2 and form3 visible if
they're already created.

I already tried have code in the closing event of form2 and form3 to try to
close it's calling form, namely form2 or formMain. But this doesn't work,
you see, when my code sets the calling form to visible=false, it
automatically callsing the form's Closing event. So, doesn't matter what
code I put there, it will get executed when I'm just setting the form to be
not visible.

My question is, if the user is closing the application either at form2 or
form3 then how do I make sure all forms are closed? Would coding to close
the main form automatically close all the chidren form in the approperate
order? If not, how can I address this? Becuase right now it's causing
memory correuption in my application. Thanks.
--
Thanks.
Mar 28 '07 #4

P: n/a
The memory corruption occured when I close the application and had to click
the stop button on VS and then trying to save changes to my code. I also
notice there were a version of my appliation still running in the task
manager and maybe that's why VS gave the memory corruption error when I tried
to save.

FormClosing event is the one I used. I was surprise to see in Debug that
after setting visible property to false, the FormClosing was invoked. I used
formName.ShowDlg(); initially to bring up form2 and form3 and then just set
their visible property false to hide them. Could this be the reason that
FormClosing is invoked?

I willl go with Patrick's suggestion 1. That seems like a good solution.
Thank you for all your input
--
Thanks.
"Peter Duniho" wrote:
On Tue, 27 Mar 2007 23:16:03 -0700, Pucca
<Pu***@discussions.microsoft.comwrote:
[...]
My question is, if the user is closing the application either at form2 or
form3 then how do I make sure all forms are closed? Would coding to
close the main form automatically close all the chidren form in the
approperate order? If not, how can I address this? Becuase right now
it's causing memory correuption in my application. Thanks.

Some thoughts:

It's not clear from your post what "memory corruption" problem you're
having. You mention having one, but other than that, there's nothing.

I don't see how the visible/closing issue is related to the memory
corruption issue. Memory corruption shouldn't happen in any case, no
matter what you're doing with the forms, and there's not any reason that
changing the visible property or closing a form should in and of itself
corrupt memory.

I also don't see why your Closing event gets fired when all you're doing
is setting the Visible property to false. Hiding the form isn't the same
as closing it, and it doesn't seem right that the Closing event would get
fired (note that the converse is not necessarily true...for example, when
a form is displayed as a modal dialog, clicking the close button on the
form results in the form being hidden rather than actually disposed).

Also note that as of .NET 2.0, you should use the FormClosing event,
rather than the Closing event. For that matter, in your situation it
seems to me that the Closed event is actually more appropriate. There's
probably no practical difference, but it just seems like a better choice
to me here, since at the point in time that the FormClosing event is
received, it is not guaranteed that the form will actually be closed.

Basically, there's a bit in your post that doesn't add up, at least at
first read. If you could clarify your situation a bit, that would be
helpful.

Pete
Mar 28 '07 #5

P: n/a
Hi Patrick, thank you for all the wonderful inupt. I think I willl be your
1st solution. My appliation is a import tool so they don't just have groupbox
on them. They have different controls and datagrids on each of the form. I
think I will have the main on the designer and then create the form2 and
form3 control upon loading of the formMain and hide them until they're
needed. Do you think this will work and is a good solution? Also, if I make
the control invisible, do I need to make them not able?
--
Thanks.
"Patrick Simpe-Asante" wrote:
Hi ,

I'm not sure whether design-wise what you have is the cleanest way to
achieve what you're looking for - this might also explain why you're running
into the kind of issues that you describe... I can suggest three other ways
that might make coding this a little more straightforward:

(1) A lightweight option could be to have one form, but with three separate
groupBoxes that 'simulate' a form each, each groupBox of which contains the
controls that you want to collect data in. Put a close, next and previous
button on the form, and as the user clicks through next/previous, hide/unhide
the groupBoxes. You could even create a sorted list populated with an enum
code + groupBox, and cycle over to the first groupbox 'form' when the user
clicks next past the third groupbox, or cycles backwards to the last groupbox
'form' when the user clicks previous past the first entry.. This is the most
simple to implement, however is probably the least amenable to change.

As an example, your next/previous button click events might look something
like (not compiled/tested):

private void btnNext_Click(object sender, EventArgs e)
{
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = false;
m_currentFormEnum++;
if (m_currentFormEnum == FormEnum.End)
m_currentFormEnum = FormEnum.Form1;
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = true;
}

private void btnPrevious_Click(object sender, EventArgs e)
{
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = false;
m_currentFormEnum--;
if (m_currentFormEnum == FormEnum.Begin)
m_currentFormEnum = FormEnum.Form3;
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = true;
}
(2) Another option, might be to represent each 'form' as a custom user
control, which each contain the native .NET controls used to capture your
required data. The user controls could have public properties that expose the
data that the user entersin them. Again, a single form will host the three
instantiated user controls, and you would have hide/unhide your custom user
controls as the user clicks through next/previous. This is a little bit more
work, however your new user controls will be re-useable elsewhere, and also
would have a nice separation from the hosting Form (which is a good thing).

(3) A third much more heavyweight option could be to use something like the
User Interface Process Application Block from Microsoft which enables you to
do what you're looking for, along with a whole lot more! You can find out
about the UIPAB from:
(1) http://msdn2.microsoft.com/en-us/library/ms979217.aspx
(2) http://www.codeproject.com/dotnet/UIPAB1.asp

Not sure why, but something tells me that there are many other possibilities
as well ;-).. Hope this helps you though...

Kind regards,
Patrick
--
Patrick Simpe-Asante
MCAD, MSCD.Net
"Pucca" wrote:
Hi, I'm using VS2005 and .net 2.0. I'm creating an application that has 3
forms. I want allow users to move forward and backward with the forms and
retain the data users have entered. I thought I'll make the inactive forms
invisible but this is creating a memory corruption problem when user close
the form2 or form3 and not the formMain.

My main form has a Next button which makes the main form invisible and
starts a new form which I'll call form2. The form 2 has a Previous and Next
button. The previous button would make the main form visiable again. The
next button would invoke a form3. both of these buttons would make form2
invisible. The form3 has a previous button to go back to form2 vislble and
make itself invisible. User can go forward and backward with these 3 forms.

Actually, I have a boolean variable in formMain and form2 to indicate if
form2 or form3 has been created. Since my application allows them to go back
and forward with these 3 forms I only want to make form2 and form3 visible if
they're already created.

I already tried have code in the closing event of form2 and form3 to try to
close it's calling form, namely form2 or formMain. But this doesn't work,
you see, when my code sets the calling form to visible=false, it
automatically callsing the form's Closing event. So, doesn't matter what
code I put there, it will get executed when I'm just setting the form to be
not visible.

My question is, if the user is closing the application either at form2 or
form3 then how do I make sure all forms are closed? Would coding to close
the main form automatically close all the chidren form in the approperate
order? If not, how can I address this? Becuase right now it's causing
memory correuption in my application. Thanks.
--
Thanks.
Mar 28 '07 #6

P: n/a
On Wed, 28 Mar 2007 11:56:02 -0700, Pucca
<Pu***@discussions.microsoft.comwrote:
The memory corruption occured when I close the application and had to
click the stop button on VS and then trying to save changes to my code.
I also notice there were a version of my appliation still running in the
task manager and maybe that's why VS gave the memory corruption error
when I tried to save.
Ah. Well, then the problem is that you have to forcibly terminate your
application.

This is because the application only exits once all the forms have been
closed. If you've simply hidden them, the application continues to run
(unless it's forcibly terminated, of course).

FormClosing event is the one I used. I was surprise to see in Debug that
after setting visible property to false, the FormClosing was invoked. I
used formName.ShowDlg(); initially to bring up form2 and form3 and then
just set their visible property false to hide them. Could this be the
reason that FormClosing is invoked?
Could be. Have you tried just using the Show and Hide methods on the
forms? I think that would be better than using ShowDialog (after all,
they don't really sound like dialogs to me).
I willl go with Patrick's suggestion 1. That seems like a good solution.
Thank you for all your input
I have found that layering different groups of controls on the same form
makes it difficult to edit the form in the designer. However, if you
don't find that to be a hassle then I'd agree that just keeping everything
on the same form might make sense.

Another option not mentioned is to implement each of your three forms as
tabs on a single dialog. This would allow for an easier time designing,
and provides the user with a familiar interface for switching from one
form to the other.

Of course, as you can see above, I don't think there's anything
fundamentally wrong with the approach you tried first. It sounds as
though you just need to learn a little more details about what actually
happens when doing modeless vs modal, and closing vs hiding.

Hope that helps...

Pete
Mar 28 '07 #7

P: n/a
Thanks Pete and Patrick for your great help. I have changed to use form.show
and form.hide and these 2 working out fine without invoking the FormClosing
event. I agree with you that layering controls on the same form does make it
cumbersome to maintain and design. I would still like to have 3 forms if
possible.

I tried coding in the FormClosing event for all 3 forms so the the
application can exit after all the forms are closed.
1. if user click to close from formMain then if form2 was created,
formMain's Fomclosing event would have: form2.close();
2. In form2's FormClosing event: If form3 was created then form3.clsoe();

The prblem is when user click to exit from form2 or form3. In form2
FormClosing event besides form3.close();
1. How does form2 inform formMain to close?
2. Is that OK to do since formMain called form2?
3. And how would I know in form2 the FormClosing is invoked by user
clicking on form2's closing icon or invoked by formMain or form3?
--
Thanks.
"Peter Duniho" wrote:
On Wed, 28 Mar 2007 11:56:02 -0700, Pucca
<Pu***@discussions.microsoft.comwrote:
The memory corruption occured when I close the application and had to
click the stop button on VS and then trying to save changes to my code.
I also notice there were a version of my appliation still running in the
task manager and maybe that's why VS gave the memory corruption error
when I tried to save.

Ah. Well, then the problem is that you have to forcibly terminate your
application.

This is because the application only exits once all the forms have been
closed. If you've simply hidden them, the application continues to run
(unless it's forcibly terminated, of course).

FormClosing event is the one I used. I was surprise to see in Debug that
after setting visible property to false, the FormClosing was invoked. I
used formName.ShowDlg(); initially to bring up form2 and form3 and then
just set their visible property false to hide them. Could this be the
reason that FormClosing is invoked?

Could be. Have you tried just using the Show and Hide methods on the
forms? I think that would be better than using ShowDialog (after all,
they don't really sound like dialogs to me).
I willl go with Patrick's suggestion 1. That seems like a good solution.
Thank you for all your input

I have found that layering different groups of controls on the same form
makes it difficult to edit the form in the designer. However, if you
don't find that to be a hassle then I'd agree that just keeping everything
on the same form might make sense.

Another option not mentioned is to implement each of your three forms as
tabs on a single dialog. This would allow for an easier time designing,
and provides the user with a familiar interface for switching from one
form to the other.

Of course, as you can see above, I don't think there's anything
fundamentally wrong with the approach you tried first. It sounds as
though you just need to learn a little more details about what actually
happens when doing modeless vs modal, and closing vs hiding.

Hope that helps...

Pete
Mar 28 '07 #8

P: n/a
On Wed, 28 Mar 2007 16:26:02 -0700, Pucca
<Pu***@discussions.microsoft.comwrote:
The prblem is when user click to exit from form2 or form3. In form2
FormClosing event besides form3.close();
1. How does form2 inform formMain to close?
Same way formMain "informs" form2 to close: formMain.Close().
2. Is that OK to do since formMain called form2?
Sure. The forms don't have a hierarchical relationship. They are all
peers in the same application. Just because formMain's code is what
caused form2 to be shown, that doesn't mean there's an ownership
relationship there. Any non-modal form can close any other form.
3. And how would I know in form2 the FormClosing is invoked by user
clicking on form2's closing icon or invoked by formMain or form3?
Well, the simplest solution is in each form to have a flag that notes
whether the form's FormClosing event has been signaled yet or not. The
FormClosing handler can be written to not do anything if that flag is set.

Basically, in each form the FormClosing handler can check that flag, and
if it's not set it would close the other two forms (checking to make sure
they have been insantiated first, of course) and set the flag. That way,
even if when the other forms get their FormClosing event and try to close
the form that started the whole process, if that form's FormClosing event
gets fired *again*, it won't do anything.

Actually, it is my recollection that when I did this, I didn't have any
trouble with recursive closing. I don't recall if that's because I used
the Closed event rather than the FormClosing event (IMHO, the Closed event
makes more sense), or if it's simply because when a form is closed, the
WM_CLOSE message is posted rather than sent directly. But either way, I
don't think there was a conflict the way I did it.

You can easily test this out yourself. The issue should be minor, and
easily addressed if necessary.

Pete
Mar 28 '07 #9

P: n/a
I put the code in the FormClosed event of 3 forms. It checks to see if
children forms were created then childForm.close(); is called. I pass the
calling form handle to both child forms, form2(this); which is receive as a
static Form variable in the child form.
I tried closing the form from form2 and the FormClosed was looped through
many times and then I get a error message: An unhandled exception of type
'System.stackoverflowexception' occured in System.Windows.Forms.dll. Why
can't I close the calling form with the static form variable that stores the
calling form's handle? Also, the application stays in the task manager until
I exit the VS. Thank you.
--
Thanks.
"Peter Duniho" wrote:
On Wed, 28 Mar 2007 16:26:02 -0700, Pucca
<Pu***@discussions.microsoft.comwrote:
The prblem is when user click to exit from form2 or form3. In form2
FormClosing event besides form3.close();
1. How does form2 inform formMain to close?

Same way formMain "informs" form2 to close: formMain.Close().
2. Is that OK to do since formMain called form2?

Sure. The forms don't have a hierarchical relationship. They are all
peers in the same application. Just because formMain's code is what
caused form2 to be shown, that doesn't mean there's an ownership
relationship there. Any non-modal form can close any other form.
3. And how would I know in form2 the FormClosing is invoked by user
clicking on form2's closing icon or invoked by formMain or form3?

Well, the simplest solution is in each form to have a flag that notes
whether the form's FormClosing event has been signaled yet or not. The
FormClosing handler can be written to not do anything if that flag is set.

Basically, in each form the FormClosing handler can check that flag, and
if it's not set it would close the other two forms (checking to make sure
they have been insantiated first, of course) and set the flag. That way,
even if when the other forms get their FormClosing event and try to close
the form that started the whole process, if that form's FormClosing event
gets fired *again*, it won't do anything.

Actually, it is my recollection that when I did this, I didn't have any
trouble with recursive closing. I don't recall if that's because I used
the Closed event rather than the FormClosing event (IMHO, the Closed event
makes more sense), or if it's simply because when a form is closed, the
WM_CLOSE message is posted rather than sent directly. But either way, I
don't think there was a conflict the way I did it.

You can easily test this out yourself. The issue should be minor, and
easily addressed if necessary.

Pete
Mar 29 '07 #10

P: n/a
On Wed, 28 Mar 2007 18:58:03 -0700, Pucca
<Pu***@discussions.microsoft.comwrote:
[...]
I tried closing the form from form2 and the FormClosed was looped through
many times and then I get a error message: An unhandled exception of type
'System.stackoverflowexception' occured in System.Windows.Forms.dll. Why
can't I close the calling form with the static form variable that stores
the calling form's handle?
You have an unterminated recursion, thus the stack overflow. I would
guess that your two forms are busy trying to close each other. One tries
to close the other, which then tries to close the first, which causes the
first to again try to close the other, and so on.

My previous post includes suggestions for how to work around just such a
problem. Have you tried any of those suggestions?
Also, the application stays in the task manager until I exit the VS.
Thank you.
As I mentioned, your application won't exit until all forms are closed
(and until all non-background threads have terminated, though you have not
made any mention of any other threads, so I assume that's not your
problem).

Also, you are still using this "child form" terminology. I recommend you
stop thinking of the forms as being children of other forms. There's no
such hierarchy for the non-modal forms, and I believe that treating them
as though there is may lead to conceptual misunderstandings that either
prevent you from solving problems, or cause bugs, or both.

Also, I don't understand the use of a static variable to keep track of a
form. I don't think it's necessary to keep track of any form (after all,
all of your forms should already have references within the namespace that
you can use directly), but assuming you feel it necessary to store a
reference in a variable upon creation of a form, that value should be
stored as a normal member within the instance of the created form.

Pete

Mar 29 '07 #11

P: n/a
Hi Pucca,

Yes the first solution is probably the simplest..

The reason I suggested use of group boxes that contain your data controls is
that rather than having to individually hide each control as the user clicks
next/previous (you would end up with a lot of similar-looking code), you can
simply hide the group box and all the contained data controls will be hidden
as well. For example if your GroupBox 1, representing your first form
contained 15 controls, you could set those 15 controls visible property to
true. When you hide the GroupBox, all the contained controls will also be
hidden in spite of the fact that you set the controls visible property to
true. The GroupBox is a special kind of control that has the ability to
'contain' other controls, and certain properties when set on teh container
will ripple down to the contained - one other option you might want to look
at is the "Panel" class which can also be used to to contain data controls
(the Panel container might even be a better option than the group box).

If you use either the group box or panel to contain your controls and design
them using the VS.NET forms designer, you will not need to 'create' forms at
runtime which is where problems seem to have been occurring..

"Also, if I make the control invisible, do I need to make them not able? "
<-- I'm not sure I understand this last question - did you mean editable? If
so, making a control invisible, does not require setting them to be
non-editable as by definition they are not visible for the user to perform
any kind of input...

Hope this helps..

Kind regards,
Patrick
--
Patrick Simpe-Asante
MCAD, MSCD.Net
"Pucca" wrote:
Hi Patrick, thank you for all the wonderful inupt. I think I willl be your
1st solution. My appliation is a import tool so they don't just have groupbox
on them. They have different controls and datagrids on each of the form. I
think I will have the main on the designer and then create the form2 and
form3 control upon loading of the formMain and hide them until they're
needed. Do you think this will work and is a good solution? Also, if I make
the control invisible, do I need to make them not able?
--
Thanks.
"Patrick Simpe-Asante" wrote:
Hi ,

I'm not sure whether design-wise what you have is the cleanest way to
achieve what you're looking for - this might also explain why you're running
into the kind of issues that you describe... I can suggest three other ways
that might make coding this a little more straightforward:

(1) A lightweight option could be to have one form, but with three separate
groupBoxes that 'simulate' a form each, each groupBox of which contains the
controls that you want to collect data in. Put a close, next and previous
button on the form, and as the user clicks through next/previous, hide/unhide
the groupBoxes. You could even create a sorted list populated with an enum
code + groupBox, and cycle over to the first groupbox 'form' when the user
clicks next past the third groupbox, or cycles backwards to the last groupbox
'form' when the user clicks previous past the first entry.. This is the most
simple to implement, however is probably the least amenable to change.

As an example, your next/previous button click events might look something
like (not compiled/tested):

private void btnNext_Click(object sender, EventArgs e)
{
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = false;
m_currentFormEnum++;
if (m_currentFormEnum == FormEnum.End)
m_currentFormEnum = FormEnum.Form1;
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = true;
}

private void btnPrevious_Click(object sender, EventArgs e)
{
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = false;
m_currentFormEnum--;
if (m_currentFormEnum == FormEnum.Begin)
m_currentFormEnum = FormEnum.Form3;
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = true;
}
(2) Another option, might be to represent each 'form' as a custom user
control, which each contain the native .NET controls used to capture your
required data. The user controls could have public properties that expose the
data that the user entersin them. Again, a single form will host the three
instantiated user controls, and you would have hide/unhide your custom user
controls as the user clicks through next/previous. This is a little bit more
work, however your new user controls will be re-useable elsewhere, and also
would have a nice separation from the hosting Form (which is a good thing).

(3) A third much more heavyweight option could be to use something like the
User Interface Process Application Block from Microsoft which enables you to
do what you're looking for, along with a whole lot more! You can find out
about the UIPAB from:
(1) http://msdn2.microsoft.com/en-us/library/ms979217.aspx
(2) http://www.codeproject.com/dotnet/UIPAB1.asp

Not sure why, but something tells me that there are many other possibilities
as well ;-).. Hope this helps you though...

Kind regards,
Patrick
--
Patrick Simpe-Asante
MCAD, MSCD.Net
"Pucca" wrote:
Hi, I'm using VS2005 and .net 2.0. I'm creating an application that has 3
forms. I want allow users to move forward and backward with the forms and
retain the data users have entered. I thought I'll make the inactive forms
invisible but this is creating a memory corruption problem when user close
the form2 or form3 and not the formMain.
>
My main form has a Next button which makes the main form invisible and
starts a new form which I'll call form2. The form 2 has a Previous and Next
button. The previous button would make the main form visiable again. The
next button would invoke a form3. both of these buttons would make form2
invisible. The form3 has a previous button to go back to form2 vislble and
make itself invisible. User can go forward and backward with these 3 forms.
>
Actually, I have a boolean variable in formMain and form2 to indicate if
form2 or form3 has been created. Since my application allows them to go back
and forward with these 3 forms I only want to make form2 and form3 visible if
they're already created.
>
I already tried have code in the closing event of form2 and form3 to try to
close it's calling form, namely form2 or formMain. But this doesn't work,
you see, when my code sets the calling form to visible=false, it
automatically callsing the form's Closing event. So, doesn't matter what
code I put there, it will get executed when I'm just setting the form to be
not visible.
>
My question is, if the user is closing the application either at form2 or
form3 then how do I make sure all forms are closed? Would coding to close
the main form automatically close all the chidren form in the approperate
order? If not, how can I address this? Becuase right now it's causing
memory correuption in my application. Thanks.
--
Thanks.
Mar 29 '07 #12

P: n/a
Hi Peter, I forgot to add the flag for the closed event. It is now working
when close from form2 or form3. Thank you for all your help through this
very confusing issue for me. I really appreciate it.
--
Thanks.
"Peter Duniho" wrote:
On Wed, 28 Mar 2007 16:26:02 -0700, Pucca
<Pu***@discussions.microsoft.comwrote:
The prblem is when user click to exit from form2 or form3. In form2
FormClosing event besides form3.close();
1. How does form2 inform formMain to close?

Same way formMain "informs" form2 to close: formMain.Close().
2. Is that OK to do since formMain called form2?

Sure. The forms don't have a hierarchical relationship. They are all
peers in the same application. Just because formMain's code is what
caused form2 to be shown, that doesn't mean there's an ownership
relationship there. Any non-modal form can close any other form.
3. And how would I know in form2 the FormClosing is invoked by user
clicking on form2's closing icon or invoked by formMain or form3?

Well, the simplest solution is in each form to have a flag that notes
whether the form's FormClosing event has been signaled yet or not. The
FormClosing handler can be written to not do anything if that flag is set.

Basically, in each form the FormClosing handler can check that flag, and
if it's not set it would close the other two forms (checking to make sure
they have been insantiated first, of course) and set the flag. That way,
even if when the other forms get their FormClosing event and try to close
the form that started the whole process, if that form's FormClosing event
gets fired *again*, it won't do anything.

Actually, it is my recollection that when I did this, I didn't have any
trouble with recursive closing. I don't recall if that's because I used
the Closed event rather than the FormClosing event (IMHO, the Closed event
makes more sense), or if it's simply because when a form is closed, the
WM_CLOSE message is posted rather than sent directly. But either way, I
don't think there was a conflict the way I did it.

You can easily test this out yourself. The issue should be minor, and
easily addressed if necessary.

Pete
Mar 29 '07 #13

P: n/a
On Thu, 29 Mar 2007 10:30:02 -0700, Pucca
<Pu***@discussions.microsoft.comwrote:
Hi Peter, I forgot to add the flag for the closed event. It is now
working when close from form2 or form3. Thank you for all your help
through this very confusing issue for me. I really appreciate it.
You're welcome. I'm glad everything worked out. :)
Mar 29 '07 #14

P: n/a
Thank you very much for all your great input. I've learned a lot from both
you and Peter.
--
Thanks.
"Patrick Simpe-Asante" wrote:
Hi Pucca,

Yes the first solution is probably the simplest..

The reason I suggested use of group boxes that contain your data controls is
that rather than having to individually hide each control as the user clicks
next/previous (you would end up with a lot of similar-looking code), you can
simply hide the group box and all the contained data controls will be hidden
as well. For example if your GroupBox 1, representing your first form
contained 15 controls, you could set those 15 controls visible property to
true. When you hide the GroupBox, all the contained controls will also be
hidden in spite of the fact that you set the controls visible property to
true. The GroupBox is a special kind of control that has the ability to
'contain' other controls, and certain properties when set on teh container
will ripple down to the contained - one other option you might want to look
at is the "Panel" class which can also be used to to contain data controls
(the Panel container might even be a better option than the group box).

If you use either the group box or panel to contain your controls and design
them using the VS.NET forms designer, you will not need to 'create' forms at
runtime which is where problems seem to have been occurring..

"Also, if I make the control invisible, do I need to make them not able? "
<-- I'm not sure I understand this last question - did you mean editable? If
so, making a control invisible, does not require setting them to be
non-editable as by definition they are not visible for the user to perform
any kind of input...

Hope this helps..

Kind regards,
Patrick
--
Patrick Simpe-Asante
MCAD, MSCD.Net
"Pucca" wrote:
Hi Patrick, thank you for all the wonderful inupt. I think I willl be your
1st solution. My appliation is a import tool so they don't just have groupbox
on them. They have different controls and datagrids on each of the form. I
think I will have the main on the designer and then create the form2 and
form3 control upon loading of the formMain and hide them until they're
needed. Do you think this will work and is a good solution? Also, if I make
the control invisible, do I need to make them not able?
--
Thanks.
"Patrick Simpe-Asante" wrote:
Hi ,
>
I'm not sure whether design-wise what you have is the cleanest way to
achieve what you're looking for - this might also explain why you're running
into the kind of issues that you describe... I can suggest three other ways
that might make coding this a little more straightforward:
>
(1) A lightweight option could be to have one form, but with three separate
groupBoxes that 'simulate' a form each, each groupBox of which contains the
controls that you want to collect data in. Put a close, next and previous
button on the form, and as the user clicks through next/previous, hide/unhide
the groupBoxes. You could even create a sorted list populated with an enum
code + groupBox, and cycle over to the first groupbox 'form' when the user
clicks next past the third groupbox, or cycles backwards to the last groupbox
'form' when the user clicks previous past the first entry.. This is the most
simple to implement, however is probably the least amenable to change.
>
As an example, your next/previous button click events might look something
like (not compiled/tested):
>
private void btnNext_Click(object sender, EventArgs e)
{
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = false;
m_currentFormEnum++;
if (m_currentFormEnum == FormEnum.End)
m_currentFormEnum = FormEnum.Form1;
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = true;
}
>
private void btnPrevious_Click(object sender, EventArgs e)
{
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = false;
m_currentFormEnum--;
if (m_currentFormEnum == FormEnum.Begin)
m_currentFormEnum = FormEnum.Form3;
((GroupBox)(m_groupBoxList[m_currentFormEnum])).Visible = true;
}
>
>
(2) Another option, might be to represent each 'form' as a custom user
control, which each contain the native .NET controls used to capture your
required data. The user controls could have public properties that expose the
data that the user entersin them. Again, a single form will host the three
instantiated user controls, and you would have hide/unhide your custom user
controls as the user clicks through next/previous. This is a little bit more
work, however your new user controls will be re-useable elsewhere, and also
would have a nice separation from the hosting Form (which is a good thing).
>
(3) A third much more heavyweight option could be to use something like the
User Interface Process Application Block from Microsoft which enables you to
do what you're looking for, along with a whole lot more! You can find out
about the UIPAB from:
(1) http://msdn2.microsoft.com/en-us/library/ms979217.aspx
(2) http://www.codeproject.com/dotnet/UIPAB1.asp
>
Not sure why, but something tells me that there are many other possibilities
as well ;-).. Hope this helps you though...
>
Kind regards,
Patrick
--
Patrick Simpe-Asante
MCAD, MSCD.Net
>
>
"Pucca" wrote:
>
Hi, I'm using VS2005 and .net 2.0. I'm creating an application that has 3
forms. I want allow users to move forward and backward with the forms and
retain the data users have entered. I thought I'll make the inactive forms
invisible but this is creating a memory corruption problem when user close
the form2 or form3 and not the formMain.

My main form has a Next button which makes the main form invisible and
starts a new form which I'll call form2. The form 2 has a Previous and Next
button. The previous button would make the main form visiable again. The
next button would invoke a form3. both of these buttons would make form2
invisible. The form3 has a previous button to go back to form2 vislble and
make itself invisible. User can go forward and backward with these 3 forms.

Actually, I have a boolean variable in formMain and form2 to indicate if
form2 or form3 has been created. Since my application allows them to go back
and forward with these 3 forms I only want to make form2 and form3 visible if
they're already created.

I already tried have code in the closing event of form2 and form3 to try to
close it's calling form, namely form2 or formMain. But this doesn't work,
you see, when my code sets the calling form to visible=false, it
automatically callsing the form's Closing event. So, doesn't matter what
code I put there, it will get executed when I'm just setting the form to be
not visible.

My question is, if the user is closing the application either at form2 or
form3 then how do I make sure all forms are closed? Would coding to close
the main form automatically close all the chidren form in the approperate
order? If not, how can I address this? Becuase right now it's causing
memory correuption in my application. Thanks.
--
Thanks.
Mar 30 '07 #15

This discussion thread is closed

Replies have been disabled for this discussion.