I received a phone call out of the blue a few weeks back from US customs informing me that they had received an animal's head with my name as the listed recipient, and could I tell them what animal it was, what country it was from, whether it had been killed humanely, and whether it was certified disease-free! Of course, I had no idea what was arriving so I was wondering whether someone was trying to send me a nasty signal!
My wife gamely went down to SeaTac airport to try and persuade the customs folk to release the delivery to us, and after several hours of driving around in circles trying to find the tiny office and then grovelling to a variety of bureaucrats, she managed to get them to release it.
Finally we opened the package to discover a really unusual leaving gift from my old team back in the UK: a real pair of horns from a Longhorn! They're now proudly mounted on the wall of my office, and have attracted a great deal of interest from many of the people who wander down my corridor trying to find where Robert Scoble sits. They're signed by the team, and they will remind me of many happy memories - thanks guys!
So to the moral of the story: Longhorn is definitely shipping, but it might be held up in customs... :-)
I've been taking a short timeout to look forward to the year ahead and just to let some thoughts percolate a little. Most companies encourage their employees to set down some commitments or objectives for the year ahead on a professional level, and this is a good thing, right? It helps to focus the mind, prioritise and manage conflicts and measure performance at an end-of-year review. But we rarely take the time to do the same for our personal life. I truly want to set time aside on a regular basis for a little self-appraisal. To look at who I am and who I want to be. To be intentional about my life and not have life simply be something that happens to me.
As I took a quick lunchtime walk around the campus here in Redmond and enjoyed the brisk air and mountain views, it reminded me how much of a rush everyone is in. In just a few short minutes, I saw several drivers speeding around campus in a mad dash to get to the next meeting, someone reading a book on work/life balance whilst they sped-walk to their next building, the general hubbub of people speed-talking their way through lunchtime meetings, and literally nobody else taking time out. This is a campus filled with people in the prime years of their life, and everyone is speeding through their 20s/30s in the mad race to work hard / play hard. The upshot is that I know too many people who have been burnt out by this lifestyle, and even more who are tetchy, stressed and exhausted by the unsurmountable workload.
I wish I had some straightforward answers to this - I could then write the next self-help book that would sell by the truckload and retire early to some luxury yacht moored just within WiFi range of beautiful coastline. In the meantime, I've put together a much more humble set of personal objectives that I'm going to try to live by.
As a result of overwhelming customer feedback, we've now made the Avalon November CTP available to anyone who wants to get their hands on it, whether or not you've got an MSDN subscription. This is the first release of Avalon that supports Windows XP and Windows Server 2003. It's pretty stable and functional, as far as CTP releases go, and it's a great place to start if you want to experiment with what will become the strategic presentation technology for Windows over the next decade. For more information on what's contained in the CTP release and how to go about evaluating it, check out this MSDN article.
You can use any Beta 1 release of Visual Studio 2005 to code for the Avalon CTP (including the Beta 1 Refresh); check out this article on using the Express products with Avalon. Be aware, however, that later CTP releases of Visual Studio 2005 aren't compatible with this Avalon CTP drop - that's the price you pay for being on the bleeding edge! The Avalon CTP release ships with an SDK containing a fair quantity of documentation; this is also available online here. Lastly, some other useful blogs to read on Avalon include those from Chris Sells, Daniel Lehenbauer, Chris Anderson, Nathan Dunlap and Karsten Januszewski.
I've been writing a game recently using Avalon, as part of which I wanted to load and display a number of sprites and other graphical objects. There were two specific problems I wanted to resolve: what was the best way to cache the sprite images for efficient reuse, and how should I store and load the images themselves? In both cases, WinFX provided quite a neat solution that I wanted to share here.
To start with the problem of storing and loading images, the most straightforward approach would have been to simply load images from a bitmap file. Of course, then you have to deploy a series of image files with your application, which can become painful. Instead, Visual Studio allows you to embed resources directly into the application assembly, allowing you to distribute the executable code and any dependent resources as a single file. To achieve this, you simply have to add the bitmap images into your project and mark them as "Embedded Resources" within the content property (use F4 to bring up the properties window if it's not currently active). The resources then get compiled into the application itself, which you can see if you inspect the assembly with ILDASM. How do you access the bitmap image itself? It's a little opaque, but you use a command such as the following:
stream = this.GetType().Assembly.GetManifestResourceStream(file);
where file is the full filename that was embedded (e.g. "background.bmp"). You can now create an instance of BitmapImage based on this stream and use it for whatever you want: for example, you could create an ImageBrush and use it to paint the background of an element.
The second half of the problem reflects that the game I'm working on has an avatar moving around a grid of tiles. On each frame, many of the tiles need repainting, which involves loading the images again. Some kind of image cache is obviously the solution to ensuring that this gets handled with reasonable performance. Fortunately the BitmapImage class has a constructor parameter that allows exactly that:
public BitmapImage( Stream bitmapStream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption );
where BitmapCacheOption can be one of OnLoad, OnDemand or None. OnLoad is actually the default, so you get this caching goodness for free unless you explicitly unset it.
So here's the working code snippet to grab an image from an assembly resource (corrected unreachable code based on comments below):
// using System.Windows.Media; stream = this.GetType().Assembly.GetManifestResourceStream("background.bmp"); if (stream != null) { // following line throws NotSupportedException if bitmap resource // is corrupt or wrong type BitmapImage bitmapImage = new System.Windows.Media.BitmapImage( stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad); ImageBrush ib = new ImageBrush(bitmapImage); ib.TileMode = TileMode.Tile; ib.Stretch = Stretch.None; // required for TileMode to take effect MyWindow.Background = ib; stream.Close(); } else { throw new NullReferenceException("Stream is null - resource missing."); }
Incidentally, the embedded resources capability has no dependency on Avalon - you can do it just as well from a WinForms solution. Hope that helps someone. More tomorrow...