After an immense amount of reasearch I am still no closer to a solution.
I have a simple app, 2 forms .NETv3.5 C#.
The application loads the first form, i press 'X' on the windows bar.
The application hides the form and continues to run without exiting the application even though the only form loaded is closed.
The main form Closing method does not get called when the X is pressed because the form is hidden when the x is pressed. Form.Deactivated is called but not Form.Closing.
How can i catch the the even when the X is pressed ? (Then I can implement Application.Exit())
Check if you have timer or thread that is running. If so stop those.
I guess in Program.cs, you call Application.Run passing the main form as parameter. If so, the app won't exit until the main form closes.
To catch the event when X button is pressed, add event handler to secondary form's Closed event, not the main form's. In that event, call main form's Close method (or Application.Exit).
Related
Background:
I am creating a WinForms app using C# 4.0 and VS2013. My app has a main form named ParentForm and a secondary form named ChildForm. The application follows an Model-View-Presenter design, so I want my presenter class P to control all the form opening, closing, button clicks, and generally anything the user requests. (Both forms are actually abstracted behind "view" interfaces, but the problem is specifically with the WinForms implementation, so let's ignore the interfaces.)
Problem:
Currently P is handling FormClosing events for both ParentForm and ChildForm, and calling Form.Close or Form.Dispose if it determines that the user is allowed to close these forms.
The problem I'm having is if ChildForm is open and the user clicks the 'X' button on ParentForm. In this scenario, FormClosing is called first on ChildForm, then on ParentForm. P doesn't have any way of knowing whether the user clicked 'X' on ChildForm (which P should react to by closing ChildForm), or the user clicked 'X' on ParentForm (which P should react to by confirming if the user really wants to exit, before closing any forms).
Questions:
Is there a way to tell if FormClosing is being called in reaction to a parent form closing?
Is there any way to treat the 'X' button like a normal button?
Is there a way to prevent child form closes until after the parent form's FormClosing event (and possible user cancellation)?
You can use FormClosingEventArgs.CloseReason property, which according to MSDN
Gets a value that indicates why the form is being closed.
See the CloseReason Enumeration values, in particular FormOwnerClosing and MdiFormClosing.
I'm trying to make a new form appear when I click on a label. I'm using Windows Application Forms.
Here's the code:
private void label1_Click(object sender, EventArgs e)
{
Form parpokeru = new Form();
parpokeru.Show();
parpokeru.ShowDialog();
}
When I click on the label, a error appears (Unhandled exception has occurred in your application...). Can anyone tell me how to fix it?
Call .Show() or .ShowDialog(). Not both.
Show() will display your second form, while still allowing the user to access the first form.
ShowDialog() will display your second form as "modal". Execution of code in the first form stops while the second form is open (at least on the main thread.. for example, timers will continue to run), and the user will not be able to access your first form while the second is open.
When you call the Show method your form is shown on video like another window and the code returns immediately from the call. So your code continues and all the forms of your application are available for the user interaction. It is calledd a modeless dialog
On the contrary, ShowDialog is a blocking call. The code doesn't return from this call until something happen inside the called form that terminates the visualization of the form. As an example comes to ming a call to the methid Hide or a click on a button with its DialogResult property set to something different from DialogResult.None. At this point the code from ShowDialog returns and the normal processing continue. While the code is blocked inside the ShowDialog the application is blocked and the user cannot interact with other forms or menus or whatever is displayed on video. It is called modal dialog
Another difference is ShowDialog returns value (a DialogResult enum value) that can can be used to determine how the user closed the form (DialogResult.Cancel, DialogResult.OK), also ShowDialog does not call the Dispose method at closing time. This will allow to retrieve property from the Modal Dialog like user inputs for further processing.
I cannot imagine what happen in the internal processing of your form if, after a modeless call to Show you call immediately a ShowDialog on the same form instance. However, an exception is really the minimum to expect from this code.
Suppose that I have Form1 as a parent from in a MDI Windows forms application.
It has a btnStart button, which simply does a lot of calculation, let say:
double i;
while(blnContinue)
{
i=(i+1)%100000;
}
Form2 is a child with btnStop button, which simply assign blnContinue = false; so that the while loop breaks;
But the point is that, the Form2 cannot raise the event when the btnStop is pressed.
In this case, it's straightforward to make the function containing the while loop in a separate thread and create the btnStop in the parent form.
But I must do the "infinite" while loop in the main thread, so I it's not allowed to
make it as a thread and start/stop it.
Anyone knows how to process the event of the Form2?
Thanks in advance!
You will need to call Application.DoEvents inside the loop, say every 100ms. I don't think there is any other option. Without that your entire app will appear locked and no events will fire anywhere so no chance to do anything. Is there something stopping you using another thread?
I have two .net 2 winforms, each has its own project. project 1 is main form and project 2 is a child form. and now I would like to know how to make the child form close it self if main form is no longer active.
killing child form on exit doesnt work, because main form can be killed by task manager.
you need to handle the OnClosing event of main form where you can close any child forms.You need to have a member variable of a child form in main.
If I understand correctly, what you call a 'child form' is actually another WinForms app running in a separate process?
In addition, I take it (from your "because main form can be killed by task manager" comment) that you want the exiting behaviour to be resilient to cases when the main-app is forcefully killed.
One way would be to get the 'child app' to listen to the Process.Exited event of the 'main app', and exit if it fires.
I imagine it would look something like:
public Form1()
{
InitializeComponent();
// You need to figure out how best to do this part.
// Also, what to do if the main-app isn't already running.
var mainAppProcess = Process.GetProcessesByName("MainApp").First();
mainAppProcess.EnableRaisingEvents = true;
// Close the form when the other process exits.
mainAppProcess.Exited +=
delegate { BeginInvoke(new Action(Close)); };
}
In my application I want to show a login form first and then the main form if the login has been successful. Currently I'm doing it something like this:
var A = new LoginForm();
if ( A.ShowDialog() == DialogResult.OK )
Application.Run(new MainForm());
But then I started wondering - what's the point of the Application.Run()? Why not just do (new MainForm()).ShowDialog() as well? What's the difference? And what would be the correct way to achieve what I want?
Application.Run(Form) starts a message loop on the current thread and displays the specified form. The message loop enables the form to receive Windows messages (eg, key presses, mouse clicks, paint invalidations) to allow it to appear responsive and have interaction with the user. When you call ShowDialog() on a Form instance, it actually does a similar thing and creates a modal message loop for the form on which ShowDialog has been called.
There is not much difference between the two calls. Application.Run does add some extra event handling enabling you to do some tidying up of resources when the main form is closed (see Application.ThreadExit).
The recommended way to start WinForms applications is using Application.Run, but I suspect this is more of a convention than a rule. The biggest reason to use Application.Run is if you want to open multiple non-modal forms. You can do this using:
new Form().Show();
new Form().Show();
Application.Run();
You could not achieve this using the ShowDialog() method as one of the forms would have to be modal.
As for your question of how to show a login form and then the main form if the login is successful, I think what you have is fine:
if (new LoginForm().ShowDialog() == DialogResult.OK)
{
Application.Run(new MainForm());
}
The alternative is to do the plumbing yourself and open an instance of MainForm in the closing event of the LoginForm if the login was successful.
From MSDN:
This method adds an event handler to
the mainForm parameter for the Closed
event. The event handler calls
ExitThread to clean up the
application.
http://msdn.microsoft.com/en-us/library/ms157902.aspx
From my testing, I noticed this main difference:
When Application.Run is used, the form's Close button (red X) returns DialogResult.None; however, when ShowDialog is used, the Close button produces DialogResult.Cancel.
Does this matter to you? In my code, I was testing for DialogResult.Cancel to determine the exit code of my application. That was broken when the red X was used to close the form. I now test for DialogResult.OK to indicate a successful exit.
return myForm.DialogResult == DialogResult.OK ? 0 : 1;
One key difference is that ShowDialog is usually a modal Dialog. If you wanted to create a user-friendly toolset, you would not want it to be comprised of modal dialog boxes.
Also, Application.Run() accepts more than just a form. It has a few overloads.
As for your application, I do not think it matters much. Application.Run makes sense to me because it denotes the start of your actual Application.
The documentation of the overload
public static void Run(
ApplicationContext context );
has a neat example with a different approach that involves two forms as well.
For a more concerete example of a difference:
If your main form is an MDI form, then the behavior on clicking the close button (the 'x' in the upper right, or Alt-F4) is different depending on which method you use to show the form.
With Application.Run(mainForm), the closing event of the child forms run, then the main form's closing event runs.
With mainForm.ShowDialog, the closing event of the main form runs, and the closing event of the child forms do not run.
Application.Run() is for the start of application while MainForm is part of the application and MainForm()).ShowDialog() used to display it only.
Application.Run() is the entry point for your Application. same as Main() method is for some class or ApplicationStart() for a WebApplication
Application.Run() has different overloads, one of which is without parameters. That Method starts application without an initial form.
From my testing I notice that using Application.Run buttons with DialogResult does not close the form (OnFormClosing is not hit) compare to ShowDialog in which the buttons with DialogResult hit OnFormClosing and the close the form.