Search code examples
c#winformssystem-tray

Navigate to Another Form from System Tray Winforms


I am working on a WinForms application, I tried to minimize the form to system try while closing and when opening from the system tray I want to directly go to the main app without logging again. The main point is to reduce the login attempts to get into the main app and the app should run in the background until the account holder logs out of the app and sees the login screen.

This is what I am up to

Program.cs

static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Splashscreen());
        Application.Run(new SignIn());                                       
    }

This is how I navigate to the main app from sign-in form

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        waitForm.Close();
        this.Hide();
        //Nothing to do with this system tray problem, just checking for another valid condition
        if(condition == true)
        {                 
            MainApp mainapp = new MainApp();
            mainapp.ShowDialog();                
        }            
        this.Close();
    }

Main App to get into after login

private void MainApp_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (e.CloseReason == CloseReason.UserClosing)
        {
            notifyIcon1.Visible = true;
            notifyIcon1.ShowBalloonTip(500);
            this.Hide();
            e.Cancel = true;                
        }
    }

    private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
    {
        this.Show();
        notifyIcon1.Visible = false;
        WindowState = FormWindowState.Normal;
    }

But, When I do this, the system tray icon disappears and cannot go to the specified page. Any thoughts or experience in making this happen?

Thanks in advance guys!


Solution

  • The problem is, that hiding a form ends the ShowDialog() modal loop. So in backgroundWorker1_RunWorkerCompleted your SignIn form gets closed when the MainApp form is hidden and exits the Application.Run() loop in the main method. See my comments in your existing code:

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        waitForm.Close();
        this.Hide();
        //Nothing to do with this system tray problem, just checking for another valid condition
        if(condition == true)
        {
            MainApp mainapp = new MainApp();
            // this method will exit when mainapp will be hidden:
            mainapp.ShowDialog();
        }
        // this will exit your Application.Run(new SignIn()) in the static Main methods:
        this.Close();
    }
    

    As you said you don't need the SignIn instance after a successful login, you could change your app as follows.
    In SignIn form change the following method like this:

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        waitForm.Close();
        //Nothing to do with this system tray problem, just checking for another valid condition
        DialogResult = condition ? DialogResult.OK : DialogResult.Cancel;
    }
    

    This way you can use the DialogResult of SignIn in your Main method in Program.cs:

    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Splashscreen());
        using (var signIn = new SignIn())
        {
            switch (signIn.ShowDialog())
            {
                case DialogResult.OK:
                    break;
                default:
                    return;
            }
        }
        Application.Run(new MainApp());
    }
    

    The rest of the code looks Ok at the first glance.