Research into classic color schemes and desk cpl's behaviour
May 11, 2021 16:35:41 GMT -8
Post by leet on May 11, 2021 16:35:41 GMT -8
Hello everyone!
For the last week or so I have spent some time digging into desk.cpl and analyzing how it works. I've currently found the function responsible for applying a theme and have succesfully hooked into that functionality from my own code, using desk.cpl as a dll instead of a control panel item.
Now that I had found a way to apply a scheme, I started doing some analysis on how the schemes actually are saved in registry. Through some reverse engineering I was able to come up with this C# class that allows us to create schemes programatically. It still misses a few things but I'm sure that it will be completed if I spend a little more time on it.
Wanting to put these bits of research together, I've stumbled upon another rabbit hole. I want to create a preview for the theme and change the window according to the users selections, just like desk.cpl does it. Sadly I couldn't find any way to dynamically change a window's colors and metrics at this point in time.
Wanting to know how the desk cpl's did it, I started doing some source code digging and found out the desk cpl's actually don't contain the code for the Appearance tab. They take it from themeui.dll instead. This can be confirmed by looking at this analysis from nirsoft: windows10dll.nirsoft.net/themeui_dll.html. It contains strings like Application Background, Message Box and ToolTip which are some of the strings you see when you run desk.cpl.
Going further down this rabbit hole I looked into XP's source code and found that ThemeUI uses an interface called IThemePreview, which is only available through private shell API's. Going down further, I've found a file called previewsm.cpp, which is responsible for drawing the theme preview. This is what the top of the file says:
NOTE: This code will >hand< draw all the window controls, so if
windows changes the way the windows controls are draw, this code
needs to be manually updated. This is an issue for skinning.
There's a function called _DrawPreview in the file. It seems that this function manually draws everything you see in the preview. Literally everything. So basically, to create a custom desk cpl, we would need to create a custom control, which manually draws everything for a preview. Combine that with the class I supplied earlier, and we have a working desk cpl. You might ask, why did you write this thread? Well, I wanted to share everything I have researched because the chance that I'm actually doing this myself is very low. Maybe someone else can pick up where I left one day.