Retrieving Aero Glass base color for opaque surface rendering

1 Jul
2010
18 Comments

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_USER\Software\Microsoft\Windows\DWM
  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.

18 Comments

Matt Sharpe

Interesting stuff.


Jaryth

“and cause the Earth to tilt”

I had that happen once… was NOT cool! ;)

reverse engineering is fun, although you tend to go a bit further then I take things! :D


Leo Davidson

Given the choice of both unsupported methods, I think I’d go with the registry with a bit of validation/sanity-checking.

Neither is ideal but I figure calling an undocumented ordinal means you might crash in the future if the function or parameters change meaning (rather than disappear) while the worst that can happen with the registry is you don’t find the colour or you use a bogus colour.

Still interesting stuff, though.

It’s a shame the public DWM API is still so basic with so much hidden and undocumented (or barely documented). Hopefully now that it’s a mature API (i.e. the internals shouldn’t need to change too much) it will be opened up a bit more in future versions of Windows.


Singh

God, I love reading your blog posts. I’m not a dev, but it does give me a welcome insight into the world of devs.


Panda X

I’ve always wondered. What’s the Afterglow and Balance’s do?


Vincent

Thanks for this piece of information, I always wondered why my form background color, which was set to use the DWM window border color, went crazy “sometimes”.


lula

No glass on metrotwit? Why not?


Rafael Rivera

Glass is ugly.


Christo27

Agreed that glass is ugly. Got tired of it after 6 months, I’d say.

I wonder if this is the same way that Windows Live Mail finds the glass color?


Mark

Great stuff, amazing really. I’ve done a fair amount of development, but no dis-assembly or reverse engineering. It seems like black magic, can anyone recommend a class or books that would be good to get started?


ngyikp

A better solution than this is to /not/ use custom windows in the first place :)


GRiNSER

MS guidelines say that you shouldn’t change the window frame behaviour unless you create a real benefit.
http://msdn.microsoft.com/en-us/library/aa974173.aspx
Actually I prefer glass more than these custom window frames because most of them either don’t fully recreate the original Windows placement or behaviour and some render much slower/with artifacts.

Google Chrome, iTunes, MetroTwit, Zune, to name some I know, all have their different takes on the top right window controls. Some of them forget to arrange the controls differently between windowed and maximized mode for example (which the original glass frame does).
MetroTwit, iTunes, Zune Player sometimes also render really badly – you get to see the shadow of the windows first, the content area shows up later.

I think MS is here to blame on some of these bad behaviours and rendering issues. Besides I always hated these graphical glitches like flickering and such in Windows, not only at the custom window frames, but also with e.g. normal content resizing… I hope they will finally step up and deliver a more glitch-free Windows desktop experience like they will provide with Windows Phone 7 in the mobile space.


Vincent

Totally offtopic: UxStyle Core is now one year old! Yeah :D


Roman

Thanks for this alternative to using the registry!
It’s certainly less code to write, but will it also perform better? (I think perfomance is always an important point, no matter how little some method seems)

@GRiNSER:
I believe Google Chrome uses the native window frame but draws onto the non-client area.
Not sure though about using skins in chrome if that is still no custom framing.

But I agree that too many applications apply their own window borders :(


Lucktube

Agreed that glass is ugly.


Darren

Ok, this is awesome stuff. However, what about setting the color?


Ian Boyd

i asked this same question on Stackoverflow, trying to get an answer to the real question: “What is DwmGetColorizationColor returning?”. You can see the question at (http://stackoverflow.com/questions/3560890/vista-7-how-to-get-glass-color)

Also, i love your screenshot much better, so i stole it as a template for my question.


Rafael

I think my post here answered your SO question, not sure what else you need to get color information.


Comment on this post