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()
DwmGetColorizationParameters()
DwmSetColorizationParameters()
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"); if(!hDwmDLL)
{
MessageBox(hWnd,"Unable to load DWM Library!","Error",MB_ICONERROR);
EndDialog(hWnd,0); }
When we have loaded the DLL, now it's time to load the needed functions.
HRESULT (WINAPI *DwmIsCompositionEnabled)(BOOL *pfEnabled);
HRESULT (WINAPI *DwmSetColorizationParameters) (COLORIZATIONPARAMS *colorparam,UINT unknown);
HRESULT (WINAPI *DwmGetColorizationParameters) (COLORIZATIONPARAMS *colorparam);
*(FARPROC *)&DwmIsCompositionEnabled = GetProcAddress(hDwmDLL,"DwmIsCompositionEnabled");
*(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; COLORREF clrAftGlow; UINT nIntensity; UINT clrAftGlowBal; UINT clrBlurBal; UINT clrGlassReflInt; BOOL fOpaque;
}DWMColor;
DWMColor dwmcolor;
COLORREF Restore;
Now, when we know everything, it's time to use the needed functions. Let's take a look at the sample.
DwmIsCompositionEnabled(&enabled); if(!enabled) {
MessageBox(hWnd,"Composition is not enabled\nUnable to work!","Error",MB_ICONERROR);
FreeLibrary(hDwmDLL);
EndDialog(hWnd,0);
}
if(!DwmGetColorizationParameters &&
!DwmSetColorizationParameters) {
MessageBox(hWnd,"Unable to find necessary functions in library","Error",MB_ICONERROR);
FreeLibrary(hDwmDLL);
EndDialog(hWnd,0);
}
else
{
DwmGetColorizationParameters(&dwmcolor); Restore = dwmcolor.clrColor; }
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);
And then finally, we will free the loaded DLL.
FreeLibrary(hDwmDLL);
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; #define ID_TIMER 1 // Timer ID
ypedef struct COLORIZATIONPARAMS
{
COLORREF clrColor; COLORREF clrAftGlow; UINT nIntensity; UINT clrAftGlowBal; UINT clrBlurBal; UINT clrGlassReflInt; BOOL fOpaque;
}DWMColor;
DWMColor dwmcolor;
COLORREF Restore;
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"); if(!hDwmDLL)
{
MessageBox
(hWnd,"Unable to load DWM Library!","Error",MB_ICONERROR);
EndDialog(hWnd,0); }
else
{
*(FARPROC *)&DwmIsCompositionEnabled =
GetProcAddress(hDwmDLL,"DwmIsCompositionEnabled");
*(FARPROC *)&DwmGetColorizationParameters = GetProcAddress(hDwmDLL,(LPCSTR)127);
*(FARPROC *)&DwmSetColorizationParameters = GetProcAddress(hDwmDLL,(LPCSTR)131);
}
DwmIsCompositionEnabled(&enabled); if(!enabled) {
MessageBox(hWnd,"Composition is not
enabled\nUnable to work!","Error",MB_ICONERROR);
FreeLibrary(hDwmDLL);
EndDialog(hWnd,0);
}
if(!DwmGetColorizationParameters &&
!DwmSetColorizationParameters) {
MessageBox(hWnd,"Unable to find
necessary functions in library","Error",MB_ICONERROR);
FreeLibrary(hDwmDLL);
EndDialog(hWnd,0);
}
else
{
DwmGetColorizationParameters(&dwmcolor); Restore = dwmcolor.clrColor; srand((unsigned) time(&t)); }
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: KillTimer(hWnd,ID_TIMER);
dwmcolor.clrColor = Restore;
DwmSetColorizationParameters(&dwmcolor,0); break;
case IDC_BUTTON2: SetTimer(hWnd,ID_TIMER,300,NULL);
break;
}
return TRUE;
case WM_CLOSE:
KillTimer(hWnd,ID_TIMER);
dwmcolor.clrColor = Restore;
DwmSetColorizationParameters(&dwmcolor,0); FreeLibrary(hDwmDLL); 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
NOTE: This will not work on Windows 10.