Archives

Archives / 2008 / June
  • Tree Surgeon is Looking for a Logo

    A new release of Tree Surgeon is forthcoming and I’m looking to the community to see if someone with some time and artistic skills on their hands would be interested in putting together a logo to kick things up a notch. Tree Surgeon is a .NET development tree generator. Just give it the name of your project, and it will set up a development tree for you in seconds.

    The UI for Tree Surgeon is pretty simple and it doesn’t need to be extravagant (you run it once to create a new solution tree and you’re done, this generally doesn’t happen dozens of times a day unless you’re someone like me). However it would be nice to have something snappy as a splash screen and give the product a little branding.

    image

    The image will be used in the product itself (probably as a splash or something) and on the website (to replace the icky picture of logs I put there so long ago) so please size it accordingly.

    Get your crayons out and thinking caps on and let’s see what you can come up with. The rewards? My undying gratitude, exposure on the blog (for the 10 readers that I have), and 15 minutes of fame (and I’ll toss in some XBox 360 games or something cool that I can dig up, Microsoft or .NET related of course; no Java swag here).

    Any ideas are welcome and I’ll post the entries here on the blog (please provide your name, email (if desired), and a link to your website (if desired)). Please submit your entries to me via email.

    Thanks!

  • Testing Castle Windsor Mappings Part Deux

    In my original post on testing Windsor Container mappings, I posted a spec to run whenever you are using Castle Windsor in your project. It basically ran through your configuration file and ensured all the mappings worked. This was meant to be a safety net to catch a rename or namespace move in the domain (which wouldn't update the configuration file).

    It worked pretty good and has helped us catch silly errors but we were getting pain with mappings on classes like this:

    public partial class FinderGrid<T> : UserControl, IFinderGrid<T> where T : Entity
    {
    }

    Generics were a funny thing so you get an error like this:

    System.ArgumentException: GenericArguments[0], 'T',
    on 'UserInterface.FinderGrid1[T]' violates the constraint of type 'T'. <BR>---&gt; System.TypeLoadException: GenericArguments[0], 'T', <BR>on 'UserInterface.FinderGrid1[T]' violates the constraint of type parameter 'T'.
       at System.RuntimeTypeHandle.Instantiate(RuntimeTypeHandle[] inst)
       at System.RuntimeTypeHandle.Instantiate(RuntimeTypeHandle[] inst)
       at System.RuntimeType.MakeGenericType(Type[] instantiation)
       --- End of inner exception stack trace ---
       at System.RuntimeType.ValidateGenericArguments(MemberInfo definition, Type[] genericArguments, Exception e)
       at System.RuntimeType.MakeGenericType(Type[] instantiation)
       at Castle.MicroKernel.Handlers.DefaultGenericHandler.Resolve(CreationContext context) 

    We put an exception handler around the test, but it was butt ugly. After some posting on the Castle mailing list and discussion with a few people I came up with a way to handle any generic mapping you have. Here's the updated spec that will deal with (hopefully) any mapping:

    [TestFixture]
    public class Whenstartingtheapplication : Spec
    {
        [Test]
        public void VerifyWindsorContainermappingconfigurationiscorrect()
        {
            IWindsorContainer container = new WindsorContainer("castle.xml");
            foreach (IHandler handler in container.Kernel.GetAssignableHandlers(typeof (object)))
            {
                if (handler is DefaultGenericHandler)
                {
                    Type[] genericArguments = handler
                        .ComponentModel
                        .Service
                        .GetGenericArguments();
     
                    foreach (Type genericArgument in genericArguments)
                    {
                        Type[] genericParameterConstraints =
                            genericArgument.GetGenericParameterConstraints();
                        foreach (Type genericParameterConstraint in genericParameterConstraints)
                        {
                            container.Resolve(
                                handler
                                    .ComponentModel
                                    .Service
                                    .MakeGenericType(genericParameterConstraint));
                        }
                    }
                }
                else
                {
                    container.Resolve(handler.ComponentModel.Service);
                }
            }
        }
    }

    This will handle any mapping with constraints and the name isn't tied to your test (originally I found one that worked but I had to specify the generic type when trying to set the constraint). This is a 2.0 solution and not as pretty as it could be with LINQ and 3.5 but it works.

    Hope this helps!

    P.S. Here's a silly creepy version for those that dig anonymous delegates to the extreme. Lamdbas would just make most of this syntax sugar go away:

    [Test]
    public void VerifyWindsorContainermappingconfigurationiscorrect()
    {
        IWindsorContainer container = new WindsorContainer("castle.xml");
        foreach (IHandler handler in container.Kernel.GetAssignableHandlers(typeof (object)))
        {
            if (handler is DefaultGenericHandler)
            {
                new List<Type>(handler
                                   .ComponentModel
                                   .Service
                                   .GetGenericArguments())
                    .ForEach(
                    delegate(Type argument)
                        {
                            new List<Type>(argument.GetGenericParameterConstraints())
                                .ForEach(
                                delegate(Type constraint)
                                    {
                                        container
                                            .Resolve(
                                            handler
                                                .ComponentModel
                                                .Service
                                                .MakeGenericType(constraint));
                                    }
                                );
                        }
                    );
            }
            else
            {
                container.Resolve(handler.ComponentModel.Service);
            }
        }

  • ADO.NET Enity Framework Vote of No Confidence

    Over the past year or two, I've been a casual observer into the Entity Framework coming out of Microsoft. Being an ALT.NET guy, the world tends to revolve around NHibernate for me so I've already got an excellent OR/M tool in my toolset. One of the big issues with EF that we've recognized is the general direction Microsoft has taken with it, following a data centric model rather than an object one. One of the first principles I picked up when I started doing OO programming (back in the SmallTalk days in the 80s) was that objects are defined by behavior, not their properties. Yes it's true that objects are pretty thin without data, but data is not my centre of the universe.

    What we see on the horizon is a new breed of VB6 drag-n-drop programmers embracing EF as the next Messiah. We see a new generation of developers focused on mapping their data models and missing the target of architecting and constructing well designed systems. As a result, the community has put together an open letter to Microsoft outlining these concerns. The letter outlines the deficiencies in the EF specifically related to the values we see as solid working practices. It's late to the game and Microsoft probably isn't going to make any sweeping changes so close to the release so don't expect any big short-term changes however as Dave Laribee says, it's good to be explicit and professional about criticisms so this is one of those.

    What's interesting too is that Microsoft has put tgoether what they call the Data Programmability Advisory Council, a team of notable people including Eric Evans, Martin Fowler, and Jimmy Nilsson (all very non-data centric guys in their own right). I'm not quite sure what they will do or how they fit into the entire fray but it might be a step in the right direction (whatever that direction may be).

    You can view the entire letter here where you can sign at the bottom to show your support and you can view the list of signatories here.

  • Creating a Native Win32 Splash Screen

    Splash screens are all the rage. They’re cool, they’re fun, and they can be a pain to program right.

    I though I would share a native Win32 splash solution with you on this rainy night in June (well, it is June here and it is raining from where I am, YMMV). This is slightly different from your typical splash screen as it’s done using the Win32 API calls and it’s fired off before the .NET Forms engine even gets started. As a result it’s quick and snappy and doesn’t intrude on your normal WinForms programming.

    First off, let’s look at how we’re going to invoke it. Here’s the Program class that will call our normal splash screen:

       1: [STAThread]

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: rgb(244, 244, 244);"><span style="color: rgb(96, 96, 96);">   2:</span> <span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(0, 0, 255);">void</span> Main()</pre>
    
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: rgb(96, 96, 96);">   3:</span> {</pre>
    
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: rgb(244, 244, 244);"><span style="color: rgb(96, 96, 96);">   4:</span>     SplashWindow.Current.Image = <span style="color: rgb(0, 0, 255);">new</span> Bitmap(<span style="color: rgb(0, 0, 255);">typeof</span>(Form1), <span style="color: rgb(0, 96, 128);">"splash.jpg"</span>);</pre>
    
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: rgb(96, 96, 96);">   5:</span>     SplashWindow.Current.ShowShadow = <span style="color: rgb(0, 0, 255);">true</span>;</pre>
    
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: rgb(244, 244, 244);"><span style="color: rgb(96, 96, 96);">   6:</span>     SplashWindow.Current.MinimumDuration = 3000;</pre>
    
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: rgb(96, 96, 96);">   7:</span>     SplashWindow.Current.Show();</pre>
    
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: rgb(244, 244, 244);"><span style="color: rgb(96, 96, 96);">   8:</span>&nbsp; </pre>
    
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: rgb(96, 96, 96);">   9:</span>     Application.EnableVisualStyles();</pre>
    
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: rgb(244, 244, 244);"><span style="color: rgb(96, 96, 96);">  10:</span>     Application.SetCompatibleTextRenderingDefault(<span style="color: rgb(0, 0, 255);">false</span>);</pre>
    
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: rgb(96, 96, 96);">  11:</span>     Application.Run(<span style="color: rgb(0, 0, 255);">new</span> Form1());</pre>
    
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: rgb(244, 244, 244);"><span style="color: rgb(96, 96, 96);">  12:</span> }</pre>
    

    Note that it’s the first thing called (even before we do Application calls or create the main form). We’re launching it using a JPG image but any embedded or external resource file will do (JPEG, PNG, BMP, etc.). There are a couple of options we turn on here like showing a shadow (if the OS supports it) and setting a duration.

    The duration is the minimum number of milliseconds to display the splash screen for. For example you can set this to 5000 (5 seconds) and no matter how much or how little your app is doing, the splash screen will stay around for at least this long. This is handy to keep it up even though your app may find a burst of speed and be ready before you know it.

    Now that we’ve launched the splash screen, we just go about our normal business and at the right time launch the main window and tell the splash screen to go away. We’ll do this in our Main form class by overriding the OnActivate event:

    protected override void OnActivated(EventArgs e)
    {
        base.OnActivated(e);
        if (_firstActivated)
        {
            _firstActivated = false;
            SplashWindow.Current.Hide(this);
        }
    }

    The call here to SplashWindow.Current.Hide passes in the Form derived class of our window. The SplashWindow will keep a reference to this Form object so later in the splash thread it can invoke Activate on the Form class to pop it up after destroying itself. The “_firstActivated” variable is just a boolean set on the Form class and set to true at creation. This prevents us from hiding the splash screen if the main form is activated more than once (can happen).

    And that’s it for using the SplashWindow. Simple huh? Here’s our splash in action over top of our important business application (another Bil Simser UI Special):

    Splash Window:

    image

    Main Window with Splash in Front:

    image

    Ready to work!

    image

    One of the other options you can do with this class is to provide it a custom event handler. This is called during the WM_PAINT event and will allow you to get a copy of the Graphics object that the SplashWindow owns (the surface holding the bitmap image you provide) and a Rectangle class of the boundaries of the splash window. This is really handy for doing fancy stuff to your splash screen without having to fuss around with the image itself.

    For example here’s the call to our SplashWindow again but using a custom handler:

       1: [STAThread]
       2: private static void Main()
       3: {
       4:     SplashWindow.Current.Image = new Bitmap(typeof(Form1), "splash.jpg");
       5:     SplashWindow.Current.ShowShadow = true;
       6:     SplashWindow.Current.MinimumDuration = 3000;
       7:     SplashWindow.Current.SetCustomizer(CustomEventHandler);
       8:     SplashWindow.Current.Show();
       9:  
      10:     Application.EnableVisualStyles();
      11:     Application.SetCompatibleTextRenderingDefault(false);
      12:     Application.Run(new Form1());
      13: }

    And here’s the custom handler. This simply uses the GDI+ function of drawing a string on the Graphics surface. You could use this to display version information from your app, progress messages, etc. without having to build a form and adding labels to it.

       1: private static void CustomEventHandler(SplashScreenSurface surface)
       2: {
       3:     Graphics graphics = surface.Graphics;
       4:     Rectangle bounds = surface.Bounds;
       5:  
       6:     graphics.DrawString("Welcome to the Application!",
       7:                         new Font("Impact", 32),
       8:                         new SolidBrush(Color.Red),
       9:                         new PointF(bounds.Left + 20, bounds.Top + 150));
      10: }

    And here’s the result:

    Splash with custom event handler

    Of course this is pretty simplistic. I would love to see some creative geniuses out there do something cool with this. Since your have the Graphics object (already loaded with the splash screen image) and the GDI+ at your disposal, the sky is the limit. Let me know what you come up with.

    Like I said, this is simple and easy. A few lines of code in your main program to launch it, one line to hide it, and the initialization is just providing it an image to display. All of the code is available for download below in source and binary form. You can just add the SplashLib.dll to your projects and go. Or feel free to enhance it, the code is released under the Creative Commons Attribution-Share Alike 3.0 Unported License. You can share and adapt it (even in commercial work) but please give back to the community.

    One side note, .NET doesn’t provide an interface to winuser.h and other Win32 headers so the structures and constants that are needed by SplashWindow to work are in the class. If you’re a ReSharper junkie you’ll notice that R# complains that the file has a lot of dead code. Don’t for the love of all that is holy remove the unused structure members as the SplashWindow will fall down and go boom.

    Of course there’s room for improvement so feel free to send me your changes or enhancements!

    SplashLib Source Files
    SplashLib Binary Files

    Enjoy!

  • WinForms Dummy Question

    This has got to be one of the dumbest posts I've done but for the life of me and my co-horts we can't figure it out.

    We have a TextBox sitting on a UserControl sitting on a Panel sitting in a Form.

    $10 to the first person to tell me how to set the focus to the TextBox.

    We've tried:

    • txtBox.Focus();
    • ActiveControl = txtBox;
    • txtBox.Select();

    Nothing works. WTF? This has got to be a simple thing right?

  • The First Spec You Should Write When Using Castle

    Thought this might be useful. On a new project where you're using the Castle Windsor container for Dependency Injection, this is a handy spec to have:

    [TestFixture]
    public class Whenstartingtheapplication : Spec
    {
        [Test]
        public void verifyCastleWindsormappingsarecorrect()
        {
            IWindsorContainer container = new WindsorContainer("castle.xml");
            foreach (IHandler handler in container.Kernel.GetAssignableHandlers(typeof(object)))
            {
                container.Resolve(handler.ComponentModel.Service);
            }
        }
    }

    It doesn't guarantee that someone missed adding something to your configuration, but this way anytime someone adds a type to the configuration this will verify the mapping is right. Very often I move things around in the domain into different namespaces and forget to update Castle. I supposed you could use reflection on your assembly as another test and verify the mapping is there, but not every type in the system is going to be dependency injected so that's probably not feasible.

    Thanks to the Castle guys for helping me get the simplest syntax going for this.

  • Plumbers @ Work, Catching up with the Kovacs

    James "The Godfather" Kovacs has been a busy beaver. We've been recording our podcast show, Plumbers @ Work, but post-editing the show has been dreadfully slow. James has pulled his rabbit out of his hat and posted not 1, not 2, but 3 podcasts online!

    So if you're looking to catch up with the plumbers then this is your chance. It was James and myself for the first episode, then James and John for the second two shows.

    The last podcast was a bit of an experiment with ooVoo, a multi-user video chat tool. James and John tried it out (I was MIA for some reason, probably drunk and passed out in the basement or something) and it looks pretty good. There's an audio only MP3 version here and you can view the video podcast via Silverlight here.

    Hopefully I'll get my act together for the next taping (we generally tape the show on Sundays) and we'll have a 3-way video conference going.

    Talk to you soon!