What's the proper way to minimize to tray a C# WinForms app?

Viewed 64403

What is the proper way to minimize a WinForms app to the system tray?

Note: minimize to system tray; on the right side of the taskbar by the clock. I'm not asking about minimizing to taskbar, which is what happens when you hit the "minus" button on the window.

I've seen hackish solutions like, "minimize, set ShowInTaskbar = false, then show your NotifyIcon."

Solutions like that are hackish because the app doesn't appear to minimize to the tray like other apps, the code has to detect when to set ShowInTaskbar = true, among other issues.

What's the proper way to do this?

9 Answers

Update: Looks like I posted too soon. I was also using the below hack for a tool of mine. Waiting for the right solution for this..........

You can use Windows.Forms.NotifyIcon for this. http://msdn.microsoft.com/en-us/library/system.windows.forms.notifyicon.aspx

Add NotifyIcon to the form, set some properties and you are done.

        this.ShowIcon = false;//for the main form
        this.ShowInTaskbar = false;//for the main form
        this.notifyIcon1.Visible = true;//for notify icon
        this.notifyIcon1.Icon = ((System.Drawing.Icon)(resources.GetObject("notifyIcon1.Icon")));//set an icon for notifyicon

    private void Form1_Shown(object sender, EventArgs e)
    {
        this.Hide();
    }

Similar as above...

I have a resize event handler that is triggered whenever the window gets resized (Maximized, minimized, etc.)...

    public form1()
    {
       Initialize Component();

       this.Resize += new EventHanlder(form1_Resize);
    } 


    private void form1_Resize(object sender, EventArgs e)
    {
       if (this.WindowState == FormWindowState.Minimized && minimizeToTrayToolStripMenuItem.Checked == true)
       {
             NotificationIcon1.Visible = true;
             NotificationIcon1.BalloonTipText = "Tool Tip Text"
             NotificationIcon1.ShowBalloonTip(2);  //show balloon tip for 2 seconds
             NotificationIcon1.Text = "Balloon Text that shows when minimized to tray for 2 seconds";
             this.WindowState = FormWindowState.Minimized;
             this.ShowInTaskbar = false;
       }
    }

This allows the user to select whether or not they want to minimize to tray via a menubar. They can go to Windows -> and click on Minimize to Tray. If this is checked, and the window is being resized to Minimized, then it will minimize to the tray. Works flawlessly for me.

I have programmed a quick solution for you guys, this might not be the most efficient way (I'm not sure), but it definitely works !

The below solution successfully minimizes your Winforms application to the system Tray, and by using the notify Icon you create a small icon in the system tray with the aforementioned menu items. than we use the in-built libraries to fetch the Window (GUI in this case), and using the appropriate methods with Booleans we then minimize the window to the tray.

private void TransformWindow()
        {
            ContextMenu Menu = new ContextMenu();

            Menu.MenuItems.Add(RestoreMenu);
            Menu.MenuItems.Add(HideMenu);
            Menu.MenuItems.Add(new MenuItem("Exit", new EventHandler(CleanExit)));

            notifyIcon = new NotifyIcon()
            {
                Icon = Properties.Resources.Microsft_Icon,
                Text = "Folder Watcher",
                Visible = true,
                ContextMenu = Menu
            };
            processHandle = Process.GetCurrentProcess().MainWindowHandle;
            ResizeWindow(false);

        }
        #region Getting Libraries
        [DllImport("user32.dll")]
        public static extern IntPtr GetShellWindow();
        [DllImport("user32.dll")]
        public static extern IntPtr GetDesktopWindow();
        public const Int32 SwMINIMIZE = 0;
        public const Int32 SwMaximize = 9;

        [DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        public static extern IntPtr GetConsoleWindow();

        [DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool ShowWindow([In] IntPtr hWnd, [In] Int32 nCmdShow);
        public static void MinimizeConsoleWindow()
        {
            IntPtr hWndConsole = processHandle;
            ShowWindow(hWndConsole, SwMINIMIZE);

        }
        public static void MaximizeConsoleWindow()
        {
            IntPtr hWndConsole = processHandle;
            ShowWindow(hWndConsole, SwMaximize);

        }
        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
        public static void ResizeWindow(bool show)
        {
            RestoreMenu.Enabled = !show;
            HideMenu.Enabled = show;
            SetParent(processHandle, WinDesktop);

            if (show)
                MaximizeConsoleWindow();
            else
                MinimizeConsoleWindow();

        }
        public static void MinimizeClick(object sender, EventArgs e) => ResizeWindow(false);
        public static void MaximizeClick(object sender, EventArgs e) => ResizeWindow(true);
        public static IntPtr processHandle;
        public static IntPtr WinShell;
        public static IntPtr WinDesktop;
        public static NotifyIcon notifyIcon;
        public static MenuItem HideMenu = new MenuItem("Hide", new EventHandler(MinimizeClick));
        public static MenuItem RestoreMenu = new MenuItem("Restore", new EventHandler(MaximizeClick));
        public void CleanExit(object sender, EventArgs e)
        {
            notifyIcon.Visible = false;
            this.Close();
        }

In the constructor of the Form:

this.Resize += new EventHandler(MainForm_Minimize);

Then use this Event Handler method:

    private void MainForm_Minimize(object sender, EventArgs e)
    {
        if(this.WindowState == FormWindowState.Minimized)
            Hide();
    }
Related