Changing Windows Aero Color






4.80/5 (5 votes)
Ever wanted to change the Windows Aero color without restarting the DWM?
Introduction
From Windows Vista and above [till now], 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 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 the functions inside this DLL and I found 3 functions which can change the Aero colors.
Background
There are several API which are not documented in the Windows API lists. These undocumented APIs are private for Windows OS. To obtain these APIs, we can use Microsoft public symbol server. When dumped the dwmapi.dll, we can find three functions.
DwmIsCompositionEnabled() // Documented API,check if DWM composition is enabled or not
DwmGetColorizationParameters() // At index 127, undocumented API
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, it's necessary that we check it. 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 back at anytime without notification.
Using the Code
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".
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.
// 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 upto 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. Do find out the PARAMS
, we can take a look at the registry key HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM.
The structure in C looks like below:
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.
DwmIsCompositionEnabled(&enabled);//Need to call DwmIsCompositionEnabled
// before calling the DwmSetColorizationParameters or it will fail.
if(!enabled) // If glass composition is not enabled then close up
{
MessageBox(hWnd,"Composition is not enabled\nUnable to work!","Error",MB_ICONERROR);
FreeLibrary(hDwmDLL);
EndDialog(hWnd,0);
}
if(!DwmGetColorizationParameters &&
!DwmSetColorizationParameters) // The undocumented functions are not there, sorry
{
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.
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 it back to the Aero on closing of the application.
dwmcolor.clrColor = Restore;
DwmSetColorizationParameters(&dwmcolor,0); // Restore color back
And then finally, we will free the loaded DLL.
FreeLibrary(hDwmDLL); // Free the loaded DWM Library
The complete source code, for this job, goes below:
#include <windows.h>
#include <stdlib.h>
#include <time.h>
#include "resource.h"
HMODULE hDwmDLL;
BOOL enabled = FALSE;
time_t t;
int R=0,G=0,B=0; // Colors
#define ID_TIMER 1 // Timer ID
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
// Needed Function from DWM Library
HRESULT (WINAPI *DwmIsCompositionEnabled)(BOOL *pfEnabled);
HRESULT (WINAPI *DwmSetColorizationParameters) (COLORIZATIONPARAMS *colorparam,UINT unknown);
HRESULT (WINAPI *DwmGetColorizationParameters) (COLORIZATIONPARAMS *colorparam);
BOOL CALLBACK DlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
hDwmDLL = LoadLibrary("dwmapi.dll"); // Loads the DWM DLL
if(!hDwmDLL)
{
MessageBox
(hWnd,"Unable to load DWM Library!","Error",MB_ICONERROR);
EndDialog(hWnd,0); // Close
}
else
{
// Everything is fine upto 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);
}
DwmIsCompositionEnabled(&enabled);//Need to call DwmIsCompositionEnabled
// before calling the DwmSetColorizationParameters or it will fail.
if(!enabled) // If glass composition is not enabled then close up
{
MessageBox(hWnd,"Composition is not
enabled\nUnable to work!","Error",MB_ICONERROR);
FreeLibrary(hDwmDLL);
EndDialog(hWnd,0);
}
if(!DwmGetColorizationParameters &&
!DwmSetColorizationParameters) // The undocumented functions are not there, sorry
{
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
srand((unsigned) time(&t)); // seed for random number
}
return TRUE;
case WM_TIMER:
{
R = (rand() % 256);
G = (rand() % 256);
B = (rand() % 256);
dwmcolor.clrColor = RGB(R,G,B);
DwmSetColorizationParameters(&dwmcolor,0);
}
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_BUTTON1: //Stop
KillTimer(hWnd,ID_TIMER);
dwmcolor.clrColor = Restore;
DwmSetColorizationParameters(&dwmcolor,0); // Restore color back
break;
case IDC_BUTTON2: //Start
SetTimer(hWnd,ID_TIMER,300,NULL);
break;
}
return TRUE;
case WM_CLOSE:
KillTimer(hWnd,ID_TIMER);
dwmcolor.clrColor = Restore;
DwmSetColorizationParameters(&dwmcolor,0); // Restore color back
FreeLibrary(hDwmDLL); // Free the loaded DWM Library
EndDialog(hWnd,0);
return TRUE;
}
return FALSE;
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,DLGPROC(DlgProc),0);
}
Points 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.
History
- Initial release: 1.0
NOTE: This will not work on Windows 10.