author
Tejashwi Kalp Taru
Engineer, Tinkerer, Blogger
Reading time about 9 minutes

Changing Windows Aero color with Win32 programming


cover

From Windows Vista and above, Windows introduced a new engine called Desktop Window Manager which enables the use of hardware acceleration to render the user interface. It is used to enable the new Windows Aero look and design which enables the glassy look, 3D view and switching. The Desktop Window Manager is a compositing window manager. This means that each program has a buffer that it writes data to, then it composites each buffer into the final image and look. Hence it needs a DirectX compatible graphic device and WDDM drivers.

When the DWM was introduced, Windows introduced a colorful transparent UI called Aero. There are many ways to change the Aero color, mostly upon changing the Windows Aero enabled theme, the Aero color changes. The other ways need the restart of the DWM process that it dwm.exe.

Hence, when I tried to know more about this Aero color-changing values, I found the DLL dwmapi.dll, which can be found in system32 folder of the Windows installation directory. This DLL holds and serves all the needed API calls related to DWM. I tried to look at the functions inside this DLL and I found 3 functions that can change the Aero colors.

Background

There are several API which is not documented in the Windows API lists. These undocumented APIs are private for Windows OS. To obtain these APIs, we can use the Microsoft public symbol server. When dumped the dwmapi.dll, we can find three functions

1
DwmIsCompositionEnabled() // Documented API,check if DWM composition is enabled or not
1
DwmGetColorizationParameters() // At index 127, undocumented API
1
DwmSetColorizationParameters() // At index 131, undocumented API

As I said, the first function is used to check whether DWM composition is enabled or not. If it’s not enabled, then all calls to other functions will fail. So before using other functions, we should check it. The next two functions are used to get and set the Aero color parameters respectively.

As the 2 functions are undocumented, Microsoft can modify or remove them at any time without notification.

Lets start coding, shall we?

As the 2 functions are undocumented, we cannot use the direct API call or header file dwmapi.h. So I decided to load the dwmapi.dll at the runtime using the LoadLibrary() function. According to the MSDN, LoadLibrary() can load the DLL and using the GetProcAddress() function, we can load the address of the desired function. The GetProcAddress() can load the address of the function by either using the function name or the index of the function. As we have the index of those 2 undocumented APIs, we can load them too using GetProcAddress().

So first, let’s load the dwmapi.dll

1
2
3
4
5
HMODULE hDwmDLL = LoadLibrary("dwmapi.dll"); // Loads the DWM DLL
if (!hDwmDLL) {
  MessageBox(hWnd, "Unable to load DWM Library!", "Error", MB_ICONERROR);
  EndDialog(hWnd,0); // Close
}

When we have loaded the DLL, now it’s time to load the needed functions.

1
2
3
4
5
6
7
8
9
10
11
// Needed Function from DWM Library
HRESULT (WINAPI *DwmIsCompositionEnabled)(BOOL *pfEnabled);
HRESULT (WINAPI *DwmSetColorizationParameters) (COLORIZATIONPARAMS *colorparam,UINT unknown);
HRESULT (WINAPI *DwmGetColorizationParameters) (COLORIZATIONPARAMS *colorparam);

// Everything is fine up to here, we can get function address
*(FARPROC *)&DwmIsCompositionEnabled = GetProcAddress(hDwmDLL,"DwmIsCompositionEnabled");

//Below two functions are undocumented thus load from there index
*(FARPROC *)&DwmGetColorizationParameters = GetProcAddress(hDwmDLL,(LPCSTR)127);
*(FARPROC *)&DwmSetColorizationParameters = GetProcAddress(hDwmDLL,(LPCSTR)131);

Now, we have to check the COLORIZATIONPARAMS used by the 2 undocumented APIs. To find out the parameters, we can take a look at the registry key HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM.

The structure in C looks like below:

1
2
3
4
5
6
7
8
9
10
11
12
13
typedef struct COLORIZATIONPARAMS
{
	COLORREF         clrColor;          //ColorizationColor
	COLORREF         clrAftGlow;	   //ColorizationAfterglow
	UINT             nIntensity;	   //ColorizationColorBalance -> 0-100
	UINT             clrAftGlowBal;    //ColorizationAfterglowBalance
	UINT		 clrBlurBal;       //ColorizationBlurBalance
	UINT		 clrGlassReflInt;  //ColorizationGlassReflectionIntensity
	BOOL             fOpaque;
}DWMColor;

DWMColor dwmcolor;
COLORREF Restore; // This will be used to restore back the colors to default

Now, when we know everything, it’s time to use the needed functions. Let’s take a look at the sample.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//Need to call DwmIsCompositionEnabled before calling the DwmSetColorizationParameters or it will fail.
DwmIsCompositionEnabled(&enabled);

// If glass composition is not enabled then close up
if(!enabled) {
  MessageBox(hWnd,"Composition is not enabled\nUnable to work!","Error",MB_ICONERROR);
  FreeLibrary(hDwmDLL);
  EndDialog(hWnd,0);
}

// The undocumented functions are not there, sorry
if(!DwmGetColorizationParameters && !DwmSetColorizationParameters) {
  MessageBox(hWnd,"Unable to find necessary functions in library","Error",MB_ICONERROR);
  FreeLibrary(hDwmDLL);
  EndDialog(hWnd,0);
} else {
  DwmGetColorizationParameters(&dwmcolor); // Get current values
  Restore = dwmcolor.clrColor; //Backup current color
}

To change the color at runtime, I have used the timer. We will generate the color automatically using random values and then set the color to the Aero.

1
2
3
4
5
6
7
8
9
case WM_TIMER:
{
  R = (rand() % 256);
  G = (rand() % 256);
  B = (rand() % 256);
  dwmcolor.clrColor = RGB(R,G,B);
  DwmSetColorizationParameters(&dwmcolor,0);
}
return TRUE;

Now, this will change the Windows Aero color without the need to restart the DWM. But, it’s good if we set back the default color when we close this application. So at the start of the application, we will save the default Aero color and restore to the Aero on the closing of the application.

1
2
dwmcolor.clrColor = Restore;
DwmSetColorizationParameters(&dwmcolor,0); // Restore color back

And then finally, we will free the loaded DLL.

1
FreeLibrary(hDwmDLL); // Free the loaded DWM Library

You can download the complete source code here

Point of interest

It is good to experiment with the internals of Windows. Suppose an application can change the Windows Aero color according to the current temperature or according to the average color of your wallpaper, sounds interesting?? This source code can be used to easily manipulate the Aero color and what’s good is that you don’t have to restart DWM.

comments powered by Disqus