App Current Shutdown closing window prompting - c#

I have a wpf project which has couple of windows, whne i navigate from one window to other i just hide one window and create instance of other if not created already, otherwise just make it visible
in all windows there is window closing event handler
private void Window_Closing_1(object sender, CancelEventArgs e)
{
{
string message = "You are trying to close window " + this.Name + " .Are you sure?";
string caption = "Exit";
MessageBoxButton buttons = MessageBoxButton.YesNo;
MessageBoxImage icon = MessageBoxImage.Question;
if (MessageBox.Show(message, caption, buttons, icon) == MessageBoxResult.Yes)
{
App.Current.Shutdown();
}
else
{
MessageBox.Show("Closing aborted");
}
}
but problem is this event is there in every window so when i close it lots of other prompt from other window which are invisible also show up. Is there a way to avoid other pronpts if i close in only one window?

Have you tried in App.xaml to add Exit attibute?
it will be a better solution since you will only have to write this confirmation exit code just once. about window name you could cast sender to window in order to find out its name

just create a static method in another class to handle closing of forms.
public class X
{
private static bool isClosingHandled = false;
public static void HandleClose()
{
//// app closing logic
isClosingHandled = true;
}
}
private void Window_Closing_1(object sender, CancelEventArgs e)
{
X.HandleClose();
}

Related

Switching between Window Forms does not seem to work

Hey there StackOverflow community!
So I've been working on an application that checks if the user has entered valid credentials in a Login() form, then it switches over to an Intro_Sequence() form (where a .mp4 file is played in fullscreen mode) as a sort of aesthetic addition to the app. So far so good, no problems whatsoever.
The problem comes right after the Intro ends, where supposedly the application should switch over to a third form, called Main().
I have implemented a check whenever Windows Media Player (aka axWMPLib) changes its PlayState to see whether it has finished the playback.
If it has, then the Hide() event is called to conceal the current Form's window, then main.ShowDialog() should open the third form.
Afterwards, I call the Close() event to close the previous Form's window entirely.
Here is the code so far:
public partial class Intro_Sequence : Form
{
public static string Username;
public Intro_Sequence(string username)
{
InitializeComponent();
Username = username;
FormBorderStyle = FormBorderStyle.None;
Bounds = Screen.PrimaryScreen.Bounds;
TopMost = true;
intro.uiMode = "none";
intro.URL = AppDomain.CurrentDomain.BaseDirectory + "\\Intro.mp4";
intro.enableContextMenu = false;
DisableMouseClicks();
}
private void DisableMouseClicks()
{
if (this.Filter == null)
{
this.Filter = new MouseClickMessageFilter();
Application.AddMessageFilter(this.Filter);
}
}
private MouseClickMessageFilter Filter;
private const int LButtonDown = 0x201;
private const int LButtonUp = 0x202;
private const int LButtonDoubleClick = 0x203;
public class MouseClickMessageFilter : IMessageFilter
{
public bool PreFilterMessage(ref System.Windows.Forms.Message m)
{
switch (m.Msg)
{
case LButtonDown:
case LButtonUp:
case LButtonDoubleClick:
return true;
}
return false;
}
}
private void Intro_Sequence_Load(object sender, EventArgs e)
{
}
private void intro_PlayStateChange(object sender, AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e)
{
if(intro.playState == WMPLib.WMPPlayState.wmppsMediaEnded)
{
Main main = new Main(Username);
this.Hide();
main.ShowDialog();
this.Close();
}
}
}
As you can see I have also added a filter to block clicks during playback, so as not to allow the user to pause it.
However, when I execute this code, it works perfectly fine until it finishes the video and then closes abruptly.
I tried putting breakpoints and everything seems to be fine.
It does call everything I tell it to call, yet the form doesn't even appear.
I have also tried several other alternatives, like not closing the Form at all, calling Show() instead of ShowDialog() and even not Hiding it at all.
It is as if it either freezes there or closes instantly without any sign of the Main form showing.
I also tried calling the Main() form from the Login() and it works perfectly from there.
I really don't know what is going on.
Any help would be appreciated.
How about something like this?
There are three forms. There's a Login form (in this case, it's just an empty form - you close it by clicking on the red X). It is popped up modally from within the Main form (while the main form is hidden).
There's a Splash screen on which your video is to play. I fake out the video by using await Task.Delay(4000); to get a pause. After the 4 second delay, I raise an event (equivalent to your media player event). What I do is show this modally from the main form. I put the event handler in this form; when the event is raised, I close the splash screen modal. The entire (non-designer) code for that form looks like (and, since there are no controls on this form, the designer code is pretty lean):
public partial class SplashScreen : Form
{
public event EventHandler SplashFinished;
public SplashScreen()
{
InitializeComponent();
this.SplashFinished += SplashScreen_SplashFinished;
}
private async void SplashScreen_Load(object sender, EventArgs e)
{
await Task.Delay(4000);
SplashFinished?.Invoke(this, new EventArgs());
}
private void SplashScreen_SplashFinished(object sender, EventArgs e)
{
this.DialogResult = DialogResult.OK;
this.Close();
}
}
Then there's the Main form. It gets fired up in the normal way from Program.cs:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
The only thing that I added to that form (from the out-of-the-box code) is:
private void Form1_Load(object sender, EventArgs e)
{
this.Hide();
var login = new LoginForm();
//should really check this, but for now
login.ShowDialog(this);
var splash = new SplashScreen();
splash.ShowDialog(this);
this.Show();
}
So, when the app starts, the user is shown the login form (the main form is hidden). He does what is needed to do (and the result is checked in the main form's Form1_Load handler.
If everything is cool, a new SplashScreen form is created and shown modally. When it pops up, the video starts (in this case, the video is simply an asynchronous timer). When the video ends, the SplashScreen handles the finished event, and uses it to close itself.
Once control returns to the main form, it displays itself.

How to do something after clicking on MessageBox button, but before this MessageBox closes?

I have a list of "projects" with some informations in textBoxs for each project. The user can select a project then modify the informations and click on save button after that.
If I changes selected project without save the modifications, a Yes/No MessageBox appear:
DialogResult dialogResult = MessageBox.Show(
"Do you want to save changes ?",
"Title",
MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
//Click Yes
}
else
{
//Click No
}
I would to refresh all the project list (with my own Refresh() methode) after clicking on Yes/No button, but staying on the MessageBox until the refresh is done.
Is it possible?
The built in MessageBox class does not allow such complicated behaviour.
One way to do this is to create your own message box. Create a subclass of Form, add some labels and buttons. Expose some events like YesClicked and NoClicked.
In your main form, create an instance of your custom message box, subscribe to the events, and call ShowDialog on it.
After the refresh is done, you can call Close or Dispose on your custom message box to close it.
Try creating a custom message box. I commented the code, let me know if you need clarification
public static class MessageBoxResult
{
public static int dialogResult; // <== i use this value to determine what button was pressed
}
// your custom message box form code
public partial class CustomMsgBox : Form
{
public CustomMsgBox()
{
InitializeComponent();
}
public void show(string pos0, string pos1, string pos2, string message) //<=== initializing the message box with the values from your main code
{
button1.Text = pos0;
button2.Text = pos1;
button3.Text = pos2;
label1.Text = message;
}
// message box events to set the static field incase a button on the custom form was changed
private void button1_Click(object sender, EventArgs e)
{
MessageBoxResult.dialogResult = 0;
this.Close();
}
private void button2_Click(object sender, EventArgs e)
{
MessageBoxResult.dialogResult = 1;
this.Close();
}
private void button3_Click(object sender, EventArgs e)
{
MessageBoxResult.dialogResult = 2;
this.Close();
}
}
//usage
{
MessageBoxResult.dialogResult = -1; // <== setting the static field to -1 to mean nothing was pressed
CustomMsgBox cMsgBox = new CustomMsgBox();
cMsgBox.show("your message");
cMsgBox.ShowDialog();
}
You can change what happends, based on what button is clicked, with the DialogResult
DialogResult dialogResult = MessageBox.Show(#"Some body", #"Title", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
// do stuff
}
No, a message box cannot do this. It's not meant to do this. It's meant to just display a message... in a box :)
What you can always do is create your own window that looks like a message box and behaves like a message box, but actually does things when you click the buttons.

C# Game Menu Form ( Username, Start, Exit )

i'm new to the programming went through few tutorials and sample projects and then started to create my own text based adventure game with some UI.
So what i'd like to achieve with the beginning of my project is, when user launches exe, i'd like to greet them with a username input screen with Start and Exit buttons and then close that form, launch a new form which i'll put in the game's main interface.
So, when i click the "Start" Button, it'll read the username from the textbox, save it to a string, close the form and launch a new form with also using the name screen in the game's main interface.
My question is, How can i link the start button from the below code to a new Form, also closing the current AUJFM_Login form, which will also be able to read the string username.
I have tried few things but after a few attempts, i just left it with the button functions. It's not much but here is the basics of it:
The Greeting screen will be called AUJFM_Login, and the main interface will be called AUJFM.
namespace AUJFM
{
public partial class AUJFM_Login : Form
{
public AUJFM_Login()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
string UserName = nameBox.Text;
}
private void btnExit_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
You can try the code below for the “Start” button click. I added a method to check the user name as it seems like sending an invalid user name to the next form is simply a waste of time. You will have to adjust this method to check for the valid users. Hope this is what you are looking for.
private void btnStart_Click(object sender, EventArgs e) {
string userName = nameBox.Text;
if (ValidUserName(userName)) {
SecondForm nextForm = new SecondForm(userName);
nextForm.Show();
this.Hide();
} else {
// user name not valid
}
}
private bool ValidUserName(String userName) {
// logic to check if user name is valid
return true;
}
Then in the second form constructor, change the signature to accept the user name string.
public SecondForm(string userName) {
InitializeComponent();
textBox1.Text = userName;
}
If you have a form for the main window (Let's call it MainForm),
you can do:
MainForm mainForm = new MainForm();
mainForm.Show();
The main window would then appear.
To close the login form, you could do
this.Hide();
Since closing the form from which the application runs would close the entire application.

WPF close all window from the main window

I have login window. From this login window, i am intializing the main window.
Once login successfully happened, i close the login window.
Now i am having two other windows, which i am calling from Main Window.
Once i close the main Window, I am able to close the other two windows as well as Main Window.
But program still runs in memory. I have to close it manually from the Visual Studio.
How should i close the Program all instances fully??
This is the Main window Close Event code.
private void usimClose(object sender, EventArgs e)
{
newScreen2.Close();
newScreen3.Close();
this.Close();
}
This is my Login Window Code. Once the user click on the submit button.
private void btnLogin_Click(object sender, RoutedEventArgs e)
{
if (txtUserName.Text.Length == 0)
{
errormessage.Text = "Please Enter UserName";
txtUserName.Focus();
}
else
{
LoginStatus _status = _Login.LoginUsimgClient(txtUserName.Text, txtPassword.Password.ToString());
if (_status.BoolLoginstatus)
{
mainWindow.RunApplication();
string struserName = _status.StringUserFirstName;
mainWindow.userName.Text = "Welcome " + struserName;
mainWindow.Show();
this.Close();
}
else
{
errormessage.Text = _status.StringErrorDescription;
txtUserName.Text = String.Empty;
txtPassword.Password = String.Empty;
}
}
}
Try Application.Current.Shutdown();
From MSDN
Calling Shutdown explicitly causes an application to shut down,
regardless of the ShutdownMode setting. However, if ShutdownMode is
set to OnExplicitShutdown, you must call Shutdown to shut down an
application.
Important note
When Shutdown is called, the application will shut down irrespective
of whether the Closing event of any open windows is canceled.
This method can be called only from the thread that created the
Application object.
You can close all windows using this
App.Current.Shutdown();
or
you can manually close it
Window parentwin = Window.GetWindow();
parentwin.Close();
If you starting point is your MainWindow, then just start there.
Firstly, host the LoginForm in your MainWindow, and show it using ShowDialog() to force the user to interact with the LoginForm. Return the result of a successful/unsuccessful interaction to the MainForm.
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
var form = new LoginForm();
var result = form.ShowDialog();
if (result ?? false)
{
// Carry on opening up other windows
}
else
{
// Show some kind of error message to the user and shut down
}
}
Otherwise, technically your LoginForm is hosting your MainForm which is, frankly, odd.
Have a look at my answer here: How to close wpf window from another project
An Application.Current.Shutdown() will stop the application in a very abrupt way.
It is better to gracefully keep track of the windows and close them.

Windows Forms Remove Close Button

I'm working on a Windows Forms app and I'm wanting to remove the close button from the top. I'm aware of the ControlBox option, but I'm wanting to provide a help button. Is there a way to have the Close button not visible while maintaining the help button?
Your best bet may be to subcribe to the FormClosing event of the form like so and cancel the closing action:
// In your code somewhere subscribe to this event
Form1.FormClosing += Form1_FormClosing;
void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
}
The benefit of doing this is that it prevents the user from closing the application from the close button and the taskbar.
Obviously you don't want to ALWAYS cancel the form from closing. So you will want to set some type of boolean flag that you will check in the event listener as to whether you want the form to be allowed to close or not. Example:
void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (BlockClosing)
e.Cancel = true;
}
EDIT: If you don't want to approach the problem that way, and you really do intend to completely remove the close button, then your best bet is to create your own custom title bar. In that case, you set the form's FormBorderStyle property to None. And you then dock your custom title bar to the top of the form. Here is some sample code from one I made a while back:
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace Spectrum.UI
{
public partial class TitleBar : UserControl
{
public delegate void EventHandler(object sender, EventArgs e);
public event EventHandler MinButtonClick;
public event EventHandler MaxButtonClick;
public event EventHandler CloseButtonClick;
#region Properties
[Category("Appearance")]
public string Title
{
get { return TitleLabel.Text; }
set { TitleLabel.Text = value; }
}
[Category("Appearance")]
public bool MinimizeEnabled
{
get
{
return minButton.Visible;
}
set
{
minButton.Visible = value;
}
}
[Category("Appearance")]
public bool MaximizeEnabled
{
get
{
return maxButton.Visible;
}
set
{
maxButton.Visible = value;
}
}
#endregion
public TitleBar()
{
InitializeComponent();
ShowTitleBarImage = false;
}
#region Mouse Events
private void TitleBar_MouseDown(object sender, MouseEventArgs e)
{
this.OnMouseDown(e);
}
private void TitleBar_MouseUp(object sender, MouseEventArgs e)
{
this.OnMouseUp(e);
}
private void TitleBar_MouseMove(object sender, MouseEventArgs e)
{
this.OnMouseMove(e);
}
#endregion
#region Button Click Events
private void minButton_Click(object sender, EventArgs e)
{
if (MinButtonClick != null)
this.MinButtonClick.Invoke(this, e);
}
private void maxButton_Click(object sender, EventArgs e)
{
if (MaxButtonClick != null)
this.MaxButtonClick.Invoke(this, e);
}
private void closeButton_Click(object sender, EventArgs e)
{
if (CloseButtonClick != null)
this.CloseButtonClick.Invoke(this, e);
}
#endregion
}
}
As you can see from the image, I also added a background image to the control. Depending on your patience and your requirements, you can use images and PictureBox controls to make this look as much like a standard title bar as you need.
In the above example I placed three buttons on the control with images I found online to represent minimize, maximize, and close. in your case you would simply exclude a close button. I also placed a string on the control with an appropriate font to serve as the title of the window.
Adding the custom title bar to your form is easy.
public TitleBar titleBar = new TitleBar();
titleBar.Dock = DockStyle.Top;
titleBar.MaximizeEnabled = true;
titleBar.MinimizeEnabled = true;
titleBar.Size = new System.Drawing.Size(10, 40); // Width doesn't matter - I wanted it 40 pixels tall
titleBar.Title = "Title Example";
titleBar.MinButtonClick += titleBar_MinButtonClick;
titleBar.Max ButtonClick += titleBar_MaxButtonClick;
this.Controls.Add(this.TitleBar);
And then last step is to set up your event listeners for the min and max button clicks:
private void titleBar_MinButtonClick(object sender, EventArgs e)
{
WindowState = FormWindowState.Minimized;
}
private void titleBar_MaxButtonClick(object sender, EventArgs e)
{
WindowState = FormWindowState.Maximized;
}
You may also note that I included events for mouse down, up and move in my title bar. This was so that I could create listeners in my form to move the form when the user clicked and dragged the title bar. This is optional and depends on if you need the user to be able to move your application window.
The added benefit of doing this is that can use the title bar for additional controls. For example, my application was custom written for use on a toughbook style tablet computer with a small touchscreen display. In my application, utilization of the limited space was extremely important. I was able to further modify what I've described here to also include menu bar style control directly on the title bar. In addition, I added more buttons to the left of the stand minimize, maximize, and close buttons. Really helped me utilize every square inch of the screen in my application. Couldn't have done it with the standard title bar.
Can you simply use Form.ControlBox = false (or via the designer as you point out rather negatively in your comment) and then add a custom help button on the form?
EDIT: A colleague of mine wrote an Excel add in and had a requirement to remove the X from certain forms (e.g. a Progress Bar that shouldn't be closed). He found a function written by Stephen Bullen that did just that. I've only seen this function used in VB, but perhaps you can get some ideas or direction out of his approach of using Windows API to solve your issue.
This code will disable the Close button. I am not sure if you can actually make it invisible. http://www.codeproject.com/Articles/20379/Disabling-Close-Button-on-Forms
//
// source code
// Code Snippet
private const int CP_NOCLOSE_BUTTON = 0x200;
protected override CreateParams CreateParams
{
get
{
CreateParams myCp = base.CreateParams;
myCp.ClassStyle = myCp.ClassStyle | CP_NOCLOSE_BUTTON ;
return myCp;
}
}
Good luck!
Please try this.ControlBox = false.

Categories