Start a WinForm Hidden June 18, 2009Posted by codinglifestyle in CodeProject, Winform.
Tags: BackgroundWorker, hidden, threads, visible, Winform
This is a short one, there may be better ways but this was fast and simple. Works for me!
The case here is I have a WinForm application and want the Main window to start hidden. From the designer, you can’t set Visisble = false. Also, setting this.Visible=false in the constructor or Load event has no effect. Sure you can set it later (like in Paint) but the last thing you want is your window to flash and disappear every time your application starts.
So, here is all you have to do:
- In the designer, set your window Opacity to 0%
- In the constructor, pass in a boolean to indicate if the window is displayed.
- In the function body, add this line:
Opacity = bVisible ? 100 : 0;
Simple, fast, done… moving on to other things in life.
Well okay… I’m not really one for leaving well enough alone. The fact is, there is a better way but you’re not going to like it! I imagine your main form is doing something like sitting in the notification tray and/or monitoring something like a windows service. That functionality, whatever it is your application does, should be abstracted out of the form altogether. You’re really not going to like what’s next. This object, the meat of your program, can then exist in a worker thread and provide the relevant events to your UI so it may update itself if the main form is shown.
It’s not as bad as it sounds. Go on, you know separating the logic from the UI layer is the right design! We’ll abstract all our real functionality into a class called MyFunctionality. We have BackgroundWorker in our .NET toolbox MyFunctionality will inherit from. Then override OnDoWork where we’ll put the code we originally had in the main form’s constructor or Load event. We will handle the case of exiting the thread in case the user logs off. Last, we just need optional events for the UI to receive an update from our functionality object. An example of this is below, with our DisplayChanged event and DoDisplayChanged function. Use a custom event to pass more information.
class MyFunctionality : System.ComponentModel.BackgroundWorker
public event EventHandler DisplayChanged = null;
protected override void OnDoWork(DoWorkEventArgs e)
//The meat of my program…
Microsoft.Win32.SystemEvents.SessionEnded += new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
void SystemEvents_SessionEnded(object sender, Microsoft.Win32.SessionEndedEventArgs e)
if (DisplayChanged != null)
Your form will create the thread and add the relevant events, in this case DisplayChanged.
private void Main_Load(object sender, EventArgs e)
MyFunctionality func = new MyFunctionality();
func.DisplayChanged += new EventHandler(Func_DisplayChanged);
Lastly, we just need to make a small change in Program.cs to either (A) instantiate our main form, which in turn launches the thread hosting our functionality, or (B) directly instantiate the thread without ever using our main form.
MyFunctionality func = new MyFunctionality ();
See, I told you you weren’t going to like it!