Scott Hanselman

Introducing BabySmash - A WPF Experiment

June 2, '08 Comments [39] Posted in BabySmash | Learning .NET | Windows Client | WPF
Sponsored By

screenshot1 WPF (Windows Presentation Foundation) is confusing, to me at least. It's one of those things that is so completely different from how things were done in the past that it's not only hard to just pick up, but it's hard to tell what's the right way to do things. Often, there's a half-dozen ways to do something but no way to know which is the right. By right, I mean, most robust, most reliable, most future-proof, most supported, most compatible. It's powerful, but the power isn't immediately discoverable.

A Little Personal History

I'm a Win32 guy from way back. To be honest, I'm a Win16 guy. I cut my teeth when Hello World was 92 lines of C code on Windows 3.0, not counting the dialog resources. I worked on internationalizing applications in '95 when thunking (translating between 16 and 32-bit) was all the rage. We had an educational security application that needed to run in DOS, Windows 3.1 and Windows 95, and they wanted to re-use as much code as possible, so I #ifdef'd my way to glory.

I not only understand Win32, but I understand it's historical context and many of the design decisions behind it. Certainly not as much as Raymond Chen, but I devoured Petzold's legendary book, as did we all, and when MFC came out, I understand exactly what it abstracted and what it didn't.

WinForms is a managed layer over Win32 Windowing, and not only does Win32 sneak out occasionally in your code, but so does (of course) many other Win32 APIs.

BabySmash

OK, fast forward to this past weekend. My 2.5 year old and 6 month olds are constantly smashing on the various computers around the house. There's two Macs and four PCs in various locations. I've got a great free toddler-specific  application called AlphaBaby installed on the Mac that makes sounds, shows letters and numbers while ostensibly protecting the machine (the software at least) from the kids. When I see my kids playing with it with such enthusiasm, I always think of the Incredible Hulk when he says "Hulk! Smash!" so this is "Baby! Smash!"

I always wanted a Windows version of AlphaBaby, and some Googling didn't find me what I wanted, although I knew it must be out there. (Of course, now many of you have shared with me your favorite toddler programs. Someone should re-write KidPix for the PC. THAT was a great application.)

Learning WPF

My wife was watching some horrific movie on Lifetime (seriously, Patrick Swayze was in it and it wasn't Dirty Dancing) so I figured I'd spend a few hours and bang out a little application for the boys. Then I realized that this was a fine opportunity to learn WPF. I understand the general ideas behind WPF and Chris Sells has explained some aspects of it to me. Suffice it to say, WPF is a complete re-imagining of how Windows Client Developer should work - hence it's relative inaccessibility to folks like me who are deeply routed in PeekMessage. ;)

File|New WPF Application and some poking around got me some progress, but I was really trying to make the code clean. I had two goals: make it work and do it well.

Then, it hit me. "Make it work' usually is the most important goal, so I accepted that I don't know WPF and just made it work using techniques I already knew. About 6 hours later, a lot of hacking, some sample wav files of kids laughing, a quick web search for free "Web 2.0 templates," register a domain, upload, and I had http://www.babysmash.com and a workable ClickOnce WPF application that's about 60% of where I want it.

Features

Here's some of the "features." Note that some of these are technical features. Some are kind of obscure, but as a whole, I think these represent a good representative mix of the kinds of things that Windows Client Programmers might find themselves trying to figure out. I think it's a decent sample because it's complex without being oppressively so, it's easy to get one's head around the requirements, it has a lot of possibilities, and it touches all over the platform (BCL, WinForms, Win32, WPF).

Current Features

  • Silly Graphics
  • Options Dialog and Settings saved in Isolated Storage
  • Keyboard Hooks - Disabled Windows Key, ALT-TAB, Ctrl-Esc
  • ClickOnce (is it viable? sure makes auto-updating easy)
  • Kiosk Mode (Full Screen)
  • Multi-monitor Support (almost)
  • Multimedia, Playing audio files
  • Text to Speech

Future Features Ideas

  • 3D? Animations? Gradients?
  • Code Signing Certificate to avoid warning
  • Mouse drag/painting support  
  • Better/more Multimonitor options
    • Simultaneously add shapes on n monitors
  • Optional install as Screensaver?
  • When .NET 3.5 is released, support the smaller .NET 3.5 Client Install
  • Add custom WAV files (my voice?) for letters/shapes, rather than TTS
    • Maybe let parents record their own voices
  • Localized?
    • Does it work on non-English Keyboards/Systems?
    • Does it make sense/is it useful with non-Latin languages? Chinese, Arabic?
  • Logging/phone-home when exceptions happen
  • About Box (woohoo!)

Did I mention the code sucks deeply?

it also has some "hidden features." By hidden features, I mean, the code sucks. Deeply. Which is kind of the whole point. After I abandoned my "do it well" goal and focused on "make it work," I made ridiculous progress. Of course, I'm not sure the fate of my immortal soul after writing this code, but calling back to last week's post on how none of us really knows what we're doing, why not use this as a learning experience?

I decided to not only hack this together, but also to consciously not do a refactoring pass. This is the code exactly and horribly as written the first time, comments, dead code, duplicated blocks, and random copy-pastes from the bathroom wall of code CodeProject and MSDN. Don't judge me too harshly because you KNOW you've written this kind of crap yourself, Dear Reader. The kind of code that makes you need a shower later, but it works and it solved the problem.

Problems as I see them

The code is on CodePlex, and this is my own stream-of-consciousness review of the code and functionality.

  • No real design
  • No separations of concerns between objects
  • Utils class (isn't there always a Utils class?) is schizophrenic
  • Unclear to me how to convert the low level Win32 calls to WPF-eese.
  • I think there's easier way to have "stroked" (outined) characters.
  • Not modular - no way to add new shapes and have sounds associated with them.
  • ConfigurationManager/IsolatedStorage - feels like I shouldn't have had to do that.
  • Audio - used Win32 APIs. Do the WPF managed API have the same perf?
  • If you slam on the keyboard too fast, like wipe your hand over it, it can crash in un-managed code. Is this the global keyboard hook gone wrong or something more sinister?
  • Need to capture Alt-Space
  • Relationship between Main Window, Options, and configuration details is shaky at best. There should be a pattern for chunks of config state that might change during the process.
  • The random letter/shape positioning has some hard-coded fudge factors that feel gross.
  • No tests - how would you test something like this?
  • No thought to threading issues (do I have any?)
  • Multimonitor is cheesy, and the Windows on other monitors don't update unless they have focus. How can dispatch (Replay/Tivo?) keystrokes/events too n windows at once so they all update?
  • Multimonitor - I'd like to detect on window being closed, then close them all.
  • Splash screen?
  • No tracing, debugging, exception handling, logging.
  • I keep calling into System.Windows.Forms. Are there known WPF limitations on keyboard handling?
  • If you hit enough keys fast enough, you have to wait for the "queue" to empty. Can I solve that and drop keys if something fills to fast? My own key queue?
  • Not localized - magic strings.
  • I'm not really using XAML. Is there a better, more declarative way to do some of this?

The Experiment

image I'd like to try two things here. First, what I'd like to do is have a group code review. Leave your thoughts in the CodePlex Issue Tracker and code in <pre> tags. Be sure to read them first so you aren't duplicating effort. Of course, even better, feel free to blog your improvements and diffs or email me diff files (firstname at lastname.com).

Second, I'm going to hunt down WPF programmers. Not just Microsoft Employees, although I'll go find the WPF team and ask them, but I want to talk people who have succeeded and failed at WPF applications and get their ideas on refactorings, structure, design, and correctness. Help me (us) understand how it works and if it's better.

Then (hopefully) over a series of blog posts and maybe a podcast or two, we'll have two applications, before and after, that we can look at. One will be my initial hacked-together-but-functional application, and one will be a completely refactored, group-vetted, expert-reviewed sample that represents (theoretically) a well-written WPF application. The app will implement all the features above and more, and each "feature" will be a little best-practice that someone can use in their app. This way we'll have not just a random sample - with credit to Rob Conery's MVC Storefront application and his transparent design process - but two, before and after, and at some point I'm hoping my brain will break out of my Win32 thinking and I'll better understand WPF idioms.

I will tag the posts on my blog in the BabySmash category. I'll also be trying some other mostly unrelated experiments, as I'll use Git for local, offline source control, but I'll be pushing my major commits from Git to TFS (Team Foundation Server) at CodePlex as well as using TFS for issue tracking.

Have at it, the source is up on CodePlex, you can download a ZIP.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Monday, June 02, 2008 7:22:19 PM UTC
The best part about this entire post is that the Lifetime movie ended way before the code did ("honey, I'm working...."). Seriously though Scott, you have gone miles in your screen casting skills, so please, do one up for us here; or maybe, get with your Pwop pals and new up a DNRTv episode.

Wow, the hits keep on rollin'.
Monday, June 02, 2008 7:33:03 PM UTC
Thanks for the post. It's really interesting to follow along with you. I'm particularly interested in the ClickOnce technology as I'm contemplating using it for a project soon. Saw your tweet about it being "tricky." If you get a chance to eloborate on the process it would be great.
Monday, June 02, 2008 7:47:52 PM UTC
I really like this program, thanks for writing it and sharing it. I've wanted to write something like this for my 2 year old for a while, but wasn't sure what to write it in. I look forward to checking out the code.

And for the record my boy loves it, he didn't want to stop.
Monday, June 02, 2008 8:13:21 PM UTC
I floundered quite a bit with my first WPF application as well, even with the "Programming WPF" book. One of the things I found that made my life easier was Microsoft Expression. I would create whatever it was that I wanted to do in Expression first, then have a peek at the XAML. The .NET API and XAML are basically the same thing, so when I saw a ViewBox element, I looked for a ViewBox class and when I saw a Stretch attribute, I looked for a Stretch property. It worked pretty well - I considered it training wheels for WPF.
Monday, June 02, 2008 8:47:44 PM UTC
What a great fun little app!

The code might be ugly and not the way you'd design it if you knew the system inside and out but it's a learning process and with the great refactoring tools available in VS you can mash it into shape much easier than before :)

[)amien
Monday, June 02, 2008 8:50:08 PM UTC
You have a common background as myself and many of us in the MS community. The fact this approahc was not taken by MS is one of the reasons I have not fully grok'ed the wpf world as much as I want to. Thanks for the approach of having us follow along the journey through the dirty code.
Bart
Monday, June 02, 2008 8:55:12 PM UTC
Scott,

This sounds like a lot of fun and I for one am going to do my best to follow along. I hope to learn enough to possibly contribute.

In a slightly unrelated fashion I have a somewhat related question.

Is there the pontential here to have something worth using as an example when pointing out to pointy haired people that just because we "made it work" doesn't mean it is correct? Taking into consideration the "real world" maybe we can gather enough information to be able to give reasonable arguments for actually fixing things. Remember that if this was most "enterprise" shops this app would pretty much be v1.0 . Making changes to code that was already written that didn't fix a "show stopper" would be looked down upon and questioned.

I know that sounds kinda off the wall but this is a great chance for those of us who don't have the privelege of working in environments where our peers and administrators understand our concerns. We have to explain needs like what is needed here to people who might not understand what it means to honestly feel like you need to take a shower after writing "make it work" code .... even if it does "work"... for now.

These kinds of interactions I think are just as important to software development as learning any number of languages/ API's/ patterns etc. We need to learn to be able to explain why we learned something and why doing it better is a good idea. For my self at least I know this is something I have never been able to master.

ok... I'll go stop ranting now...
Ang3lfir3
Monday, June 02, 2008 8:59:24 PM UTC
What a sweet idea! The group coding effort, I mean. No kids yet, so can't tell about the utility of the app.

Having used WPF for a while now, it's interesting to see someone who is obviously an experienced developer use it for the first time. The Options window is especially telling. I think that shows the weakness of the visual designer making use of XAML. I've found the only way to take advantage of WPF's awesomeness is to write the XAML yourself.

Monday, June 02, 2008 9:00:58 PM UTC
It's BabyType (from Raize Software) adapted to .NET. BabyType is AT LEAST 8 years old.

http://www.raize.com/CProducts/SoftwareForKids.asp

Joe
Monday, June 02, 2008 9:08:05 PM UTC
For your problem with borders for the shapes/text you can try using the OuterGlowBitmapEffect which should get you a sort of outline for text.
Patrick
Monday, June 02, 2008 9:27:01 PM UTC
Excellent, thanks! My 19-month-old will love this I'm sure. Although, we're still anxious to let him touch the new laptop since his ruined my TabletPC by drooling on the keyboard. Somehow, the motherboard now thinks that the Ctrl key is always pressed, even when you remote desktop into it. Need to hook up a USB keyboard to the laptop I suppose, and only let him play on that.

Very good idea for learning the WPF paradigm too!
Monday, June 02, 2008 9:33:07 PM UTC
Scott, you must be psyhic or something, because I wanted to write this exact same program when my little girl started bashing out laptop. But I err, couldn't be bothered. Which is why we have you. Once again sir, you have taken it down to Chinatown. Ray Ozzie, look out!
Andrew
Monday, June 02, 2008 9:33:37 PM UTC
Scott:

You should checkout Poisson Rouge. Their games are pretty interesting. Well, my four-year-old loves it anyway, and they look more interesting than the Playhouse Disney offerings.
Monday, June 02, 2008 9:35:24 PM UTC
Hmm, yeah I never could spell phycic physic psychic.
Andrew
Monday, June 02, 2008 10:03:41 PM UTC
Grabbed the code, set a breakpoint, hit F5 and then... oh hang on, how do i get to my IDE to see the breakpoint with all these keyboard hooks & 'stay on top' maximised chromless windows ;-)
Sherwin
Monday, June 02, 2008 11:37:25 PM UTC
Sherwin -
"Grabbed the code, set a breakpoint, hit F5 and then... oh hang on, how do i get to my IDE to see the breakpoint with all these keyboard hooks & 'stay on top' maximised chromless windows ;-) "

Sherwin, you could try remote debugging until Scott or others try to add that support (i.e., if running Debug mode, allow ALT+TAB, chrome, etc...)
Keeron Modi
Tuesday, June 03, 2008 1:56:29 AM UTC
Thanks so much for doing this, I think it's a fantastic idea. By the end of this you will have really pushed WPF forward. I too have stayed away from WPF for now and am waiting and watching for the right time to jump in. Seeing someone as respected as yourself admit you don't know what you're doing is refreshing and I think will earn you even more respect from the community. I'll be watching this experiment closely.

And yes, I HAVE written code like that.
Jason
Tuesday, June 03, 2008 2:00:28 AM UTC
I'll be the first to admit that it took me quite a while to get used to WPF based upon by background. However, I've now studied every major WPF book on the market (except the worthless Essential WPF one) and finally have some polished ninja skills. Now it's as easy as anything else. These days I can think in WPF.
Tuesday, June 03, 2008 3:40:19 AM UTC
Keeron - Oops! Yes, what I do is I go into App.xaml.cs and remove this line:

Line 23: MainWindow.WindowState = WindowState.Maximized; //Do it here, rather than in XAML otherwise multimon won't work.

Then you can run it as a regular app and debug fine. Sorry.
Scott Hanselman
Tuesday, June 03, 2008 4:48:10 AM UTC
I think you took the correct approach for getting dirty with WPF. There are so many subtleties in WPF that can sometimes take hours to get around. Fortunately, once the concepts are well understood, WPF development provides incredible productivity gains.

For those that are interested, here is a large list of WPF blogs: Blog List
Tuesday, June 03, 2008 5:26:25 AM UTC
This is the first application I've seen where the first feature is _honestly_ called "Silly Graphics"! Incidentally, it's also the only appropriate one - most apps use different terms for it :-P
Tuesday, June 03, 2008 6:33:18 AM UTC
My 15 month old managed to quickly somehow change my account password and lock me out of my XP laptop. Fortunately, I had another old admin account that I was able to login to, but...a few moments of panic there.
Tuesday, June 03, 2008 8:00:29 AM UTC
Scott... the ClickOnce setup says that it cannot download the application. The application is missing required files.
What's up? Am I the only one?
Using FireFox 2.0 on Vista 32bit
Tuesday, June 03, 2008 2:26:11 PM UTC
Scott, when you say you want code in the codeplex IssueTracker to be in pre blocks...that doesn't seem to work. It has put the pre tags literally in the comment I've added, and it has helpfully stripped out all the whitespace in the code I put inside the pre tags...

So did I post that in the wrong place, or is there some way to use HTML in the CodePlex issue tracker that's off by default?
Tuesday, June 03, 2008 2:26:57 PM UTC
Scott... seriously where do you get off insinuating that the rest of us would ever consider writing such appalling code... err... damn... hold on a sec... that Star looks embarassingly familiar...

http://blog.spencen.com/2008/06/03/quotstarquottlingly-bad-code.aspx
Tuesday, June 03, 2008 5:05:43 PM UTC
Rutger - Try FFClickOnce for ClickOnce Support on Firefox.

Ian - Looks like I was wrong about the Issue tracker supporting pre blocks. Maybe just attach a file?
Scott Hanselman
Tuesday, June 03, 2008 7:48:10 PM UTC
Can you port Alphababy to Windows?


Tuesday, June 03, 2008 7:49:48 PM UTC
That's kind of what BabySmash is, it's an Alphababy clone nfor Windows.
Scott Hanselman
Thursday, June 05, 2008 6:54:06 AM UTC
Hey Scott! You are my inspiration for doing the skunk works.
Thanks for sharing this app. My son will love this :-)
Thursday, June 05, 2008 7:12:01 AM UTC
Someone should re-write KidPix for the PC. THAT was a great application.

My wife is teacher in the Bellevue, WA school district. She has KidPix installed on the Dell PCs in her classroom and on her Dell XP laptop.
Tuesday, June 10, 2008 5:10:15 AM UTC
Scott, you have executed on an idea I've had for a while now. My son is about to turn two and I wanted to write some a WPF-based children's game to keep him occupied. Babysmash is along the lines of what I was thinking but while I procrastinated, he has gotten too sophisticated for that. What I want is an alternate input device along the lines of a Wii remote. He doesn't get much out of a keyboard and mouse since he really can't type. Maybe we'll just play ball instead...
Louis
Tuesday, June 10, 2008 8:08:43 AM UTC
There is a nice C# WiiRemote library on coding4fun. Why not hook that up to this?
Scott Hanselman
Tuesday, June 10, 2008 2:41:13 PM UTC
I did something similar awhile ago called AlphabetSmash, then turned that into Little Merlin... then my daughter got tired of it, so no more work has been done.

You can download it from http://www.littlecamelot.com
Wednesday, June 11, 2008 5:34:11 PM UTC
I ran the prg on Vista, SP1 with dual monitors. It filled both screens with white space but shapes only appeared on monitor 1.
Alt-F4 didn't properly exit the prg; instead it reduced the prg to only monitor1. Monitor2 showed normal prgs running and allowed me to do stuff there.
Ctrl-Alt-Shift-O seemed to launch the options menu but it remained hidden behind monitor1's white screen and inaccessible.
Ultimately, I was only able to terminate the prg via task mgr.
dav
Wednesday, June 11, 2008 5:35:55 PM UTC
Typo in my email on above post in case you wanted to reply to me.
Dav
Wednesday, June 11, 2008 5:58:50 PM UTC
Good bug. I'll look at that now!
Scott Hanselman
Thursday, June 26, 2008 8:06:41 AM UTC
The effect the BabySmash has made on my one year old daughter was rather unexpected: when she heard laughing she went behind the monitor apparently convinced that there was another baby hidden who made these laughters. Nothing could change her mind about it. When she was behind the monitor laugters stopped since she was not pressing any keys. But as soon as she got back to the keyboard and resumed banging on it the laughs resumed as well and there again she was going back behind the monitor to see who is laughing there. So far it's more confusion than fun judging from the expression on her face.

Next time i'll try to replace laughter wav files with non-human sounds.

Max
Thursday, June 26, 2008 8:19:40 AM UTC
Max - I'm not sure if that's funny or sad! I think it'd be nice to have "sound themes" or "audio packs" and have animals with pictures, cars and trains, and all that. It's on my list to do.

Hopefully another father-programmer will join forces with me.
Scott Hanselman
Saturday, June 28, 2008 12:41:07 PM UTC
My son will grow to love Scot Hanselman! I’m a big fan of your blogs and podcasts already, and now you can add a 11 months old to your fan-list.

Oh, and by the way! He left message to you here; “HHHHHGGR6JJEKKDDDDEDASEW”. Not quite sure what it means yet, but I’ll guess BabySmash 2.0 will have a Translate-to-grown-up-readable-format button somewhere?

Keep up the good work :)
Kjetil
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.