In the past, a GUI-based operating system dictated all the elements of the user interface for programs running on it. In recent years, Linux began to allow users to customize the look-and-feel of both the main windows of applications and user interface controls, like buttons. The same idea (often indicated by the term skin) has appeared in numerous programs with such a positive impact that even Microsoft has begun to integrate it (first in programs and then in the entire operating system).
As I mentioned, on Linux (on XWindow, to be more precise) the user can generally choose the user interface style of the controls. This approach is fully supported by Qt and by the KDE system built on top of it. Qt offers a few basic styles, such as the Windows look-and-feel, the Motif style, and others. A user can also install new styles in the system and make them available to applications.
The styles I'm discussing here refer to the user interface of the controls, not of the forms and their borders. This is generally configurable on Linux systems but is technically a separate element of the user interface.
Because this technique is embedded in Qt, it is also available on the Windows version of the library; CLX makes it available to Delphi developers, so that an application can have a Motif look-and-feel on a Microsoft operating system. The CLX Application global object has a Style property you can use to set a custom style or a default one, indicated by the DefaultStyle subproperty. For example, you can select a Motif look-and-feel with this code:
Application.Style.DefaultStyle := dsMotif;
In the StylesDemo program, I've added, among various sample controls, a list box with the names of the default styles, as indicated in the TDefaultStyle enumeration, and this code for its OnDblClick event:
procedure TForm1.ListBox1DblClick(Sender: TObject); begin Application.Style.DefaultStyle := TDefaultStyle (ListBox1.ItemIndex); end;
The effect is that, by double-clicking the list box, you can change the current application style and immediately see its effect on screen, as demonstrated in Figure 6.7.
With the release of Windows XP, Microsoft has introduced a new, separate version of the common controls library. The old library is still available for compatibility reasons, so that a program running on XP can choose which of the two libraries it wants to use. The new common controls library's main difference is that is doesn't has a fixed rendering engine, but relies on the XP theme engine and delegates the user interface of the controls to the current theme.
In Delphi 7, the VCL fully supports themes, due to a lot of internal code and to the themes management library originally developed by Mike Lischke. Some of these new rendering features are used by the visual controls of the Action Manager architecture, independently of the operating system you are running on. However, full theme support is available only on an operating system that has this feature—at the moment, Windows XP.
Even on XP, Delphi applications use the traditional approach by default. To support XP themes, you must include a manifest file in the program. You can do so multiple ways:
Place a manifest file in the same folder as the application. This is an XML file indicating the identity and the dependencies of the program. The file has the same name as the executable program with an extra .manifest extension at the end (as in MyProgram.exe.manifest). You can see a sample of such a file in Listing 6.2.
Add the same information in a resource file compiled within the application. You have to write a resource file that includes a manifest file. In Delphi 7, the VCL has a WindowsXP.res compiled resource file, which is obtained by recompiling the WindowsXP.rc file available among the VCL source files. The resource file includes the sample.manifest file, again available among the VCL source files.
Use the XpManifest component, which Borland has added to Delphi 7 to further simplify this task. As you drop this do-nothing component in a program's form, Delphi will automatically include its XPMan unit, which imports the VCL resource file mentioned earlier.
When you remove the XpManifest component from an application, you also have to delete the XPMan unit from the uses statement manually—Delphi won't do it for you. If you fail to do so, even without the XpManifest component, the program will still bind in the manifest resource file. Using the unit is what really matters (which really makes me wonder why Borland chose to create the component instead of simply providing the unit or the related resource file; by the way the component isn't documented at all).
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity version="18.104.22.168" processorArchitecture="X86" name="Pages.exe" type="win32" /> <description>Mastering Delphi Demo</description> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="22.214.171.124" processorArchitecture="X86" publicKeyToken="6595b64144ccf1df" language="*" /> </dependentAssembly> </dependency> </assembly>
As a demo, I've added the manifest file from Listing 6.2 to the folder of the Pages example discussed at the beginning of this chapter. By running it on Windows XP with the standard XP theme, you'll obtain output similar to that shown in Figure 6.8. You can compare this to Figures 6.1 and 6.2, which display the same program under Windows 2000.