Search code examples
c#exceptionchartssystem-tray

Issue when minimizing forms with Charts to System Tray,


I have a form that I minimize to the system tray, by hooking-in to the form_resize event. All worked well, until I added a Chart to the form. When the chart is on the form, I would get the following exception:

Width must be greater than 0px.

The highlighted line is:

   this.ShowInTaskbar = false;

It took me a bit of time frigging around to work-out what the problem was (including that it was adding the Chart that caused it), but managed to deduce it from very long stack trace messages. Anyway, I managed to solve it by setting the chart visibility to false before hiding the form.

private void Form1_Resize(object sender, EventArgs e)
    {
        if (FormWindowState.Minimized == this.WindowState)
        {
            //Hide chart to prevent exception
            chtCompliance.Visible = false;
            chtHistory.Visible = false;

            icoTrayIcon.Visible = true;
            icoTrayIcon.ShowBalloonTip(500);
            this.ShowInTaskbar = false;
            this.Hide();
        }
        else if (FormWindowState.Normal == this.WindowState)
        {
            icoTrayIcon.Visible = false;
            this.ShowInTaskbar = true;

            //Restore chart visibility
            chtCompliance.Visible = true;
            chtHistory.Visible = true;
        }
    }

Now... this appears to resolve the problem, but seems to me that this is more of a workaround than a solid solution. Anyone know of a more elegant way of addressing this problem? (I guess for a start I could dynamically look for all charts, so I don't have to hard-code this into the routine if I add more!)


Solution

  • Changing the ShowInTaskbar property has many side effects. It is a "difficult" property, it forces the native window to be recreated since the property affects a window style flag that is specified when the window is created with CreateWindowEx(). The underlying style flag is WS_EX_APPWINDOW, it has to be turned off to get rid of the taskbar button. Which forces Winforms to destroy and re-create the window.

    That has a knack for causing trouble, particularly for controls that haven't been debugged well enough. And you are doing it at the worst possible time, when the window is minimized and doesn't have a meaningful size. So sure, such a chart control might well object against being re-hosted to a new window with a 0x0 size.

    Short from trying to keep that balky control happy, the much simpler workaround is to just not change the ShowInTaskbar property. There is no point to it, the taskbar button is invisible anyway when you call Hide().

    Remove the ShowInTaskbar property assignments to fix your problem.