Windows 7 Previews – the Delphi Way

In the ancient days of Windows XP and Delphi 7 I used to provide a preview of the proprietary file content inside the file open dialog of one of my applications. This was accomplished by deriving from TOpenDialog, just like the TOpenPictureDialog does that comes with Delphi itself.

The drawback was that since Windows Vista this was no way to go when you wanted to use the new Vista style dialogs. This was an even more nuisance as the new dialogs already come with a preview ability – so why not use it directly?

Googling a bit reveiled that others have to fight with the same problem, but no one seemed to have bitten the bullet to make a nice Delphi wrapper around the usual hurdles encountered when programming directly against the operating system. Looks like it was my turn to volunteer and here are the results. A simple implementation of a preview handler the Delphi way can be written in 45 lines:

This is all that must be done to display the description of a BPL file in the preview pane, whereas most of the work is actually setting up a TLabel do display it nicely.

Overriding DoPreview is obiligatory as the inherited declaration is abstract. If you refuse to override it, you actually don’t want to write your own preview handler, so stop reading further and mind your own business.

The overridden constructor Create is the place to establish the needed controls for the preview and connect it to the passed parent. You can easily place a derived TFrame instance onto the parent control, which allows the use of the visual form designer for your preview. Be aware that the constructor has to be declared as override.

Overriding the Unload method is optional in case you have to clear the preview and/or free some resources. It just didn’t make sense in this example, unless you want to clear the label caption. (and it would have increased the line count to 51)

Don’t forget to register your preview handler in the initialization part of the unit using a fresh GUID. (Pre-emptive comment: No, class constructors are not the way to go here)

Of course the compiled DLL has to be registered with regsvr32. Make sure to run it as Administrator.

OK, I admit that the overall benefit of this preview handler is somewhat limited, but it does serve well as an example. I also admit that I suppressed the project file, which in turn is quite simple.

I tried to get rid of the {PreviewHandler: CoClass} entry in the uses clause, but the IDE insisted to put it in again. So, be it…

The real work (as usual) is done under the hood in unit PreviewHandler.pas, which I will explain shortly in the following.

The interface section declares a base class TPreviewHandler and two derived classes TStreamPreviewHandler and TFilePreviewHandler.

Microsoft recommends to implement the stream based preview handler as it will also work for previews, say, inside a zip file, but there are cases when a file based preview handler is just a bit more handy. You would have difficulties to implement the sample preview handler from above on a stream with the same simplicity. There is indeed a third possibility to implement a preview handler based on an IShellItem, but let’s say I left the implementation as an exercise.

You may have noticed that TPreviewHandler is derived from TObject instead of TComObject, which actually was my first approach. I decided to separate the COM stuff from the preview implementation to get a lean inheritance and small base classes not cluttered with methods you better shouldn’t know about. The actual COM class is retrieved from the virtual class function GetComClass, which is overriden in both of the derived preview handler classes. The declaration of the derived function as final ensures that no one can override this function in a descendant class. This is necessary because the underlying factory assumes that the COM class descends from a specific private class (I’m open for suggestions on that). If you are going to implement your own COM classes you should better implement your own complete preview handler framework at all. For anyone else, just ignore the GetComClass function.

The implementing COM classes resemble the file/stream structure of the preview handler classes, just because they have to implement either IInitializeWithFile or IInitializeWithStream. The base class TComPreviewHandler is responsible for most of the internal stuff and the implementation is mostly straight forward. The mapping to the Delphi type TWinControl properties is made with a class helper just to bundle all that stuff (and to make it harder to port it to older Delphi versions).

The TComPreviewHandlerFactory class is responsible for updating the various registry entries needed to make Windows aware of the preview handler. It also takes care of doing the right things to use a 32-bit handler in a 64-bit environment. The code to check for this situation is taken from www.delphidabbler.com and I expanded it a little bit so that it hopefully will also work with the upcoming 64-bit Delphi compiler.

As a gimmick you get a TStream implementation that maps to an IStream interface with the TIStreamAdapter class. The other way round is already available in Delphi, but it didn’t fit in here very well.

The sources for Delphi XE can be downloaded here: Preview Handler

Author: Uwe Raabe

Addicted to Pascal/Delphi since the late 70's