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 Visible = 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)
{
Microsoft.Win32.SystemEvents.SessionEnded +=
new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
base.OnDoWork(e);
}
void SystemEvents_SessionEnded(object sender, Microsoft.Win32.SessionEndedEventArgs e)
{
this.CancelAsync();
}
void DoDisplayChanged()
{
if (DisplayChanged != null)
DisplayChanged.Invoke(this, EventArgs.Empty);
}
}
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);
func.RunWorkerAsync();
}
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.
if (bDisplay) Application.Run(new Main());
else
{
MyFunctionality func = new MyFunctionality ();
func.RunWorkerAsync();
Application.Run();
}
See, I told you that you weren’t going to like it!
Reference: http://www.interact-sw.co.uk/iangblog/2004/11/30/nomainform