Search code examples
c#.netauthenticationmessage-loop

Difficulty displaying "login" and "main" forms correctly


I have a WinForms application, with a login form and main form. The login form contains two textboxes for the user to enter credentials, an OK button, and a Cancel button. The following code is the event handler for the OK button:

        private void button_OK_Click(object sender, EventArgs e)
        {
            if (authenticated())
            {
                this.Close();
                Application.Run(new MainWindow());
            }
            else
            {
                MessageBox.Show("Incorrect credentials", "Retail POS", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }    
        }

The problem with this is that it keeps the login dialog when the main form opens. I have tried to accomplish the desired behaviour by showing the login form as a modal dialog by calling ShowDialog() from Program.cs, but this has not achieved the desired behaviour.

Note that the main form has an option to log out. That is, it should remove the main form and display the login form again.

Program.cs code:

static void Main()
{
    LoginForm loginForm = new LoginForm();
    loginForm.ShowDialog();
}

This produces an error, saying a second message loop cannot be started.


Solution

  • You need to hide your fist from. You can do it with this.Hide()

    Be careful where you position this.Hide().

    If you are using mainForm.Show(); you can place it before or after it, but if using mainForm.ShowDialog(); you can place it only before it since ShowDialog() stops code from executing until form which called this method is closed.

    From program.cs you start your application with Application.Run(YourMainForm)

    Since you want your LoginForm to be first when you open app you should create it inside Program.cs and pass it inside Application.Run() like this:

    ...
    LoginForm lf = new LoginForm();
    ...
    Application.Run(lf);
    

    Now we have LoginForm displayed. We can not close it since our application will close (since it is main form)

    So when user login and press button and succeed, we hide our main form and show other we want like this:

    private void button_OK_Click(object sender, EventArgs e)
    {
        if (authenticated())
        {
            MainWindow mw = new MainWindow();
            mw.Show();
            this.Hide();
        }
        else
        {
            MessageBox.Show("Incorrect credentials", "Retail POS", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }
    }
    

    Now we have our MainForm displayed, and login hidden.

    Since you want to make so user can log off, you can do it two ways:

    First is when user press button, we do this:

    LoginForm lf = new LoginForm();
    lf.Show();
    this.Close(); //We assume that button is placed in your main form
    

    This way we again display Login Form (at this point we have 2 login forms in memory, main one and new one which is a waste of memory) and there user can login again. This way every time user logs out you will have one more LoginForm in memory which is very bad.

    Other efficient way is that inside Program.cs file we do not create LoginForm instance inside Main() function, but outside and mark it as public static

    It would look like this:

    Program.cs
    
    ...
    static class Program
    {
        ...
        public static LoginForm mainForm;
    
        static void Main()
        {
            ....
            mainForm = new LoginForm();
            Application.Run(mainForm);
        }
    }
    

    Now when we have this and user press Logout in your MainWindow you do not need to create new instance of LoginForm but you can just Show() existing (main) one with Program.mainForm.Show()