Within the application I am writing for testing/learning C#, I use the hidden/visible property to open and close windows.
It is a WPF application.
In the main window, I have a "close" button that triggers this method:
public void buttonQuit_Click(object sender, RoutedEventArgs e)
{
var message = exitmessage;
var title = exitTitle;
var result = MessageBox.Show(
message, // the message to show
title, // the title for the dialog box
MessageBoxButton.YesNo, // show two buttons: Yes and No
MessageBoxImage.Question); // show a question mark icon
// lets see what has been pressed
switch (result)
{
case System.Windows.MessageBoxResult.Yes: // Yes button pressed
CloseAllWindows();
break;
case System.Windows.MessageBoxResult.No: // No button pressed
break;
default: // Neither Yes nor No pressed (just in case)
MessageBox.Show("Oh noes! What did you press?!?!");
break;
}
}
This way I make sure that all windows get closed, including the hidden ones.
But now is the catch; when the user presses (in the main window) the top right red X in toolbar to close, only that main window gets closed, but in the background the hidden ones are still there.
So in fact it is 2 questions:
Is CloseAllWindows(); really sufficient to get the app 100% closed down?
How do I "catch" the event when the user presses that red X in the toolbar, and make this also trigger the right closing event?
You should be handling either the Closing or Closed event for your window(s). The former allows you to cancel the close, while the latter just allows you to perform necessary cleanup in response to the window being closed.
So, in this case, you should place the code from your buttonQuit_Click method into a handler method attached to the Closing event so that it gets triggered regardless of how the window is closed.
Then, your buttonQuit_Click method can simply call the window's Close method. That will close the window, in turn raising the Closing event, and running your code in the attached handler method.
As far as your other question, CloseAllWindows will do exactly what it says: it will close all of the windows that your application has opened. In most cases, that should be sufficient to close the application, but it might not be, especially if you've created non-background threads or depending on the ShutdownMode setting.
App.Current.Shutdown will work unconditionally.
You could use the Closing event of the window for that.
Some more info
http://msdn.microsoft.com/en-us/library/system.windows.window.closing.aspx
Related
I've built a Windows form application which contains some forms. I would like to create a button on a certain form which saves its state.
For example, if I have a textbox in which a user typed "Hello" and pressed the save button, when he goes back to this form, the textbox would still say "Hello". I want it to happen only in the same execution of the program, which means when the program closes and reopens, the textbox wouldn't say "Hello" anymore (which is why Settings don't fit my need I believe, because they keep the changes between executions).
Since you only want the form to retain its state while the application is running, the solution is very simple: never close the form, just hide it. When you're ready to display it again, show it. It will re-appear on the screen, everything exactly as it was left. (Unless, of course, you loop through the controls and reset their properties.)
In the simplest case, you accomplish this by substituting calls to this.Close with this.Hide. But it is likely more complicated than that, since the user can close your form with the big red X. To ensure all attempts to close the form are stealthily rerouted as requests to hide the form requires some minor finesse:
private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true; // cancel the request to close
this.Hide(); // hide the form instead
}
}
Note that this code checks the close reason and ensures that it's a user-initiated close request. This is very important. If you omit this part, you can't close the form programmatically, either!
Store your data in static variables and they will live until you close your program.
static string textboxText = textbox1.text;
Should sound weird, but this is just for my hobby. I would want a (custom) messagebox to pop up with a YesNo buttons which should ideally block the code. But I should be able to click on the parent form so that I can dismiss the message box without having to specifically click on the messagebox buttons (equivalent to clicking No on the message box)..
something like this:
void Foo()
{
CustomMsgBox.Show("do you really wanna delete?", CustomMsgBox.Buttons.YesNo);
//block the code here, but user should be able to click on form, so that its equivalent to have clicked No;
//if clicked No, return;
//delete.
}
So the solution I thought was make the custom message box non modal - so that user can click on form, but I'm not able to block code.. How can i do that?
It would look like this:
void Foo()
{
NonModalMsgBox.Show("do you really wanna delete?", CustomMsgBox.Buttons.YesNo);
//block thread till user clicks on form or messagebox buttons.
//unblock when user clicks.
//if No, return;
//delete.
}
Edit: I know this is not a standard practice and I know non modal forms do not block, while modal forms do. So please do not recommend to be content with either modal form's or non-modal form's behavior. My question would be is there any way to simulate the behaviour of ContextMenu with windows forms.
You can solve this quite easily. Create and use a modal dialog but override the WndProc of the dialog and process the WM_MOUSEDOWN event. Check the position of the mouse down and if it is over the parent window but not over the dialog itself then simply dismiss the dialog.
Essentially you can't do this in a 'blocking' call easily. What you could do easily enough is to either pass the information required to perform the delete, or a delegate to perform the operation, to the form. When they click Ok you simply perform the operation. If they activate the parent form, then just close the child.
You want the user to be able to click the background window to cancel the dialog box? Add a handler to the background window so that when the user clicks on it you check to see if the non-modal window is displayed, if so close it.
Sounds easy, but you will need to be careful to handle every possible click on the background window and child windows. That sounds like a can of worms I wouldn't want to go down.
Perhaps instead you could detect if the non-modal dialog box loses focus and automatically close it. I can see this behavior making sense for a simple "confirm delete" dialog box, but as a user my first reaction is going to be to spam the ESC key to close the dialog box.
Another way of handling this is by manually enabling the parent form when calling ShowDialog, from here
[DllImport("user32.dll")]
private static extern bool EnableWindow(IntPtr hWnd, bool enable);
internal static DialogResult ShowDialogSpecial(this Form formToBeShown, Form parent)
{
parent.BeginInvoke(new Action(() => EnableWindow(parent.Handle, true)));
formToBeShown.ShowDialog(parent);
return formToBeShown.DialogResult;
}
Just call the extension method from any parent form like this:
var f = new Form();
f.ShowDialogSpecial(this);
//blocks but parent window will be active.
Of course you need to handle the clicks on parent form to close child form.
You could do something like:
public void ShowMe() {
Show();
while (!_receivedDeactivateEvent)
Application.DoEvents();
}
I'm not sure I'd recommend it, though -- I'm not sure how stable it would be, nor am I sure whether it would behave the way you want if you click the Delete button on the parent form while the 'dialog' is up (would it close the first dialog first, or leave it up? might be the latter, which could get messy).
An easier way: set form's "TopMost" property to be True. Then it will act like blocking
I'm writing a Windows application that basically runs in the background with a notification icon to interact with it. The notification icon can do basic things like exit the application or show information about it. It can also launch a modal configuration dialog.
The code that creates the dialog is pretty straightforward:
using(var frmSettings = new SettingsForm(configuration))
{
frmSettings.ConfigurationChanged += ConfigurationChangedHandler;
frmSettings.UnhandledException += UnhandledExceptionHandler;
frmSettings.ShowDialog();
}
The SettingsForm class basically has three GroupBox controls, with a Label and TextBox control in each, and 4 Button controls at the bottom: "Advanced...", "Restore Defaults", "Cancel", and "Apply". Each TextBox has a Validating event handler wired up through the designer. Each button has a Click handler wired up through the designer. Each of them does pretty obvious things: opens another modal dialog with more advanced settings, restores the textboxes to their default values, closes the dialog, or saves the changes, fires the ConfigurationChanged event, and then closes the dialog (but only if all fields are valid!).
When there is a form entry error I cancel the corresponding Validating event by setting ((CancelEventArgs)e).Cancel = true. However, the default behavior of both forms was to prevent the user from changing focus when validation failed. I found this pretty annoying and eventually found the option in the designer to still automatically validate when the user leaves the field, but to allow them to leave even if validation fails: AutoValidate = EnableAllowFocusChange.[1]
My "Apply" button Click handler looks basically like this:
private void btnApply_Click(object sender, EventArgs e)
{
try
{
if(this.ValidateChildren())
{
this.Configuration.Field1 = this.txtField1.Text;
this.Configuration.Field2 = this.txtField2.Text;
this.Configuration.Field3 = this.txtField3.Text;
if(this.Configuration.Changed)
{
this.Configuration.Save();
this.OnConfigurationChanged(new ConfigurationChangedEventArgs(
this.Configuration));
}
this.Close();
}
}
catch(Exception ex)
{
this.OnUnhandledException(new UnhandledExceptionEventArgs(
"Failed To Apply Configuration Settings",
ex));
}
}
I'm currently testing out the code by breaking on the first line and stepping through the method line by line. Essentially, ValidateChildren is returning false as expected and the entire if block, including the this.Close() are skipped. Yet, if I step all the way to the bottom of the method and then step out of it I end up back on the frmSettingsForm.ShowDialog() line and the form is magically closed.
The "Apply" button is set as the form's AcceptButton. I wonder if it's implicitly attached a handler to the button's Click event to automatically close the form when the button is pressed. That doesn't sound like it logically should be assumed, especially considering there doesn't seem to be a way to cancel the Click event, but it's the only explanation that I can come up with. To test that theory, I have tried unsetting the AcceptButton in the designer, but my form still closes when the data is invalid.
What is closing my form and how do I stop it?
[1]: If anybody else has trouble finding it, it's a form property, not a property of each individual control (as I expected it would be).
Do you have the DialogResult of the Button set? If so, when you click the Button, the DialogResult of the Form will be set to that value and the modal Form will close. To prevent this, when validation fails in your Click handler, set the Form's DialogResult to DialogResult.None.
I don't know why that happens, but you could override the event OnFormClosing and check for the value of DialogResult according to your logic.
If (DialogResult != Windows.Forms.DialogResult.Cancel )
e.Cancel = True
I want to capture events that close editor window (tab) in Visual Studio 2008 IDE.
When I use
dte2.Application.Events.get_CommandEvents(null, 0).BeforeExecute
I successfully captured such events:
File.Close
File.CloseAllButThis
File.Exit
Window.CloseDocumentWindow
and others.
If code in window is not acceptable, I stop the event (CancelDefault = true).
But if I click "X" button on the right hand side, "Save Changes"; dialog appears, tab with
editor window close and I have no any captured events. In this case I can capture WindowClosing event,
but can not cancel the event.
Is it poosible to handle "x" button click and stop event?
In C# it would be something like this: you add Closing event handler and then
void MyWindow_Closing(object sender, CancelEventArgs e)
{
if(something)
e.Cancel = true; //<- thats the magic part you want
}
I would suggest, check on the lines of handling MDI Child window events!!
The editor tab you are referring is basically an instance of MDI Child Window.
Hope this helps!
If you're willing to use some Windows API code you might be able to set up a hook using the SetWindowsHookEx function to intercept WM_CLOSE, WM_QUIT and WM_DESTROY.
Is there an event that is fired when the user presses the close button?
This is because the Window Closing event is fired both when one closes the window manually (with the Close method) and also when the user presses the [X] button...but I somehow need to know only when the user presses the [X] button not when the window is closed manually.
I don't believe there is a way to tell those apart in WPF (though I'm not positive).
The way I always handled it in WinForms was to create a member variable "_Closing", set it to false, and a method "ReallyClose()" that would set _Closing to true, then call Close. My Closing handler would then cancel the close if _Closing was not set to true.
Yeah, it's a bit of a hack, but it worked.
I also don't think there is a way to tell them apart. You can put a handler on the Application.Exit event, but it doesn't distinguish between "red X button close" and "alt-F4 close" (or whatever other types of close you are considering).
BTW, if you check for Application.Exit, be sure to check for Application.SessionEnding too - if someone logs off while your app is running, you can't be guaranteed that Application.Exit will be called.
Try to put button with name Cancel and bool variable in your class so When you click on button set it to the true and in Closing Event check if is true use e.Cancel=false to exit window I tried everything and It doesn't work for me and I do on this way and also you can remove X button just to have Accept ot Cancel buttons if you insert some informations.