ShawnVN's Blog

Programming for the Windows Tablet Foundation

  • ColorComb: Yet Another Color-Picker Dialog for WPF

    WPF v1 doesn't include a color-picker dialog (or a font dialog).  A variety of SDK samples and community samples will undoubtedly fill this void.  That's ok with me -- I've never been happy with the traditional Windows color-picker UI, anyway.  I can never find the color I have in mind, looking at this flattened-out-color-wheel-with-dingy-grey-bottom:

  • AutoClaimsFX

    In celebration of WinFX Beta2, I've attempted to recreate the Tablet PC SDK's beloved AutoClaims sample in WPF.

    This sample demonstrates: 

    • InkCanvas
      • collecting ink in multiple transparent layers, over an Image resource
      • databinding for Strokes
      • DefaultDrawingAttributes defined in static resources
      • animated Opacity and ZIndex properties for smooth transitions among layers
    • TextBox.InputScope
      • defines a pattern to coerce Tablet Input Panel handwriting recognition for the Year (YYYY) field
    • Scrolling and resizing
      • relative layout techniques
      • ScrollViewer around the Image and InkCanvas elements

    ...all in 100% pure XAML!

    Ok, admittedly it probably would've been easier to code some of those lengthy EventTriggers for managing the layers in C#.  And I'm a little bummed to discover than I can't set Panel.ZIndex in partial trust (else you'd be running this app in your browser right now, not reading about it).

    Still, it's a fun exercise in what can be done with InkCanvas and XAML, with so few lines of code compared to our WinForms platform.  You really have to compile and run the mundane old WinForms version, and peruse the code, to appreciate this WPF rendition.

    Have fun!

  • Assembly Versioning Code of Ethics (or: Dipping Your Toes in the Warm, Gentle Waters of Code-Gen)

    Prompted by an email on the dotnet-clr list, I took a moment to write down my Assembly Versioning Code of Ethics. These rules are not enforced by .NET or the CLR in any way -- but I think I speak for virtuous developers everywhere when I say:

    I.  Thou shalt bump at least the "minor" field, when making a change that might affect existing client code.

    II.  Thou shalt bump at least the "revision" field, when making any other change, whatsoever.

    I hate to make an example out of anyone, but a certain SDK team at MS has broken both of these simple commandments over the past 18 months, and each time it's caused quite a lot of frustration.

    Post RTM, the Tablet PC team has published one additional point-release of their SDK.  They bumped the version number on the Microsoft.Ink.dll assembly (the managed wrapper for the Tablet API) from v1.0.2201.0 to v1.0.2201.2.  Now, I don't know what happened to the intervening 2201.1 release, but still, the small hop from 2201.0 to 2201.2 certainly looks like a innocuous little bug-fix patch, right?

    But no -- they've added IDisposable implementations to about half a dozen of the most heavily-used classes, and updated the documentation to imply that if we don't call Dispose() then our apps will leak -- that's a breaking change, darnnit!

    Prior to the RTM release of the SDK, they were guilty of the second sin, as well: distributing multiple versions of the assembly, all under the v1.0.2201.0 label.  It was unfeasibly difficult to distinguish between them "in the field" (eg: on a coworker's misbehaving test box).  These doppelganger assemblies were just internal alpha and/or beta releases, but still, such needless confusion -- why?

    I know why.  In fact, I'm guessing this story sounds painfully familiar to a lot of readers out there.  The problem is human: it's a royal p.i.t.a. for developers to remember to bump the revision number, by hand, with each build they send off to the QA department.  In the unmanaged world, binaries were (usually) not signed, and so details like version-info could be patched up in the very last build stages, by setup/integration engineers whose jobs it is to think about these things.  Versioning is too important to rely on 100% unfailing compliance from 100% of all developers on your team.

    The good news: with just five minutes of effort, you can automate this problem out of existence!

    I've become fond of auto-generating an AssemblyVersion.cs file, pre-build, with the low-order 32 bits of the version number (the build- and revision-fields) based loosely on the current date and time.

    For example: if I released a new product right now, I might stamp it v1.0.2003.916... Or maybe even v1.0.2003.9169 -- where the last digit (9) is computed something like (10*DateTime.Now.Hour/24).  We only have 16 bits per field to work with, so we mustn't go crazy trying to squeeze in a full-
    fidelity timestamp -- it won't happen, and it's not worth sacrificing the readability of the build-date in the version.

    Some might be tempted to go further down the "version == build-time" road, eg: v2003.9.16.2315... but that doesn't easily let one release, say, a new security patch for a product that's one or more revs past its prime.

    Why not?  In .NET, version numbers are comparable (in the System.IComparable sense) so it's not cool to release a new patch for last year's code, which compares as anywhere close to the same patch for the current generation product. This is not just academic: someday, you or your users may wish to apply binding-redirect policies to your software, based on declared ranges of version numbers!  Reserving the high-order fields in the version number to represent a logical product release is a huge help, in that case.

    Besides, there's an alternative available:  If you really want to stamp your assemblies with a human-readable, full-fidelity build timestamp, check out the AssemblyInformationalVersion attribute, which allows you to supply a whole string, of your own devising (eg: DateTime.Now.ToString() ;-).

    Here's the X-Code .NET template I use to generate an AssemblyVersion.cs file, for all my C# projects.  (This technique, if not the exact template code, should be easily portable to CodeSmith or other template-based preprocessors.)  The end result? I sleep soundly at night, knowing that my build environment will automatically and unfailingly increment my assembly version number, every few hours.

    var now:DateTime = DateTime.Now;
    var build:short = (short)(now.Year);
    var revision:short = (short)(now.Month*1000 + now.Day*10 + now.Hour*10/24);
    [assembly: System.Reflection.AssemblyVersion(
     "<%= major %>.<%= minor %>.<%= build %>.<%= revision %>"