Wednesday, March 18, 2009

Talking back to the FileDialog in OpenFileDialogEx

The .NET Framework is a many splendored thing but one eyesore in this otherwise resplendent masterpiece of engineering is the functionality (or lack thereof) of its Windows Forms wrappers around the FileOpenDialog common dialog.

To be fair they do cover the basics. It's useable as long as you don't want to take advantage of any of the templating/customization features available to the native world. When you do encounter a situation where you need to take advantage of those features, a lot of the groundwork has already been done in the form of a wonderful codeproject submission known as OpenFileDialogEx.

OpenFileDialogEx takes advantage of the fact that an owned window (not a child window, an owned window) is activated on top of the owning window. So it creates a hidden window that owns the OpenFileDialog then hooks into it's message loop via the .NET provided NativeWindow. As an aside, the existence of NativeWindow is yet another example of the genius of the framework; they knew they wouldn't be able to provide all of the windowing functionality available in Windows and so created a handy catch all class to make it easy to bridge the gap when needed.

Anyway, as awesome as OpenFileDialogEx is, one of its shortcomings is that it doesn't provide a way to interact with the main file listing (aka SysListView32). It'll tell you when a new file has been selected and when a new folder has been selected but updating the selection from your .net control/panel isn't supported.

One of the reasons I think this support wasn't added is the peculiar behavior of the common dialog. Whenever the user changes directories a new SysListView is created. Even more peculiar is that the newly created SysListView has a different control ID than the one published in the SDK docs! It changes from control ID 0x0460 to control id 1! This is doubly strange because, the first time the OpenFileDialog is shown one of the buttons gets control ID 1!

The approach I took to deal with this was to identify the newly created SysListView32 whenever the directory was changed (by enumerating child controls). Unfortunately I'm relying on the less-than-international-friendly approach of using its class to identify subsequently created list views.

No comments :

Post a Comment