Retrieving Aero Glass base color for opaque surface rendering

From time to time, Long Zheng asks me to augment MetroTwit with some obscure low-level Windows feature. Given that’s where I like to dwell, it’s a good fit for me. My latest task was to implement smarts into the MetroTwit header pane that picked up the user’s current Aero Glass color. DwmGetColorizationColor immediately popped into mind and I was done an hour later. Of course, things weren’t working very well… According to MSDN, DwmGetColorizationColor returns a color “used for Desktop Window Manager glass composition” and a boolean that simply indicates whether or not transparency is involved. The notable keyword here is composition. In the simplest scenario, a user uses a non-transparent color. This value simply gets passed to your application and everything Just Works™. In the real world, however (where transparency is turned on), things get a little trickier. The transparency toggle dutifully instructs the Desktop Window Manager to do all kinds of glass-like math-heavy nerd stuff to the base color. In this scenario, the returned color value is less useful.

DWM Colorization SampleFigure – Example function output, with and without transparency enabled

So, it boils down to – DwmGetColorizationColor is completely unusable for applications attempting to apply the current color onto an opaque surface. To workaround this, you have two options:

  1. Retrieve the safe stored ColorizationColor value located at HKEY_CURRENT_USERSoftwareMicrosoftWindowsDWM
  2. Use undocumented (but stable) dwmapi.dll function to retrieve these values for you

Both solutions suck, really. Microsoft could, at any time, rename these registry values, move the entire branch somewhere else, and/or change the ordinal numbers for their private API in dwmapi.dll. But, because I like to reverse engineer things, I elected to implement option 2. (I’m curious to hear your thoughts on this.)

IDA Pro Disassembled OutputFigure – Disassembled chunk DwmpGetColorizationParameters function

In opening up dwmapi.dll, IDA easily applied the private function names derived from the debugging symbols downloaded from Microsoft public debugging symbol server. One of the exported (by number, not name) undocumented functions was a _DwmpGetColorizationParameters (which I will call DwmGetColorizationParameters henceforth). The function was pretty small, it simply requested for and moved some information – seven values to be exact – into a structured block of memory you provide. I was able to quickly figure out what each value was by creating a dummy structure in .NET and looking at the values with my eyeballs; the values matched what was stored in the registry (see solution #1 above).

Translating that into C#, I came up with the following:

struct DWMCOLORIZATIONPARAMS 
{ 
    public UInt32 ColorizationColor; 
    public UInt32 ColorizationAfterglow; 
    public UInt32 ColorizationColorBalance; 
    public UInt32 ColorizationAfterglowBalance; 
    public UInt32 ColorizationBlurBalance; 
    public UInt32 ColorizationGlassReflectionIntensity; 
    public UInt32 ColorizationOpaqueBlend; 
}

[DllImport("dwmapi.dll", EntryPoint="#127")] 
static extern
void DwmGetColorizationParameters(ref DWMCOLORIZATIONPARAMS dp);

I wouldn’t (and didn’t) use the DllImport above in multi-platform production code. For applications that run on Windows XP, you’ll fail to bind to dwmapi.dll (because it doesn’t exist) and cause the Earth to tilt. Instead, you should import and make use of GetProcAddress, LoadLibrary, and Marshal.GetDelegateForFunctionPointer. Or just read the registry instead.

Look for Aero Glass colorization support in MetroTwit soon.