Windows Forms: because you're worth it

March 23rd, 2009

Ah, Windows Forms. You've changed my life. I used to think Java was the lowest of low in gui programming, but I've had to reset my lowest common denominator in several areas already. Layout is horrendous, and the WinForms threading model is unfathomable. At least it's nothing important then.

But it also comes wrapped with easter eggs for your enjoyment. Try this on for size:

  1. Create a new thread, run splash screen.
  2. Initialize main gui in default thread.
  3. Signal splash thread to end.
  4. Splash screen calls Close().
  5. Call Join() on splash thread.
  6. Run main gui.
  7. Main gui appears behind all other open windows.

What do you mean that's not what you wanted? So you think to yourself "Aha! I'm cleverer than you are, stupid dot net. I'll make you wish you never gave me a BringToFront() method!" But that, despite the fantastically promising name, doesn't do anything. Neither does Activate().

No big deal. I'm sure noone is planning to use a splash screen in .NET anyway. So after aimlessly looking out the window for an hour and downing another three cups of awful coffee, you snap out of your prolonged daydream and start scrolling through the member list for the seventh time. Hm, a TopMost property. I wonder... Ah yes, that's the Stalin button. Makes your window always on top of all others. But what if..

// <stalin>
this.TopMost = true;
// </stalin>
this.Load += delegate (object o,EventArgs a) { this.TopMost = false; };

Yup, that actually works. When you're initializing the gui you fool the stack that hates you into thinking that you're going to be a dictator, but just when the window loads you turn off god mode. And that's enough to bring it to the front.

Windows Forms is truly fantastic for the kind of people who enjoy trivia. Just remembering hundreds of facts that have no real use just for the sake of knowing what few other people know. Take threading. Now, in most runtimes you would imagine that creating a new thread in your program has semantics such that whatever you've been doing until now in your single threaded application continues to work. The new bit you have to tackle is new threads you create in addition to the main one. Not so in .NET (I bet you saw that coming, you rascal!) For inexplicable reasons, your process has a way of hanging at the end just for the heck of it. I think I figured it out though. Are you ready for it?

splashthread = new Thread(RunSplash);
splashthread.IsBackground = true;
Thread.CurrentThread.IsBackground = true; // cure for cancer?

That's right, suddenly your main thread doesn't work the same anymore. You have to make it a background thread (which it clearly isn't), otherwise it just hangs there after Close().

EDIT: No, that didn't fix it either.

What a shame I didn't discover Windows Forms 7 years ago, I could have spent all that time learning all these exciting hacks instead of wasting my time on useless and unproductive things like Python.

:: random entries in this category ::