The blog of dlaa.me

A big day for development tools [AJAX Control Toolkit release!]

A short while ago we published the 11119 release of the AJAX Control Toolkit to coincide with today's release of .NET 3.5 and Visual Studio 2008! As usual, we have published "source" and "no-source" versions for .NET 2.0/Visual Studio 2005 and .NET 3.5/Visual Studio 2008.

The content of the 11119 release is largely the same as our previous 10920 release, with most changes being minor tweaks to the .NET 3.5 flavor of the Toolkit:

  • All web.config files were updated to match the shipping configuration of ASP.NET/AJAX 3.5.
  • The AssemblyVersion/AssemblyFileVersion of the .NET 3.5 version of AjaxControlToolkit.dll was changed from 1.0.x.y to 3.5.x.y to more clearly identify its association with .NET 3.5 (the .NET 1.0 version of the assembly remains as 1.0.x.y).
  • All of the new code analysis warnings resulting from improvements to the VS 2008 code analysis feature were addressed.
  • The "Add Page Method" design-time feature was re-enabled because the blocking issue in VS 2008 Beta 2 was been fixed.
  • A design-time workaround for XML namespace alterations to a control's inner property content was removed because the problematic VS 2008 Beta 2 behavior was addressed.
The following changes were common to both the .NET 1.0 and .NET 3.5 flavors of the Toolkit:
  • A minor documentation correction was made to the ModalPopup sample page's descriptions of the OkCancel* properties.
  • A fix was made to AutoComplete to better support the use of purely numeric values.

As always, it's easy to sample any of the controls (no install required). You can also browse the project web site, download the latest Toolkit, and start creating your own controls and/or contributing to the project!

If you have any feedback, please share it with us on the support forum!

Bigger isn't always better [How to: Resize images without reloading them with WPF]

I've been doing some work with Windows Presentation Foundation lately and came across a scenario where an application needed to load a user-specified image and display it at a fairly small size for the entire life of the application. Now, WPF makes working with images easy and I could have simply used the Image class's automatic image scaling and moved on. But it seemed wasteful for the application to keep the entire (arbitrarily large!) image in memory forever when it was only ever going to be displayed at a significantly reduced size...

What I really wanted was a way to shrink the source image down to the intended display size so the application wouldn't consume a lot of memory storing pixels that would never be seen. The WPF documentation notes that the most efficient way to load an image at reduced size is to set Image's DecodePixelWidth/DecodePixelHeight properties prior to loading it so WPF can decode the original image to the desired dimensions as part of the load process. However, the comments in one of the overview's samples explain why this isn't suitable for the aforementioned scenario:

// To save significant application memory, set the DecodePixelWidth or
// DecodePixelHeight of the BitmapImage value of the image source to the desired
// height or width of the rendered image. If you don't do this, the application will
// cache the image as though it were rendered as its normal size rather then just
// the size that is displayed.
// Note: In order to preserve aspect ratio, set DecodePixelWidth or
// DecodePixelHeight but not both.

Basically, the problem with this approach occurs when an application doesn't know the aspect ratio of the image before loading it: the application doesn't know whether to set DecodePixelWidth or DecodePixelHeight to constrain the larger dimension. If the application picks the right one (width vs. height), then the image will be properly resized to fit within the bounds of the application - but if it picks the wrong one, then the image will be resized some but will still be unnecessarily large (though less unnecessarily large than before!). While the application could arbitrarily pick one dimension to constrain, load the image, check if it guessed correctly, and reload the image with the other constraint when necessary, I was looking for something a little more deterministic. After all, sometimes you get only one chance to load an image - or someone else loads it for you - or the cost of loading it a second time is prohibitive, so it's nice to have a way to dynamically resize an already-loaded image.

After a search of the documentation didn't turn up anything promising, I wrote a small helper function using the handy RenderTargetBitmap class to generate a new, properly sized image based on the original. The code for that method ended up being fairly simple:

/// <summary>
///
Creates a new ImageSource with the specified width/height
/// </summary>
///
<param name="source">Source image to resize</param>
///
<param name="width">Width of resized image</param>
///
<param name="height">Height of resized image</param>
///
<returns>Resized image</returns>
ImageSource CreateResizedImage(ImageSource source, int width, int height)
{
  
// Target Rect for the resize operation
  Rect rect = new Rect(0, 0, width, height);

  
// Create a DrawingVisual/Context to render with
  DrawingVisual drawingVisual = new DrawingVisual();
  
using (DrawingContext drawingContext = drawingVisual.RenderOpen())
  {
    drawingContext.DrawImage(source, rect);
  }

  
// Use RenderTargetBitmap to resize the original image
  RenderTargetBitmap resizedImage = new RenderTargetBitmap(
      (
int)rect.Width, (int)rect.Height,  // Resized dimensions
      96, 96,                             // Default DPI values
      PixelFormats.Default);              // Default pixel format
  resizedImage.Render(drawingVisual);

  
// Return the resized image
  return resizedImage;
}

[Note: If you want to see this code in action, you can download the complete source code for a sample application (including Visual Studio 2008 solution/project files) that's attached to this post (click the WpfResizeImageSample.zip link below).]

Basically, the CreateResizedImage method works by creating a new image of exactly the size specified and then drawing the original image onto the new, blank "canvas". WPF automatically scales the original image during the drawing operation, so the resulting image ends up being exactly the right (smaller) size. All that remains is for the calling application to do a bit of math on the original image's dimensions to determine how to scale it, pass that information along to CreateResizedImage to get back a properly sized image, and then discard the large original image. It's that easy.

WPF and XAML make it easy to author compelling user interfaces. But sometimes it's worth a little extra effort to optimize some aspect of the user experience. So if you're looking to trim the fat from some of your in-memory images, consider something like CreateResizedImage to help you out!

[WpfResizeImageSample.zip]

Tags: WPF

Something fun for the little ones [SilverlightKidsDoodler develops mouse skills!]

When I'm working on the computer and my toddler is around, she usually wants to "type" - which consists mostly of hitting all the keys to see the letters appear on the screen. A maximized Notepad window works pretty well for this purpose, though the occasional modal dialog (ex: open file, change font) gets in the way and requires parental assistance. I've tried using Paint to let her "draw" and develop basic mouse skills, but the Paint user interface is not great for young children. Paint's input elements are small and hard for a beginning mouser to click and there are lots more of them than a beginner really needs.

So I decided to use Silverlight to write a very simple Paint-like program for kids. SilverlightKidsDoodler looks like this (the artwork is mine; yes, I'm keeping my day job):

SilverlightKidsDoodler Demonstration Page

You can click here (or on the image above) to try SilverlightKidsDoodler in your own browser. As usual, I've made the complete source code available, so click here to download the source code and play around with it yourself! (To build the project, you'll want to use Visual Studio 2008 Beta 2 and the latest Silverlight Tools.)

Notes:

  • The user interface elements (the color palette and action buttons at the left of the frame) are flush with the edges of the screen (when zoomed) to make them easy for young hands to target. (Bruce Tognazzini has more on Fitts's Law here.)
  • The "Zoom" button switches to Silverlight's full-screen mode. Unlike the other input elements which respond to a single-click, the zoom button requires a double-click to avoid accidental triggering by children. I figure the parent will start SilverlightKidsDoodler, zoom it, and then let the child play around without needing to worry about clicks on the close button, start menu, etc..
  • If you're serious about keeping children from inadvertently messing up your computer, you probably want to consider something like Windows SteadyState which makes it easy to lock-down your computer and avoid questions like, "Sweetie, where did all of daddy's documents go?". :)
  • As my daughter grows older and becomes more proficient, I'm thinking of moving her to something like Edubuntu which comes with a variety of educational applications already installed.

SilverlightKidsDoodler is an extremely simple drawing program that's intended to help young children learn basic mousing skills while having fun doing something they already enjoy. Silverlight made the implementation easy, and hosting the application on the web means "installation" is trivial!

Bringing more HTML to Silverlight [HtmlTextBlock improvements]

I blogged about my HtmlTextBlock implementation for Silverlight a few days ago. In that post I described HtmlTextBlock as a "plug-compatible" replacement for TextBlock that knows how to take simple HTML (technically XHTML) and display it in a manner that fairly closely approximates how a web browser does. The responses I've gotten suggest HtmlTextBlock is somewhat popular, so I've spent a bit of time improving upon the original implementation. The HtmlTextBlock demonstration and source code linked to by my earlier post have been updated, so feel free to play along as you read the notes:

HtmlTextBlock Demonstration Page

Notes:

  • I loved the simplicity of using an XmlReader to parse the input to HtmlTextBlock, but I worried that the prevalence of non-XHTML would limit the usefulness of HtmlTextBlock. For example, the following invalid XHTML would fail to parse correctly: foo<b>bar</i>baz. During an informal discussion, Ted Glaza suggested using the browser's Document Object Modelto do the parsing of invalid XHTML - great idea! :)
    • So now when its Text property is set, HtmlTextBlock first treats the input as valid XHTML and tries to parse it with XmlReader. This is the most efficient code path and should be successful for any valid XHTML input.
    • However, if the input can't be parsed in that manner, HtmlTextBlock uses the objects in Silverlight's System.Windows.Browser namespace to dynamically insert the provided text into the host browser's DOM, run some JavaScript code to transform the input into valid XHTML, then extract and parse the transformed text with XmlReader as before.
    • Two techniques are tried:
      • The first method works in browsers that return XHTML for an element's innerHTML property even if the contents of the element are not valid XHTML (ex: Firefox) and simply inserts and retrieves XHTML from the innerHTML property.
      • The second method works in browsers that return the contents of an element as-is (ex: Internet Explorer (though it works fine in Firefox, too)) by walking the node's .firstChild/.nextSibling/.nodeName tree and manually building up the corresponding XHTML as the nodes of the tree are visited. The results of this method appear ideal in most scenarios, though it's possible to come up with edge cases where its output is slightly different from that of the browser itself (Internet Explorer): foo<b><i>bar</b>baz.
    • Strangely, BOTH browsers prefer <br> to <br/>, going as far as transforming the latter into the former despite the fact that doing so creates invalid XHTML!
    • If all parsing attempts fail, the supplied text is used as-is with no formatting applied.
    Unfortunately, there's a catch... Depending on the content of the text, adding it to the DOM could insert untrusted HTML into the host browser's page. A malicious user with control of the text could use the following approach to run their own JavaScript code in the context of the user's browser (Firefox only): </div><script>alert('Script code running!');</script>. As such, the new DOM parsing behavior is disabled by default and can be enabled by setting the UseDomAsParser property of HtmlTextBlock for scenarios when the input text is known to be safe.
  • A kind reader informed me that an HtmlTextBlock created in code (vs. in XAML as my sample demonstrated) did not seem to do text wrapping properly. The problem was caused by the difference in when the Control.Loaded event fires in the two scenarios. The fix is a simple change to HandleLoaded that skips sizing the contained TextBlock if the HtmlTextBlock hasn't been sized itself. Additionally, the sample code now demonstrates how to create a HtmlTextBlock in code - just #define CREATE_IN_CODE to see how.
  • Because HtmlTextBlock used bool variables to track the bold/italic/underline states, nesting a style caused that style to be prematurely removed. Specifically, the following scenario would not display properly: normal <b>bold <b>also bold</b> still bold</b> normal. HtmlTextBlock now handles nesting properly by using int variables.
  • I mentioned last time that making HtmlTextBlock adhere to all the individual browser quirks would be a daunting task. For fun, here's a simple input to demonstrate the point: <p>hello world</p>. Firefox (and HtmlTextBlock) leaves some space above the text because of the <p> element; Internet Explorer does not. :)

In its introductory post, I said that HtmlTextBlock is obviously nothing like a complete HTML rendering engine - and that statement remains true today. However, by taking advantage of the host browser's DOM to transform invalid XHTML input, HtmlTextBlock is much more flexible than it used to be. That - and a few fixes - makes it an even more compelling option for rich text display in Silverlight!

You voted lots, we fixed lots [AJAX Control Toolkit release!]

Last night we published the 10920 release of the AJAX Control Toolkit. This release continued our trend of focusing on the most popular bugs and work items identified by the user community in the support forum and online issue tracker. A number of popular issues got fixed in this release, addressing nearly 1000 user votes!

The release notes from the sample web site detail the improvements:

General fixes:

  • Controls with Embedded styles (Calendar, Tabs and Slider): Toolkit controls no longer need explicit style references when loaded asynchronously. For example, if a Calendar control is placed inside an UpdatePanel and made visible on an UpdatePanel postback, the embedded styles are now loaded properly.
  • PopupBehavior positioning (AutoComplete, Calendar, DropDown, HoverMenu, ListSearch, PopupControl and ValidatorCallout): PopupBehavior now respects the position of its parent element even when the browser window is very narrow or the parent element is close the window edge.
  • Focusing extended controls (Accordion, CollapsiblePanel, DropShadow, Tabs): Pages that use Toolkit controls which re-parent DOM elements can use a workaround to focus a specific element on page load. The new method Utility.SetFocusOnLoad ensures that the desired control receives focus.

Control specific fixes:

  • Calendar: Property to specify the position of Calendar, a default date feature that allows the calendar to start out with a selected date, and a consistent show, hide and focus story that makes the Calendar user experience more intuitive.
  • ModalPopup: Ability to disable repositioning of the ModalPopup in response to window resize and scroll.
  • ConfirmButton: ModalPopup functionality now supported in addition to the regular windows alert dialog.
  • MaskedEdit: Extended Textbox no longer uses Invariant culture if no CultureName is specified and falls back to the Page Culture.
  • AutoComplete: Allow users to associate additional data with the AutoComplete suggestions.
  • Slider: Slider can be easily customized using its various CSS properties.

As with the previous release, we have published "source" and "no-source" versions for .NET 2.0/Visual Studio 2005 as well as for .NET 3.5/Visual Studio 2008 (still in Beta). Unique to the 3.5/2008 versions are the following:

Features:

  • JavaScript IntelliSense support: We have added reference tags to all Toolkit JavaScript files that enables you to take advantage of new features in Visual Studio 2008 Beta 2. With the multi-targeting support in this Visual Studio Beta, IntelliSense will be available for the ASP.NET AJAX 1.0 flavor of the Toolkit as well. This article discusses the reference tag feature in detail.
  • Extender designer support: Enhanced designer support for Toolkit controls using the new "Add Extender" user interface.

One thing we'd hoped to include with this release didn't quite make it in: our new automated testing framework. This framework is based on a different approach than our current framework - one that makes it easy to add additional test cases and leverage existing ones across new scenarios. The new testing framework has already dramatically improved our test coverage, helped identify new issues, and made fixing existing issues less risky!

But we've been iterating on the new framework for the past couple of weeks and faced the usual decision when it came time to finalize this release: slip or ship. We slipped our release date a little in the hopes that we'd be able to include the new framework with this release, but eventually decided not to delay all the great new Toolkit code any longer. We wanted our users to take advantage of the new bits ASAP - so stay tuned for more on the new testing framework in a future release!

As always, it's easy to sample any of the controls (no install required). You can also browse the project web site, download the latest Toolkit, and start creating your own controls and/or contributing to the project!

If you have any feedback, please share it with us on the support forum!

Bringing a bit of HTML to Silverlight [HtmlTextBlock makes rich text display easy!]

Lately I've seen a few people wanting to display rich text in a Silverlight application, but having no way to do so easily. Most recently, I saw Tim Heuer bump into this when displaying RSS content in a neat demo of his. The basic problem is that Silverlight's primary text display object, TextBlock, does not natively have a way to display HTML - and that's the format most rich text is in these days. It seemed that if only there were a TextBlock that took HTML as input and built up a collection of Run and LineBreak objects corresponding to that HTML, things would be easier...

So I wrote HtmlTextBlock, a "plug-compatible" replacement for TextBlock that knows how to take simple HTML (technically XHTML, see the notes below) and display it in a manner that fairly closely approximates how a web browser does. A picture is worth a thousand words, so here's what HtmlTextBlock looks like in action:

HtmlTextBlock Demonstration Page

You can click here (or on the image above) to experiment with HtmlTextBlock in your own browser in an interactive demo page. As usual, I've made the complete source code available, so click here to download the source code and play around with it yourself! (To build the project, you'll want to use Visual Studio 2008 Beta 2 and the latest Silverlight Tools.)

Notes:

  • HtmlTextBlock supports the following HTML elements: <A>, <B>, <BR>, <EM>, <I>, <P>, <STRONG>, and <U>. Attributes are not supported with the exception of the <A> element's HREF attribute (see below).
  • I initially planned to have HtmlTextBlock derive from TextBlock and simply override its Text property. However, TextBlock is sealed, so that wasn't going to work. The next obvious approach was to have HtmlTextBlock be a Control with a TextBlock inside it, so that's what I've done here. My goal of "plug-compatibility" (i.e., the ability to easily replace TextBlock with HtmlTextBlock) meant that I needed to manually implement the various TextBlock properties on HtmlTextBlock and pass them through to the underlying TextBlock. So HtmlTextBlock doesn't actually derive from TextBlock, but it behaves as though it did.
  • Having HtmlTextBlock use TextBlock internally and represent the HTML markup with Run and LineBreak elements is nice because it means that just about everything people already know about TextBlock automatically applies to HtmlTextBlock And I get correct word wrapping behavior for free. :) However, the glitch is that the Run element does not support the MouseLeftButton* family of events, making the handling of <A> link elements difficult. Because HtmlTextBlock can't really tell when the user clicks on a link, it displays the URL of each link so the user can type it in themselves (and typing is necessary because TextBlock doesn't support select+copy either). I can think of a few reasons why Run might not support mouse events, but in this case it would be convenient if it did. :)
  • HtmlTextBlock uses an XmlReader to parse its input when creating the Run and LineBreak elements for display. This makes the parsing implementation simple and robust, but breaks down when the input is not XHTML (such as invalid HTML or valid HTML where empty elements don't have a trailing '/' (ex: "<br>" instead of "<br />")). In the event of a parsing error, HtmlTextBlock's default behavior is to display the input text as-is, just like TextBlock always does. Unfortunately, non-XHTML is pretty common, so certain scenarios may benefit from a custom HTML parser implementation that is more flexible in this regard.
  • HTML rendering is covered by a detailed specification, but some of the rules are not what one might expect. Specifically, the rules for handling spacing and whitespace (' ', '\n', '\t', etc.) can be tricky to get right. I've made some attempt to ensure that HtmlTextBlock follows the rules where possible and convenient, but it was not my goal to achieve 100% compliance in this area. Playing around in the demo application, HtmlTextBlock should pretty closely match the browser's HTML rendering of valid input, but if you know the rules, it's not too difficult to trigger whitespace rendering differences.
  • Silverlight's default font, "Portable User Interface"/"Lucida Sans Unicode"/"Lucida Grande" doesn't seem to render bold or italic text any differently than normal text. This always surprises people the first time they try to figure out why their text isn't bold/italic. I don't know why this is myself, but I'd guess it relates to keeping the download size of Silverlight to a minimum.
  • The demo page makes use of JavaScript -> C# function calls. Hooking this up in code is surprisingly easy, though I did run into a small glitch. If the sample text is deleted entirely (leaving a blank text box) in IE, the JS -> C# call originates from the JS side as it should, but never makes it through to the C# side. Looking at the call to SetText in the debugger, textAreaSampleText.value is "", so this should work in IE just like it does in Firefox - but it didn't for me. The simple workaround was to pass textAreaSampleText.value + "" instead and then things worked in IE, too.

HtmlTextBlock is obviously nothing like a complete HTML rendering engine [that's what web browsers are for! :) ]. However, if you want to add simple support for rich text to your Silverlight application without a lot of work, HtmlTextBlock may be just the thing for you!

Time for a little fun and games (Silverlight helps play Sudoku!)

I'm not much of a Sudoku player, but I was recently in the company of some and got an idea for a Silverlight application to help solve Sudoku puzzles. There are already plenty of fine Sudoku programs out there, so I didn't set out to write "the world's best Sudoku program". Rather, this was an opportunity to explore some aspects of Silverlight that I haven't shown off yet such as audio, keyboard input, control embedding, and some more animation.

Sudoku is a surprisingly complex game and its puzzles range from very easy to quite difficult. Naturally, there are a number of different techniques that can be used to solve a Sudoku puzzle. Most of the techniques rely on keeping track of what the valid candidates for each cell are. Keeping track of all the candidates is too much for most people to do in their heads, so the common approach is to maintain a collection of pencilmarks. Keeping the pencilmarks up to date is a simple, monotonous task that involves no creativity whatsoever - and is perfect for a computer!

The Silverlight Sudoku Helper displays a Sudoku puzzle, automatically tracks the valid candidates, and leaves the creative problem solving fun to the user. It also prevents illegal moves and plays some fun sounds. :) The application looks like this:

Silverlight Sudoku Helper

You can click here (or on the image above) to play a game of Sudoku in your browser. As usual, I've made the complete source code available, so click here to download the source code and play around with it yourself! (To build the project, you'll want to use Visual Studio 2008 Beta 2 and the latest Silverlight Tools.)

Notes:

  • Directions for how to use the application can be found at the bottom of the Silverlight Sudoku Helper web page.
  • The sample boards from Wikipedia and Sudopedia are included to make it easy to get started and are believed to be free of copyright restrictions.
  • I came up with the "nearly complete" sample board myself and hereby release it to the public without copyright restrictions. :)
  • There is no mechanism to automatically import boards from other sources because most of the sources I came across made a point of restricting the use of the boards they offered in one way or another. That's why it's easy to create a blank board and type in any board you want (hint: use the Shift key when typing to bold the given values).
  • The audio files were taken from the %windir%\Media directory, renamed slightly, and converted to the WMA file format for use by Silverlight. They are not included in the source code package to keep the download size small (if you download the sample code and get an error 1001/DownloadError when viewing the application, it's probably because the audio files are missing). Feel free to substitute your own favorite sounds!
  • The key handling is done on KeyUp instead of KeyDown because Silverlight does not generate KeyDown events for the arrow keys. If/when this is addressed, the key handling could be done on KeyDown instead as the more natural place (where it should automatically support holding down a key to repeat it).

I didn't know much about Sudoku when I started this project and it turned out to be a more involved game than I'd thought! I hope the Silverlight Sudoku Helper is fun and educational for others as well!

A new Silverlight version has been released! [Samples updated for the 1.1 Refresh]

With today's release of the Silverlight 1.0 RC and 1.1 Refresh, I've updated the Silverlight samples I own to run on the new bits. Specifically, I've uploaded the migrated source code and recompiled binaries for the team's Silverlight Airlines Demo, my Simple XPS Viewer Demo, and my Silverlight Surface Demo. Because the Silverlight 1.1 Refresh replaces the earlier 1.1 Alpha, the existing source and demo URLs remain the same and simply point to the new content.

The 1.1 Refresh's breaking changes from the 1.1 Alpha build we've all been using before today are documented in the SDK. The migration of the these samples was pretty simple and required very little code change. For the benefit of others migrating Silverlight apps, here are the specific incompatibilities I encountered along with the fix for each:

  • Silverlight.js content updated and namespace changed from Sys.Silverlight to Silverlight - use new version of Silverlight.js, change CreateSilverlight.js to use the new namespace, and specify version "1.1" in the call to createObject(Ex)
  • Downloader.Open API changed to remove third parameter ("async") because all downloads are now asynchronous - change call sites to pass only two parameters since they were already passing true for async
  • Assignment of DoubleAnimation to new Storyboard's Children property now throws an exception - use a Control class and InitializeFromXaml to load the Storyboard and Animation from a XAML resource
  • Visibility enum no longer contains .Hidden value - use .Collapsed instead
  • OnResize is now function pointer-based instead of string-based - pass function pointer instead

Additionally, a security-related change to the Downloader object now blocks access to file:// URLs. This means that the XPS Viewer and Surface demos will only be able to access their resources (images, files, etc.) when the host page is loaded from a web server. Specifically, loading Default.html from Explorer or by hitting F5 to run the project in Visual Studio will now result in an error message like the following:

Silverlight error message
ErrorCode: 1001
ErrorType: DownloadError
Message: AG_E_UNKNOWN_ERROR

To re-enable debugging for the XPS Viewer and Surface demos, I recommend the following steps which add a web site project to Visual Studio and access the demo page via the included Visual Studio Development Web Server (which uses http:// URLs and works fine). While there are other ways to work around the file:// restriction, I'm suggesting this approach because it automatically references the project files, doesn't require creating additional directories or copies of project files, and doesn't require getting involved with IIS. To enable debugging:

  1. From the File menu in Visual Studio 2008, click Open, Project/Solution...
  2. Select the .csproj file for the demo you want
  3. Click OK
  4. From the View menu, click Solution Explorer
  5. Right-click the Solution node at the top
  6. Click Add, Existing Web Site...
  7. Select the same directory the .csproj file is in
  8. Click OK
  9. Click No when asked to upgrade the web site
  10. Right-click the new Web Site Project node
  11. Click Property Pages
  12. Click Start Options in the left column
  13. Check Silverlight in the Debuggers section at the bottom right
  14. Click OK
  15. Right-click the new Web Site Project node
  16. Click Set as StartUp Project
  17. Press F5 to Run
  18. Click OK to enable debugging in web.config

Okay, enough with the boring details - go get the Silverlight 1.1 Refresh and have some fun with it! :)

A new Framework deserves a new Toolkit [AJAX Control Toolkit updated for .NET 3.5 Beta 2!]

Earlier today Microsoft announced Beta 2 of Visual Studio 2008 and the .NET Framework 3.5. As usual, Scott Guthrie has a bunch of reasons why the new stuff is cool. My team has one more reason to add to the list:

We've just updated the 10618 Toolkit release with Beta 2 versions of the AJAX Control Toolkit that work seamlessly with VS 2008 and .NET 3.5!

The Toolkit's new "Framework3.5" downloads contain the latest 10618 Toolkit code in a VS 2008 Beta 2 solution/project. What we've done is make a handful of tweaks to better integrate with the new VS 2008 web designer enhancements for ASP.NET AJAX extenders. As you'd expect, the Toolkit controls work the same as before - but the development experience with VS 2008 is better than ever.

Download Visual Studio 2008 with the .NET Framework 3.5, the .NET 3.5 Beta 2 Toolkit, and find out for yourself!

And if you have any feedback, please share it with us on the support forum.

An easy way to keep your windows where you want them [Releasing WindowPlacementTool with source code!]

I wrote WindowPlacementTool in December of 2000 to solve a problem I had after beginning to use Terminal Services/Remote Desktop regularly. I made WindowPlacementTool available internally in 2001. Last week someone asked about getting access the source code to make some customizations and I figured I'd post the tool and its source here for anyone to use.

Download WindowPlacementTool and its source code by clicking here.

Details:

Summary
=======

If you're picky about the layout of the windows on your desktop or if you
connect to your machine with Terminal Services at differing resolutions, you're
probably annoyed by having to re-layout your windows on a regular basis.  It
seems like something (or someone!) is always coming along and messing with your
layout.  But now that's a problem of the past; WindowPlacementTool can do all
the work for you!  Just run it once to capture the layout you like, and then
run it again whenever you need to restore that layout.  And because you can
save multiple layouts, switching resolutions is a breeze.  Yep, it's that easy!


Command Line Help
=================

WindowPlacementTool
Copyright (c) 2000 by David Anson (DavidAns@Microsoft.com)

[-h | -help | -?]
        This help screen

[-c | -capture] [Capture_file_name.txt]
        Capture the current window positions to a file (or standard output if
        no file name is given)

[Restore_file_name_1.txt] [Restore_file_name_2.txt] ...
        Restore the window positions from the data previously captured in the
        specified file(s) (or standard input if no file name is given)


Example Setup
=============

[Layout your windows however you'd like them]

[Capture the current layout to a file]
C:\Temp>WindowPlacementTool.exe -c 800x600.txt

[Optional: Edit the file to remove any programs you don't care about]
C:\Temp>notepad 800x600.txt

[Optional: Create a shortcut on your desktop for easy access to this layout]
[Here, the shortcut would run "WindowPlacementTool.exe C:\Temp\800x600.txt"]


Example Use
===========

[Run the shortcut you created above or run WindowPlacementTool manually]
C:\Temp>WindowPlacementTool.exe 800x600.txt


Notes
=====

* WindowPlacementTool saves the RESTORED locations of windows.  If a window is
  currently maximized or minimized, its restored location will be adjusted, but
  the window will not be un-maximized or un-minimized by WindowPlacementTool.
* I have placed a shortcut to a layout for each resolution I use on my taskbar
  so that it's always available when I need it.

Additional notes:

  • When restoring window positions, the window class name must match the saved value exactly, but the window title comparison is just a substring match. This makes it easy to target windows that change their window title depending on the current document. (Example: "Untitled - Notepad" and "File.txt - Notepad" will both match the window title string "Notepad".)
  • The code for WindowPlacementTool was written many years ago and may not follow conventional coding standards. Feel free to reformat it in your favorite editor. :)
  • I've made only the necessary modifications to get the original code compiling successfully under Visual Studio 2005 SP1. I specifically did NOT spend time resolving the four new compiler warnings.
  • While I've always tried to take security and correctness seriously, the original code was written well before security was as big an issue as it is today. Recent modifications to Microsoft's CRT have deprecated some functions in favor of safer alternatives. This is the source of 3 of the 4 compiler warnings; read more about security enhancements in the CRT for additional details. The 4th compiler warning is due to improved CRT warnings associated with the increasing popularity of 64-bit computing (specifically compiler warning C4267). My code is typically error and warning free at warning level 4, but it's hard to be immune to future enhancements to the compiler/CRT. :)
  • Parts of the original code (ASSERT, VERIFY, ARRAY_LENGTH, WideString/AnsiString, _sntprintfz) used a helper library I wrote - I've pulled the relevant bits of that library into the main CPP file to remove the external dependency. Strsafe.h wasn't around at the time, but some of the code in this helper library of mine was already doing similar things. For example, the *z string functions improved upon the * versions by preventing buffer overflows and guaranteeing null-termination of the target string (i.e., strcpyz vs. strcpy).
  • While the source code compiles under VS 2005, the EXE included in the ZIP archive contains the bits as they were compiled back in 2000 with whatever compiler was current at the time.

WindowPlacementTool has served me well over the years - I hope others find it useful and/or educational!