Switching between Window Forms does not seem to work - c#

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.

Related

How do I show a new window after having closed the MainWindow?

I'm trying to do what is described in this post, display a log in window and when user successfully logs in, close it and open the main window of the application.
If the user logs on successfully, then I want to show the main window, if not, I want to exit the application
but the provided answers (at the time of posting this question) do not work for me since my code to show the windows is running from the App.cs.
I know the reason, its because the first window that starts up is automatically set to be the MainWindow of the application and when I call Close() on it, it exits the application. So the second window doesn't have a chance to open.
My question is how to overcome this? Or is this just not possible the way I described?
public partial class App : Application
{
public App(){}
private void Application_Startup(object sender, StartupEventArgs e)
{
LoginScreen f = new LoginScreen(); //becomes automatically set to application MainWindow
var result = f.ShowDialog(); //View contains a call to Close()
if (result == true) //at this point the LoginScreen is closed
{
MainWindow main = new MainWindow();
App.Current.MainWindow = main;
main.Show(); //no chance to show this, application exits
}
}
}
You can change application shutdown mode to OnExplicitShutdown and then call Application.Shutdown(0) whenever you want to. For example:
public App()
{
App.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
}
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
if (MessageBox.Show("Continue?", "", MessageBoxButton.YesNo) == MessageBoxResult.No)
App.Current.Shutdown(0);
}
Here in the constructor I'm changing application shudown mode and calling Shutdown method if I need to.
Caution: When you change ShutdownMode make sure to call Shutdown method otherwise your application will be in memory even after main window closes. I've overrided OnClosed method in my MainWindow to do that:
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
App.Current.Shutdown(0);
}
App.xaml : (In this file set the start window with the login view)
StartupUri="LoginWindow.xaml"
LoginWindow.xaml : (A file with a login window view)
LoginWindow.xaml.cs : (Code Behind for the view. Place here the function assigned to login. )
private void Login_Click(object sender, RoutedEventArgs e)
{
//Access control. If correct, go ahead. Here you must create a condition check
MainWindow main = new MainWindow();
main.Show();
this.Close();
}

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.

My WinForm closes itself immediately after it is shown

After I show my WinForm, it closes immediately after. I have three WinForms: my starting one, a progress bar, and then my main one. On the starting WinForm, the user clicks a button which leads them to the progress bar. Then once the progress is completed, it runs the main form through a function in another class, but then it closes immediately. It looks something like this:
//Starting WinForm
private void button1_Click(object sender, EventArgs e)
{
ProgressBarForm PBF = new ProgressBarForm();
PBF.Show();
this.Close();
}
//Progress Bar Form stuff
private void ProgressBarForm_Shown(object sender, EventArgs e)
{
// Stuff for progress bar to load
progressBar1.Maximum = 100;
if (progressBar1.Value == 100)
{
Main.ExecuteMain();
}
}
// In main class
public static void ExecuteMain()
{
MainForm MF = new MainForm();
MF.Show()
// Other stuff that leads to another function
}
And right there it closes immediately. I've tried running a separate thread for it, but it still doesn't work. I've tried keeping it in a while loop, but it constantly keeps loading and doesn't allow any interaction. Also, if this counts, I'm trying to draw on the form aswell. My question is, why does the WinForm close immediately while the other two do not?
Change PBF.Show(); to PBF.ShowDialog();
Your closing the window straight away - that's why it closes.
you need to declare
in Main class
Public MainForm MF
In other class
private void ProgressBarForm_Shown(object sender, EventArgs e)
{
// Stuff for progress bar to load
progressBar1.Maximum = 100;
if (progressBar1.Value == 100)
{
Main.MF=new Main.MainForm();
Main.MF.Show(); // open form or
// Main.MF.ShowDialog(); open modal form
}
}
The reason is that the Application.Run() call in your Main method is passed a form, and quits the message loop when that form is closed. You might want to pass your real main form to Application.Run() (create it hidden, don't show it until the progressbar completes)

gtk# thread for window

I'm building a GUI application with C# and gtk#. I've encountered an issue recently and was looking for the best solution to this problem:
I have a modal window that pops up for the user to enter a number. This window is a separate window accessed from my main window and it's set up like this:
public class MainWindow()
{
public NumberEntry numEntry;
Whenever I need numerical input from the user, I call ShowAll() on the public Window property of NumberEntry like:
numEntry.win.ShowAll();
And all of this works fine. Afterwards, to get the value they entered, I call:
int entered = numEntry.valueEntered;
The issue is obviously that code continues executing immediately after the ShowAll() line is finished, and numEntry.valueEntered is always 0. What I'd like to do (and have been trying to do), is to suspend the main thread, and open up the number entry window in a second thread, and join back to the main thread when this is complete. Suspending the main thread seems to prevent GUI changes making the program freeze when I try to open the number entry window. I'd also like to avoid callback methods if at all possible, seeing as how this would get rather complicated after awhile. Any advice? Thanks!
Seems like when GTK window is closed all its child controls are cleared. So to get the result from the custom dialog window you may do the following (I am not gtk guru but its works for me):
1. Create a new dialog window with your controls (I used Xamarin studio). Add result properties, OK and Cancel handlers and override OnDeleteEvent method:
public partial class MyDialog : Gtk.Dialog
{
public string Results {
get;
private set;
}
public MyDialog ()
{
this.Build ();
}
protected override bool OnDeleteEvent (Gdk.Event evnt)
{
Results = entry2.Text; // if user pressed on X button..
return base.OnDeleteEvent (evnt);
}
protected void OnButtonOkClicked (object sender, EventArgs e)
{
Results = entry2.Text;
Destroy ();
}
protected void OnButtonCancelClicked (object sender, EventArgs e)
{
Results = string.Empty;
Destroy ();
}
}
2. In your main window create a dialog object and attach to its Destroyed event your event handler:
protected void OnButtonClicked (object sender, EventArgs e)
{
var dialog = new MyDialog ();
dialog.Destroyed += HandleClose;
}
3. Get the results when dialog is closed:
void HandleClose (object sender, EventArgs e)
{
var dialog = sender as MyDialog;
var textResult = dialog.Results;
}
If you whant you also may specify a dialog result property and etс.

After loading the form that should be showed up is automatically closed

I have a problem regarding the loading screen I've created.
I execute the code run but after the progress bar is finished, the form is shown but closes automatically.
Why is this happening?
namespace LogIn
{
public partial class Loading : Form
{
public Loading()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
progressBar1.Increment(2);
if (progressBar1.Value == 100) timer1.Stop();
if (progressBar1.Value == 100)
{
this.Close();
Login Login = new Login();
Login.ShowDialog();
}
}
}
}
In your startup code (your Main method), you probably have something like the following:
Application.Run(new Loading());
This makes Loading your main Application Form. When you call Close, you are closing Loading, which effectively ends the application.
What you are really looking for is the concept of a Splash Screen.
See this question and related answers for an overview.

Categories