views:

354

answers:

2

I have a program that still must target Windows XP (_WIN32_WINNT 0x501), as most of our customers still use XP. However, we have been shipping Vista for a while, and are now pushing Windows 7 upgrades. For the software to work correctly on the newer OSs, there are a couple operations that require UAC elevation. I have the elevation code working, but would like to have the UAC icon present on the buttons that launch the UAC process. Unfortunately, all of the options defined in Microsoft's UAC UI document require _WIN32_WINNT 0x600 or newer.

Is there any way to get the appropriate UAC icon (Vista and 7 use different ones) to show on the button while still being able to target XP (where no icon will be shown)? I'm using C++, but may be able to adapt a .NET solution.

+2  A: 

Use Button_SetElevationRequiredState and add something like:

#if ! defined(BCM_FIRST)
#define BCM_FIRST               0x1600
#define BCM_SETSHIELD  (BCM_FIRST + 0x000C)
#define Button_SetElevationRequiredState(hwnd, fRequired) \
 (LRESULT)SNDMSG((hwnd), BCM_SETSHIELD, 0, (LPARAM)fRequired)
#endif // #if ! defined(BCM_FIRST)

This will work on XP and Vista, and will compiled normally for all target systems.

VitalyVal
A: 

If you send the button a BCM_SETSHIELD message on XP, it will say to itself "fascinating" and do nothing of interest. It certainly won't display a shield. So you don't need to prevent yourself from sending the message. Still, it's a good thought to pay attention to your OS features before using them.

If "the UAC process" you're launching is a separate exe with a manifest, the XP machines will ignore the manifest and you won't need to write any version checking code where you launch it.

This is the best kind of cross-version code to write - it does nothing on older versions but you're not running around explicitly testing the version at runtime, nor building different exes for different versions. You won't always be able to achieve that.

Kate Gregory