The InkCanvas Tutorial and Me Cutting Corners

February 10th, 2008     |     View Comments

A few moments ago, I published my latest tutorial covering all of the cool things you can do with the InkCanvas control. I’ve been writing about the ink canvas feature for a while on this blog, so it just made sense to consolidate all of the information into one location. When proofreading the text one last time, I noticed something bizarre in one of the screenshots found on the last page.

I’ve posted the screenshot below:

Do you see what is odd about it? Look at the colors in the titlebar to the left of the minimize button. If you still can’t see it, take a look at the part I’ve emphasized below in the screenshot:

bizarreColoration

In case your monitor doesn’t show the difference, there is a hard jump in the blue between the left and right halves. Naturally, it would be a smooth gradient. This is where the cutting corners part comes in.

Confessions of a Corner Cutter
For all images used on the site, they have to be less than 500 pixels in width. This image originally posted on the blog was 539 pixels wide. The solution is simple. Simply run the application again, resize the window, and take a new screenshot. That solution would have worked for any application except this one.

Unfortunately, this time, I would have had to painstakingly draw out the Hi :) text from scratch using my mouse in my new application instance. I was clearly not going to do that, so instead, I did the following:

  1. I took the original wide image into Fireworks, and I cut out the ink drawing so it was separate from the rest of the window.
     
  2. I pasted the cut out drawing onto the same location and shifted it left a bit.
     
  3. Next, I cut out a portion of the right-half of the window and pasted it in the same spot again.
     
    What I’ve done in this and the previous step is to take the existing elements from my original screenshot and put them in separate layers.

Here is what my Fireworks representation of that image looked like:

individualLayers

Notice that the right-portion of the image and the ink drawing are in separate layers to allow me to compact the width without having to rescale. The next step was easy. I just shifted everything left to simulate the window being smaller.

My brilliant plan worked late at night a week ago when I did this originally, for I didn’t notice the weird titlebar discoloration. I thought I shifted it just enough to not interfere with the gradient too much. When I was doing a final scan of the text a few hours earlier (in the afternoon when I’m more alert), I noticed this discoloration immediately. It bothered me, but I am not quite sure if I was bothered because I "cut a corner" or because I noticed this issue in the first place.

In either case, I have some issues that I need to deal with :P

Cheers!
Kirupa :)

Random Observation: Browse by Object in Word 2007

January 23rd, 2008     |     View Comments

In one of my earlier posts, I mentioned that every now and then I notice mundane details in applications I use frequently. My most used application these days is Word, so it only made sense that it would be the featured application in today’s post. Since many of you use Word all the time also, how many of you know where the following menu comes from:

menu2 

Give up? Let’s zoom out a bit to put the above menu in context:

largerView

Nestled between your vertical scrollbar and the zoom slider in the bottom-right corner of your window, you can find the circular button that calls this mystery (at least to me) menu. This menu allows you to browse your document via objects found such as images, tables, bulleted lists, etc. In other words, if you want to go from image to image in your document, call this menu, select the Image icon, and use the previous/next selection arrows to jump between images:

updownarrow

I have been using Word for at least a few hours every day for the past few years, and noticing a feature in the main window itself like this is like living in a home for a while and mysteriously finding a door that leads to a whole new room you never knew existed.

Anyway, I just finished up the Data Binding to XML tutorial, so I figured I would take a break by writing something from my Random stash of article ideas such as this one. Until next time, I’m going to go look around my house to see if there is a door leading to a room that I never knew existed…

Cheers!
Kirupa :)

A short while ago, I decided to buy a new Zune MP3 player. I was quite happy with my first-generation Zune and the free software upgrade it received, but the idea of choosing custom pre-selected artwork on my device was too tempting to pass up. Long story short, I gave in and purchased the 8GB player from zuneoriginals.net (click on pictures for larger image):

z1

z2

z3

One of the features provided via the new Zune software is the ability to create an online account from where you can keep track of the music you have listened to, share your musical tastes with others, etc. For example, the following is the page created for me after I signed up: http://social.zune.net/member/kirupa 

Besides seeing all of the awesome music I listen to, my social page has an interactive widget that allows anyone to browse through my recently played or favorite music:

zunecard

Anyway, what interested me more about all of this was having easy access to my musical data via a web service: http://social.zune.net/zcard/usercardservice.ashx?zunetag=kirupa (where you can replace kirupa with your account name to see your info). This opens up a lot of interesting things you can do, for the data returned is basically just XML.

That is where LINQ comes in. In previous posts, I described using LINQ to access data stored in a collection. With XML, you do not have data stored sequentially in an array-like structure. Your data is hierarchically organized with nodes and sub-nodes (and attributes!) representing the various information collected about your music playing habits. Our regular LINQ queries will only help to a certain point, but we need something more specialized. Fortunately, to make accessing nested XML data more direct, you have XLINQ, short for Language INtegrated Query for XML.

Describing all of XLINQ in this post will not do it justice, so I will cover this in greater detail as an article on kirupa.com at a future date. Instead, for now, let me first show you how to display all of the songs you’ve either marked as a favorite or played via the Zune media player recently:

XElement musicData = XElement.Load(@"http://social.zune.net/zcard/usercardservice.ashx?zunetag=kirupa");
 
var music = from m in musicData.Descendants()
            where m.Name.LocalName == "track"
            select m;
 
foreach (XElement m in music)
{
string song = m.Element("label").Value;

XElement album = m.Element("album");
 
string albumName = album.Element("label").Value;
string artist = album.Element("artist").Element("label").Value;
 
Console.WriteLine(song + " by " + artist + " from " + albumName);
Console.WriteLine("——————");
}

The first part where you see my music variable should look familiar to other LINQ statements you’ve seen before. The difference is that I am digging through a collection of XElement types where each XElement represents an element in your XML document. In this case, I am getting a list of all elements whose name happens to be "track".

The track element, or node in this case, is still pretty generic. You have several ways of drilling into your track node. You could continue checking its descendants and querying further, but for diversity, let’s access the nodes directly using the various methods XElement allows you to use:

string song = m.Element("label").Value;

XElement album = m.Element("album");
 
string albumName = album.Element("label").Value;
string artist = album.Element("artist").Element("label").Value;
 
Console.WriteLine(song + " by " + artist + " from " + albumName);
Console.WriteLine("——————");

Our track node contains a label node representing the song, and we can access that directly by passing in the node name label! The rest of our data, though, is nested inside an album node. To make our code more readable, I decided to create a new XElement storing just our album data.

With your album data stored, you can access the various nested information by traversing down your tree just like you did earlier when accessing your your song title. Album name is straightforward to get, but the artist information isn’t. The artist information is nested inside the label node of your artist node. I could create a new XElement for just our artist, but instead, I am just going to directly access the nested data:

string artist = album.Element("artist").Element("label").Value;

Notice that I am digging deeper by simply tagging more .Element(name) arguments to traverse down the right branch.

When you run the above code, the following information is displayed:

cmdOutput 

If you took a look at the original XML data, you’ll see that the few lines we wrote to filter through the hundreds of data points was well worth it! Anyway, I hope this article helped give you a brief overview of XLINQ and the Zune Social data.

Cheers!
Kirupa :)

AS 3.0 Components and Web Services in Flash CS3

December 4th, 2007     |     View Comments

If you use components a lot, one thing you might notice about Flash CS3 is the number of components available when you create an ActionScript 3.0 based project. For comparison, the following screenshot shows you the number of components you have access to by default in AS 2.0 and AS 3.0 projects:

as2vsas3 

Having fewer components is fine. There is certainly a cost associated with creating and testing components – especially brand new ones using AS 3.0. The frequency each component was being used might also have played a role in determining which got cut. Unfortunately, that does not help the many of you who want to create AS 3.0 projects and actually used the components that got axed such as Menu or Tree.

I am generally not a huge fan of components because of their ability to inflate your file size and limit (easy) customizability. To workaround those issues and for simulating missing components, with some ingenuity, you can re-create a lot of the functionality found in many of these visual components yourself. You have full control over how your component looks, and the file size is often significantly less. Sure, in most cases, your code will not be as clean or as well-separated and layered across many classes like a built-in component coming from Adobe or a great component vendor, but you and your visitors can live with the results.

Web Services are a Different Ballgame
The tough part is living without those components you cannot create yourself. One of my most frequent Flash CS3 related e-mail question revolves around the use of web services in an AS 3.0 project. This is one of those components that did not make it across the bridge into the AS 3.0 world created by Flash CS3. Creating your own web services functionality is difficult for the average designer and developer, and getting it to work across many scenarios is even more difficult.

If you rarely use components in the drag-drop-modify scenario and prefer working with the actual classes instead, you are out of luck also. There aren’t any built-in AS 3.0 classes in Flash CS3 that allow you to connect to a web service and communicate data. My earlier post relating to programmatically connecting to a web service only works on AS 2.0 projects. While Flex does support (and includes) web services components and classes, I don’t know if it is possible to use those classes in an AS 3.0 project created in Flash CS3.

Help is on the Way….In the Meantime!
The lack of web service components in Flash CS3 for AS 3.0 projects is something that Adobe is aware of, and according to a post by John Dowdell in July 2007, was going to be addressed soon with a document that was in the final stages of review.

Until that document appears, I have heard good things about wellconsidered’s Flash CS3 Web Service Class for AS3 projects. What’s even nicer is that the author is more than gracious enough to accept feedback on any issues you encounter in your real-world use of this component.

Cheers!
Kirupa :)

A good part of my time is spent writing things such as e-mails, documents, presentations, engineering specifications, etc. using Word or some other Office application. In almost all of the documents I write, I incorporate images from Fireworks (or similar image editor) to help me better get the message across.

The Problem: Blurry Images
The problem was, my inserted images would often look blurry. For example, this is the source image as I saved it on my computer:

Inserting the same image into Word (or any other Office application) would cause the image to look blurry because they would be resized:

imageInsertedIntoWord

I could partially mitigate this problem by scaling down my image’s dimensions within Word itself, but that still doesn’t result in the image looking exactly like the source. For example, when inserting screenshots such as what you see above, even minor alterations from the original size will cause your image to look different. This problem is even more noticeable if what you are displaying is something everyone is familiar with – like the corners of a desktop window!

The Solution: Synchronizing the PPIs
Until I read this post by a colleague of mine, I simply never considered conflicting DPI settings as the reason why my images were getting blurry when I exported them from Fireworks into Word. I just thought it had to do with some automatic resizing because of the extra space available in my document. In hindsight, my justification really doesn’t make much sense :P

For a better explanation of what happens, I’ll just quote what Joanna wrote in the post I linked to earlier:

If you work with assets that were saved specifying a resolution other than 96 PPI, Design and Blend will scale the asset to be the same physical size at 96 PPI. For example, an image that is 72 PPI and has a width of 6.667 inches and height of 8.889 inches has a width in pixels of 480 and height of 640. If I wanted to display that same image at a resolution of 96 PPI, it would need to have a width and height in pixels of 640 and 853 respectively. Therefore, if you import a 480 X 640 image into Design or Blend that was originally created at 72 PPI, its actual size after import will be 640 X 853.

In the above paragraph, replace Illustrator with Fireworks and Blend/Design with Word, and you have the problem that I was running into. Fireworks exports at 72 PPI while Word and other Office applications work at 96 PPI. To fix this problem, when you are creating a new image in Fireworks, in the New Document window, change the Resolution from 72 Pixels/Inch to 96 Pixels/Inch as shown in the below image:

NewDocument96PPI

Now, any images you insert into an application that listen for 96 PPI will look just the way you intended for it to look when you created it originally. No more blurry images!

Cheers!
Kirupa :)

Recently, I’ve been spending a lot of my free time fiddling with Silverlight. When you start to use something for extended periods of time, you begin to notice mundane details. One such detail I noticed was that there are two types/sizes of "Get Silverlight" badges that get displayed if a user does not have the Silverlight plug-in installed when he/she visits a page containing Silverlight content:

Small Get Silverlight badge:

getSL1

When you click on the above badge, you are taken directly to Microsoft’s download site where you can get more information and download the plug-in.

Expanded Get Silverlight badge:

getSL2

With the expanded badge, when you click on the Get Microsoft Silverlight area, instead of being taken to Microsoft’s site, you directly get linked to the plug-in installer. There is no seeing a license agreement or anything, and your users stay on your site.

Choosing the Badge
Now that you have a brief overview of the two types of badges and the differences between them, let’s figure out how to choose one or the other. When a Silverlight project gets published, you have an HTML page and several JavaScript files that help getting your content displayed. One of those JavaScript files, usually Default_html.js, contains a function called createSilverlight():

function createSilverlight()
{
var scene = new UntitledProject5.Page();
Silverlight.createObjectEx({
source: "Page.xaml",
parentElement: document.getElementById("SilverlightControlHost"),
id: "SilverlightControl",
properties: {
width: "100%",
height: "100%",
version: "1.0",
},
events: {
onLoad: Silverlight.createDelegate(scene, scene.handleLoad)
}
});
}

In this function, we will make some modifications to specify which Get Silverlight badge gets displayed. Inside createObjectEx, find the properties section, and after the version information, add the following line:

inplaceInstallPrompt: true

Your createSilverlight function will look like the following:

function createsilverlight()
{
var scene = new untitledproject5.page();
silverlight.createobjectex({
source: "page.xaml",
parentelement: document.getelementbyid("silverlightcontrolhost"),
id: "silverlightcontrol",
properties: {
width: "100%",
height: "100%",
version: "1.0",
inplaceinstallprompt: true
},
events: {
onload: silverlight.createdelegate(scene, scene.handleload)
}
});
}

The inplaceinstallprompt property is what controls the type of badge that gets displayed. By choosing to install in-place, like you did in the above code by setting inplaceinstallprompt to true, you display the larger badge that allows your users to download the plug-in directly without having to leave your site to go to Microsoft’s download site.

If you set inplaceinstallprompt to false, you will see the smaller badge that takes your visitors away from your site and onto Microsoft’s site where a download can be initiated. This is actually the default behavior. If you do not specify anything for inplaceinstallprompt, the smaller badge with no in-place plug-in access gets displayed.

Cheers!
Kirupa :)

One of the oft-emphasized features of Windows Presentation Foundation (WPF) is its hardware acceleration and vector-based drawing. While both of those features are really cool and useful, there are several other under-the-hood changes that make it interesting. In this post, I will describe and elaborate on some of the well known as well as less harped about under-the-hood features in WPF that I find fascinating.

Fine, We’ll Start with Vectors!
One of the big advantages of using vectors for drawing is resolution independence. In a nutshell, resolution independence allows your applications to scale well under various display circumstances. Imagine having an application that looks nice on your cell phone as well as your 1080p display.

To highlight that, let’s look at the following image:

On the surface, with the exception of some minor variations in position and size, both of the applications look the same. The main difference, though, is that one of them is a WPF application, and the other is a WinForms application. Based on the above screenshot, knowing that one is a WPF app and the other a WinForms app is irrelevant. The divergence occurs when you literally look closely at them.

Using the Windows Magnifier, the differences between the applications becomes apparent. When magnifying the buttons in our WinForms application, notice that the text and the button’s shape become blocky and pixelated:

To contrast that, let’s put our WPF app under the same test:

The difference is huge! The text and button shape in our WPF application look smooth, and the pixelation you saw with WinForms is no longer there. That is because in a vector-based system, all drawing and scaling is done using line as opposed to shifting and skewing individual pixels. That alone doesn’t explain everything. WPF also employs anti-aliasing to smooth out any rough spots, and text is made more legible (especially at small sizes) using ClearType sub-pixel antialiasing.

Retained-Mode Drawing
To look at the drawing features in WPF in greater detail, there are some neat tricks beyond just having a vector-based drawing engine. WPF uses a retained-mode rendering or composition system. Retained-mode means that somewhere in memory, you keep track of all of the objects that have been drawn, how they look, their relationships with other objects, etc. 

By having a centralized cache where object properties are stored, you are able to make redraws and modifications as needed very quickly without having to dig deeper into your object’s internals. The time you save from having to make these roundabout calls allows your application to have high-refresh rates which allows you, among other things, to have smooth animation!

The code underlying your object will have no idea about what is going on above the surface with the visuals, but that is fine. This partly means that you can transform a fully-functioning button that looks something like the following image,…..and still have the button be fully functioning:

Priority Filling (Painter’s Algorithm)
The final cool WPF thing I want to talk about is priority filling, or what is also known as painter’s algorithm. One of the big difficulties in earlier graphics frameworks was to have objects nested on top of each other. Why you couldn’t do something like that was partly because each object was drawn within, what can best only be described as, a box:

Both from a technical as well as a computational point of view, there weren’t many effective ways of not having these boxes (also known as clipping regions) around your objects.

With WPF, you solve this problem by drawing the farthest away object first and then slowly propagating outward until the nearest object is drawn. In the process of drawing from far to near, you calculate the overlap regions and draw over them with what needs to be displayed. Each object is aware of what lay behind it so that it can draw itself accordingly:

I quickly breezed over the part where I said “you calculate the overlap regions…” Calculating the overlap regions is a time consuming process, and you also have wasted cycles from where you drew something in the background only to have it be overlapped by something that was drawn later. Fortunately, that is where your graphics accelerator plays a major role. WPF uses your graphics hardware extensively, and your graphics cards are optimized for this type of drawing because much more complicated versions of this technique are employed by 3D games. What works for 3d games must surely usually work for your standard applications.

Going Further
If you are interested in these kinds of things, one of the best resources I can recommend is taking a look at the lecture notes for 6.831: User Interface Design and Implementation. It is probably one of the best/useful classes I’ve taken at MIT, and it’s also the class where I and two friends developed Abkiya.

Cheers!
Kirupa :)

After a few months of vacationing in India, I’m back home. Gotta love airplane delays and jetlag. In the meantime, here are some interesting links I found across the net:

  • Web Service Components in Flash CS3
    Adobe blogger John Dowdell provides a reason why Flash CS3 contains no out-of-the-box support for web services. What I would like to see beyond components are access to the classes that take care of handling web services. I’m not a big fan of components (see my interview), and I’d rather have the class files now when Flash CS3 was first released instead of still waiting on documentation.
     
  • Make Up Your Mind Jim Cramer
    One of my favorite TV shows is Jim Cramer’s Mad Money. While entertaining and often insightful, Jim has a tendency to change recommendations on the same stock frequently. For investors who rely on his insight, that isn’t helpful. It’s good to see that I wasn’t the only one who felt he was being inconsistent in the short-term on his stock picks.
     
  • Microsoft Posts Two major Vista fix Packs for Download
    These fixes seem to fix some long-standing issues many Vista users have had with performance and reliability. I installed them, and everything seems to be working fine. Though, I can’t say I was actually experiencing the problems the fixes claim to resolve.

    EDIT (Revised): According to Chakkaradeep in the comments, be sure to install (along with these) the other updates that were released on Automatic Updates on August 14th.
     

  • Performance Profiling Tools for WPF
    If you are looking to optimize your WPF applications, these tools are quite helpful. They analyze your application during run-time and provide valuable feedback on details such as how much memory and how long parts of your application take.
     
  • HDMI Versions
    It turns out that simply having HDMI ports doesn’t make you cool. Having HDMI ports simply gets you into the club, and it is having HDMI version 1.3 ports that makes you cool.
     
  • Freetards in Deep Denial
    Fake Steve Jobs aka Dan Lyons of Forbes, writes a provocatively titled but interesting post describing the uphill struggle for Linux adoption in developing countries. I know from visiting family across India, all of the computers I saw ran Windows. While that is just anecdotal evidence, to me it adds some real-world validity to Dan’s claims.
     
  • Microsoft’s New Image Editor
    While this wasn’t featured at MIX, I think this is the Photoshop-killer Adobe should be on the lookout for.
     
  • How Now to Write a Technical Book
    Jeff Atwood reviews my two favorite WPF books and talks quite favorably about Adam Nathan’s book while talking less favorably about Charles Petzold’s book.
     
  • The Future of Writing
    Charles Petzold responds to Jeff’s criticism of his book.
     
  • Musings About How Not Write a Technical Book
    Scott Mitchell’s take on the debate between Jeff and Charles’s posts.
     

That’s all for now. I still have a few more weeks before I move to Seattle, so hopefully I’ll have some time to wrap up some long-standing articles covering AS3 Classes, Creating Another Simple WPF Application, and more.

Cheers!
Kirupa :-)

A few months ago, I was requested by Mark Angeletti from search-this to answer five questions about Flash both from a technical as well as a non-technical/business point of view. You can read my answers as well as those by well known developers Bartek Drozdz (Fantasy Interactive) and Keith Peters (bit-101) in the following location: http://www.search-this.com/2007/08/08/3-flash-masters-answer-5-flash-questions/ (my answers are the ones flagged in red)

For easy access to just my answers, I have pasted them below:

  1. What do you see as Flash’s key asset(s)?
    The main asset of Flash is how easy it is to go from launching the IDE, creating the content, and publishing the content to the web for others to access. As long as the user has the Flash plug-in installed, the content displays consistently with little variation across browsers, platforms, etc. If the user does not have the Flash plug-in, downloading and installing it is very straightforward.
     
    It is this, usually hassle-free, experience that makes Flash unique when compared to a host of other development platforms. This focus on simplicity on the deployment side help it to gain a lot of trust both with regular users and designers/developers who want an easy way to create and distribute interactive content.
     
  2. What do you think is Flash’s biggest weakness?
    Macromedia (and now Adobe) spent and continue to spend a great deal of effort trying to make the lives of designers easier. With each subsequent release, the integration between Flash and other applications such as Fireworks, Photoshop, etc. sees marked improvements. Beyond integration with other designer applications, features centering round drawing become much better also.
     
    Despite the improvements made for designers, I feel that Flash could offer a lot more for developers. The introduction of ActionScript 3 is great, but the tools for writing and debugging the code are very rudimentary. Even with Flash CS3, the code editor provides very limited functionality for developers who are accustomed to features found in other popular IDEs.
     
  3. If you could change one thing about Flash what would it be?
    The one thing I would change is how the components are loaded in Flash. Right now, using components greatly increases the file size of an animation. A blank Flash SWF file is around 40 bytes, and adding, for example, a simple Button component inflates the file size to 15kb. Creating your own simple button from scratch with Up, Over, and Down states takes up less than 300 bytes. The Button component isn’t alone, for you experience similar file size increases when using the other components also.
     
    Part of the reason is that large parts of these components are defined and stored within the SWF itself. My solution to this problem would be to store the component parts in the Flash Player instead with the SWF, storing only the component parts the user modifies. With this change, adding components will no longer increase the SWF file size as rapidly as it does now.
     
    While the SWF size will decrease, this solution will increase the Flash Player’s file size. In the end, I think the benefit of having smaller SWF files sizes when using components offsets the gain in file size found in the one-time download of the Flash Player.
     
  4. Has Flash’s popularity peaked?
    No, I do not think the popularity of Flash for end-users has peaked. A few years ago, nobody outside of a few individuals would have guessed how extensively Flash would be used to deliver videos on the web. As you are reading this right now, I am sure somebody out there is working on something else (maybe using Flex or Apollo) that will push Flash in a new direction.
     
    To take a broader view by looking at developers, unlike in the past, the RIA space has gotten more interesting with technologies ranging from Silverlight, JavaFX, OpenLaslo, JavaScript, etc. competing for user and developer attention. Developers now have a choice in picking the right tool for the right job, and the tool chosen may or may not be based on Flash.
     
    I believe this increased competition gets a lot of developers familiar with non-ActionScript languages to target the web. This is not a zero-sum game, so while the percentage of RIA projects using Flash might decrease, the quantity of developers who target Flash will continue to increase at the same rate as it has since Flash was first introduced. To look at it another way, Flashers in the future will have a smaller piece of a much, Much, MUCH larger RIA-flavored pie.
     
  5. What will Flash look like in 3 years?
    In three years, I think Flash will feature hardware graphics acceleration. Right now, even the lowest-end computers feature graphics cards capable of breezing through fairly complex visuals, but Flash’s lack of hardware acceleration leaves such functionality beyond the reach of developers.
     
    Ideally, Flash will combine some of the best elements of the Shockwave Player. The Shockwave Player features hardware acceleration by default with support for DirectX and OpenGL, and the Xtras extensibility model allowed developers to provide more functionality to users on an as-needed basis.

Thanks to Mark Angeletti for giving me the chance to talk more candidly about Flash. There is some extra discussion of this on a kForum thread covering the interview.

Cheers!
Kirupa :)

In my most recent tutorial, I explain how to allow your applications to open single or multiple files using the Open File dialog window. In the last page of this tutorial, I discuss a problem associated with using the OpenFileDialog found in WPF’s (PresentationFramework.dll) Microsoft.Win32 namespace.

In a nutshell, the problem is that, in Windows Vista, calling the Win32 version of OpenFileDialog displays the dialog window in the wrong style:

oldopenfiledialog

The correct style should be the version shown in the image below:

vistaOpenFileDialog

As you can tell, there is a drastic aesthetic and functional difference between both of the dialog boxes. In the tutorial, I gave only a brief overview of the problem and described how to use the WinForms version of OpenFileDialog to solve the problem. In this post, let’s look in detail why the Win32 version displays the wrong dialog window, and more importantly, why WinForms displays the correct version.

Using .NET Reflector
One of the best tools for digging through an application’s dependencies and implementation is Lutz Roeder’s .NET Reflector. Using .NET Reflector, you can select any assembly / EXE, DLL, etc. and look through the guts of the application without even having access to the original source code*:

reflectorExample

For seeing why the wrong version of OpenFileDialog is displayed in Vista, I created two versions of my application. One version used the Microsoft.Win32.OpenFileDialog class, and my second version used the System.Windows.Forms.OpenFileDialog class. Let’s look at the Win32 version first.

The Win32 OpenFileDialog is based on FileDialog which, in turn, is based on CommonDialog:

reflected_OpenFileDialog

When I call my Win32 OpenFileDialog’s ShowDialog method in my C# code, internally, I am being routed from our ShowDialog method in the CommonDialog class to a RunDialog method in the FileDialog class. Let’s look at the code in our RunDialog method, and you are not expected to understand much/any of it:

[SecurityCritical]
protected override bool RunDialog(IntPtr hwndOwner)
{
bool flag;
NativeMethods.WndProc proc = new NativeMethods.WndProc(this.HookProc);
NativeMethods.OPENFILENAME_I ofn = new NativeMethods.OPENFILENAME_I();
try
{
this._charBuffer = NativeMethods.CharBuffer.CreateBuffer(0×2000);
if (this._fileNames != null)
{
this._charBuffer.PutString(this._fileNames[0]);
}
ofn.lStructSize = Marshal.SizeOf(typeof(NativeMethods.OPENFILENAME_I));
ofn.hwndOwner = hwndOwner;
ofn.hInstance = IntPtr.Zero;
ofn.lpstrFilter = MakeFilterString(this._filter, this.DereferenceLinks);
ofn.nFilterIndex = this._filterIndex;
ofn.lpstrFile = this._charBuffer.AllocCoTaskMem();
ofn.nMaxFile = this._charBuffer.Length;
ofn.lpstrInitialDir = this._initialDirectory.Value;
ofn.lpstrTitle = this._title.Value;
ofn.Flags = this.Options | 0×880020;
ofn.lpfnHook = proc;
ofn.FlagsEx = 0×1000000;
if ((this._defaultExtension != null) && this.AddExtension)
{
ofn.lpstrDefExt = this._defaultExtension;
}
flag = this.RunFileDialog(ofn);
}
finally
{
this._charBuffer = null;
if (ofn.lpstrFile != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(ofn.lpstrFile);
}
}
return flag;
}

If you look over the code, you’ll get a basic idea of what it does even if you are not certain of the implementation details associated with this method. Let’s compare and contrast the above code with what you will see in the WinForms version of RunDialog. After you see what the WinForms implementation looks like, you’ll have an idea of what to look for, and more importantly, what isn’t found in the above code.

In the WinForms implementation, let’s jump directly to the RunDialog method. The code for RunDialog in System.Windows.Forms is:

protected override bool RunDialog(IntPtr hWndOwner)
{
if (Control.CheckForIllegalCrossThreadCalls && (Application.OleRequired() != ApartmentState.STA))
{
throw new ThreadStateException(SR.GetString(“DebuggingExceptionOnly”, new object[] { SR.GetString(“ThreadMustBeSTA”) }));
}
this.EnsureFileDialogPermission();
if (this.UseVistaDialogInternal)
{
return this.RunDialogVista(hWndOwner);
}
return this.RunDialogOld(hWndOwner);
}

Notice that you branch your code to use either RunDialogVista if you are on Vista or RunDialogOld if you are running something pre-Vista such as XP. The implementations of RunDialogVista and RunDialogOld take care of displaying the appropriate dialog windows and the style associated with it.

Because Win32 doesn’t seem to check for the OS version when attempting to display the dialog window, you run into the UI incompatibility that I described both in this post and in my tutorial. According to Daniel Moth, the chances of the final version of WPF 3.5 fixing this issue seem high.

EDIT: According to Daniel’s comment to this post, the final version of WPF 3.5 will not include this fix.

* You can always obfuscate your code to confuse .NET Reflector, but like all disassembly tools found for many languages, truly hiding the implementation of your application isn’t a perfect science.

Cheers!
Kirupa ;)