Charles Petzold

Real-Time Drop-Shadow Slam-Dunk

February 1, 2006
Nice day in New York

In his book Hackers, Steven Levy tells the story of MIT programmers who would continue to shave instructions off a decimal-print routine until a guy named Jensen took a whole different approach and completely nailed the problem. He posted his solution on a bulletin board: "his way of telling them that he had taken the decimal print routine to its limit. Forty-six instructions. People would stare at the code and their jaws would drop." (pg. 32)

That's pretty much how I felt when WinFX Tablet PC guy Shawn Van Ness sent me this little piece of XAML that does real-time drop-shadow on stylus (and mouse) input:

Obviously he's taken a much different approach to real-time drop-shadow than in my bloated WPF program or my dismal WinForms code.

In Shawn's XAML, both the Canvas and InkCanvas elements are in the same cell in the Grid panel, which means they'll overlap, the InkCanvas on top. The purpose of the InkCanvas is to collect and render stylus (and mouse) input. But notice that transparent Background property, which means we'll also be seing the Canvas underneath.

The Canvas colors its background with a VisualBrush, which is related to the DrawingBrush and ImageBrush. (All inherit from TileBrush.) But rather than using a drawing or bitmap for its surface, the VisualBrush uses a Visual, which is usually an element or a control. This particular VisualBrush binds its Visual property with the InkCanvas, which means it will display everything on the InkCanvas, but with an opacity of 50% and (due to the transform set on the Canvas) offset 3 units down and to the right.

The result is a drop-shadow. The rendering may not be real zippy, but the approach sure is elegant!

Here's a modified version of the program that renders stylus and mouse input with a pen approximately a centimeter in width, and with the shadow offset 1/4 of that width. (The DrawingAttributes class requires an explicit namespace mapping.)