Monday, January 02, 2006

wxWidgets, VC++8.0 and XP theme look and feel

I an previous post I talked about setting wxUSE_NO_MANIFEST=0 to avoid linker errors when you compile your wxWidgets application with Visual Studio 8.0. Turns out this was only half the story.

Symptoms:
Your application looses Windows XP themes for all controls.

Solution:
Add these lines to your precompiled header file "stdwx.h" if you have one, or to one of your .cpp files, preferably the applications .cpp file. (Please unwrap these lines. Every line should start with the preprocessor symbol '#'):
#if _MSC_VER>=1400
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_IA64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
#endif

Background: With Windows XP, your application must include a 'manifest' in its binary. This manifest tells Windows XP what version of what DLL your application uses. Among other things this enables 'Side By Side' installation, where two applications load a DLL of the same name, but with different versions.
Beginning with Visual Studio 8.0, the CRT runtime library DLLs are no longer found in the $PATH environment variable. Instead the linker generates a manifest for each application created with VS 8 and writes the requested DLL version into the binary. You must define wxUSE_NO_MANIFEST=0 for the .rc file to tell the resource compiler to ignore the standard wx manifest file. Otherwise the linker will give an error, since it then would see two manifests, the wx manifest and the one it generates itself.
But the manifest file generated by the linker does not include the neccessary information for the common controls version 6.0, which is responsible for the Windows XP themes for controls such as buttons. So by default, the application will have the XP themed frame with the blue bar and the bright red 'X' button in the upper right corner, but will still have the old Win2K style buttons inside the frame.
The reference to the common controls version 6.0 was contained in the wx manifest, which is no longer used due to wxUSE_NO_MANIFEST.
The lines above tell the linker to add the common controls version 6.0 to the manifest and your application will get the XP theme look back for its controls.

1 comment:

Anonymous said...

Just wanted to add quick and simple automatic wxWidget ID numbers with

just add this define before your enum statement

#define RUNNING_ID wxID_HIGHEST + __LINE__

Then to define the numbers

enum
{
MAIN_FRAME_ID = RUNNING_ID,
NEXT_BUTTON1_ID = RUNNING_ID,

.......

RunningID with use the line number its on to generate the IDS