The challenge : update the look&feel of an outdated Borland C++ Builder 4 application, while changing the minimum amount of code, and keeping the same old 1998 compiler… To make things even easier, the new look and feel must be enabled/disabled at runtime.
First, the application UI controls are straight out of the nineties. To modernize their look without replacing or rewriting them, Microsoft introduced in Windows XP “Application Visual Styles”. The MSDN doc about Visual Styles is not great, but this CodeProject article from Martin Mitáš gives a great overview.
Basically, you just have to drop a “manifest” xml file telling the OS that your application wants to use the comctl32.dll version 6, with themed controls, instead of the version 5 with “classic” controls.
If your application is named myapp.exe, the manifest file must be named myapp.exe.manifest, and contain the following :
<?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes”?>
<assembly xmlns=”urn:schemas-microsoft-com:asm.v1″ manifestVersion=”1.0″>
Don’t forget to update the manifest setings (assembly name, type, etc…).
To avoid shipping the manifest file with your executable, you can also embed it within your application by adding a resource script (*.rc file) to your application with the following line :
1 24 “myapp.exe.manifest”
The manifest file must have ID 1, and resource type 24 (or RT_MANIFEST if you’re not using a totaly outdated compiler) for it to be taken into account.
At this point, you’ll notice that you can enable Visual Styles for any application, even if you don’t have its source code
Next question is : now that Visual Styles are enabled, how to disable them at runtime ?
To disable visual styles at runtime, you have two options :
Both functions are available in the Windows SDK, in header Uxtheme.h, with libray UxTheme.lib. Unfortunately, with my 98 compiler, just including the required header caused compilation error, without mentioning linking to the Library. I ended up loading the dll and the function dynamically, at runtime :
typedef __declspec(dllimport) HRESULT (__declspec(dllimport) __stdcall *SetWindowThemeFuncPtr)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);
void DisableWindowsVisualStyles(HANDLE handle)
static HMODULE DLL = LoadLibrary(_T(“UxTheme.dll”));
static SetWindowThemeFuncPtr SetWindowTheme;
SetWindowTheme = (SetWindowThemeFuncPtr)GetProcAddress(DLL,”SetWindowTheme”);
HRESULT hres = SetWindowTheme( handle, L” “, L”” );
printf(“SetWindowTheme returned %d”, hres);
Code compiled and ran fine, but the look of the controls was unaffected by the call to SetWindowTheme. That was because :
- Visual styles are only disabled for the control you’re passing the handle of. If this control is a window, the Visual styles are not disabled for all of its children.
- Obviously, Visual Styles should be disabled once the control is created and has a handle. With C++ builder forms, that meant on the OnFormCreate event, or by extending the TForm.Create method.
Eventually, the easiest solution to disable Visual styles for the whole application, and not per control/window was to use SetThemAppProperties :
SetThemeAppProperties(STAP_ALLOW_NONCLIENT) or SetThemeAppProperties(0)