As I noted in my earlier post, the method for selecting theme (‘accent’) colours in Windows ‘Blue’ build 9364 has changed from Windows 8 RTM. I’m not going to bother looking too closely at the updates to the functions in UxTheme.dll this early in the development process, but I did notice two new registry values in the key HKCUSoftwareMicrosoftWindowsCurrentVersionExplorerAccent: ‘AccentColor’ and ‘StartColor’. These are DWORD values that store the accent colour and background colour, respectively. The format is 0xAABBGGRR. The old ‘ColorSet_Version3’ value from Windows 8 is gone for obvious reasons. ‘AccentId_v8.00’ from Windows 8 is now ‘MotionAccentId_v1.00’, but it seems to serve the same purpose – indicating which background image is selected.
Tag: colour
Image Background Remover Tool
Inspired by Window Clippings, my preferred screenshot tool (which unfortunately crashes a lot under Windows 8 RTM), I wrote a small program for making image backgrounds transparent.
It comes with a command-line interface and a basic GUI (pictured above). The GUI supports dragging-and-dropping images, and you can switch the black and white images by right-clicking on either. The source code is included, along with a sample set of images.
The command-line syntax is: BackgroundRemover.exe imageout imageblack imagewhite
Thanks are owed to Ian Griffiths for the equations used to calculate transparency.
BackgroundRemover.7z
478,473 bytes; SHA-1: 002CF9C89B918951BBC7DECB9F9C1A8D53008E1F
Windows 8 Theme Colours Reference
In a similar vein to my Windows System Colours Reference, I’ve compiled a Windows 8 Theme Colours Reference using the APIs I wrote about in the previous post.
Retrieving Windows 8 Theme Colours
See also: Windows 8 Theme Colours Reference.
Windows 8 doesn’t offer developers access to system theme colours, unlike its cousin, Windows Phone. Even for a version 1 product, this seems like a strange omission. Then again, we still don’t have a working public API for retrieving the Aero glass colour (or whatever we call it now that Aero’s gone) 6 years after the release of Windows Vista.
The functions that the system uses to retrieve colours are defined in UxTheme.dll. In particular, we’re interested in GetImmersiveColorSetCount (export #94), GetImmersiveColorFromColorSetEx (export #95), GetImmersiveColorTypeFromName (export #96), GetImmersiveUserColorSetPreference (export #98) and GetImmersiveColorNamedTypeByIndex (export #100). Relying on undocumented functions is a bad idea, and will cause your program to fail certification, so you won’t be able to use them in apps distributed through the Windows Store anyway.
For desktop developers who still want to use these functions, read on. Just assume that they’ll break in future versions of Windows (or even with patches to Windows 8).
Windows 8 Release Preview Updates
I’ve belatedly updated my Windows System Colours Reference and post about Segoe UI to reflect changes in the Windows 8 Release Preview.
WPF: Using System Colours in Animations
WPF provides access to the Windows system colours through the System.Windows.SystemColors class. As the MSDN documentation indicates, it’s possible to bind to these colours dynamically using the *Key resources, so when the system colours change, so will the appearance of your application.
This code will set the colour of a TextBlock to the ‘GrayText’ system colour, and will change automatically if the user switches themes:
1 2 3 |
<TextBlock Foreground="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"> Text </TextBlock> |
In many cases, there’s no reason not to bind dynamically. Problems arise with animations, however. From MSDN:
You can’t use dynamic resource references or data binding expressions to set Storyboard or animation property values. That’s because everything inside a ControlTemplate must be thread-safe, and the timing system must Freeze Storyboard objects to make them thread-safe. A Storyboard cannot be frozen if it or its child timelines contain dynamic resource references or data binding expressions.
This means that you’re stuck using static references to system colours in your animation storyboards – if the user changes the system colours while your application is running, your storyboards won’t update automatically. Worst-case scenario, you might end up with unreadable text.
I don’t think there are any workarounds that don’t involve reloading windows and/or resource dictionaries (depending on where the style code is located). Reloading a window is easy enough – just be careful if you’re closing your application’s last window: the program will shut down if there are no remaining references to any windows.
The method for reloading a resource dictionary is a bit less obvious. It seems that XAML files accessed by their pack URIs are already compiled, so the system colours will be fixed in place once the program starts up. To get around this, change the build action for the XAML file containing the resource dictionary to ‘Embedded Resource’. You can then (re)build the resource dictionary as you please using XamlReader:
1 2 3 |
ResourceDictionary resdic; using (XmlTextReader xr = new XmlTextReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("ProjectNameSpace.MyResourceDictionary.xaml"))) resdic = (ResourceDictionary)XamlReader.Load(xr); |
Remove the old resource dictionary from your application’s merged resource dictionaries, then add the new one.
Creating a new resource dictionary like this seems to be fairly slow, so try to avoid doing it on a regular basis. To tell when the Windows theme or system colours have changed, you’ll need to listen for the window messages WM_THEMECHANGED and WM_SYSCOLORCHANGE. See this post for information about listening for window messages in WPF.
WM_DWMCOLORIZATIONCOLORCHANGED doesn’t give the Aero Glass base colour
From MSDN:
WM_DWMCOLORIZATIONCOLORCHANGED Message
Sent to all top-level windows when the colorization color has changed.
Parameters
wParam: Specifies the new colorization color. The color format is 0xAARRGGBB.
lParam: Specifies whether the new color is blended with opacity.
We receive this message when the Aero Glass colour changes. Unfortunately, the value contained in wParam is not the ‘base colour’, as it is in fact the result of the DwmGetColorizationColor function. As Rafael Rivera noted last year, when glass transparency is enabled, the value returned by this function is quite different to the base colour:
As such, we shouldn’t rely on the contents of wParam (or on the DwmGetColorizationColor function in general).
The easiest method to find the actual base colour is to retrieve the ColorizationColor DWORD from HKCUSoftwareMicrosoftWindowsDWM. This, however, is undocumented, and could potentially change in a future version of Windows (it is correct in NT 6.0 and 6.1):
1 2 |
RegistryKey colourKey = Registry.CurrentUser.CreateSubKey(@"SoftwareMicrosoftWindowsDWM"); uint colour = (uint)(int)colourKey.GetValue("ColorizationColor"); |
(We can’t cast directly to uint despite it being a REG_DWORD, hence the first cast to int…)
For those who feel more adventurous, Rafael went to the trouble of finding a function in dwmapi.dll which returns the base colour (amongst other things). He describes it here.
Office 15: per application border colours?
Winreview.ru’s latest Office 15 screenshots reveal application-specific border colours and drop-shadows. Word gets a dark blue border and shadow, Excel gets a green border and shadow, etc.:
Microsoft in fact applied for a patent for per-window glass colourisation in late 2005 (‘Glass appearance window frame colorization’; discovered by Long Zheng in 2007). While there isn’t any glass in the Office 15 windows shown here (despite the DWM being enabled), the idea is similar.
Office 15 and Windows 8 seem to be moving in similar UI directions – it seems like square corners are in and transparency is out (at least for the ‘Aero Lite’ theme).