{"id":366,"date":"2013-01-02T00:05:16","date_gmt":"2013-01-01T13:05:16","guid":{"rendered":"http:\/\/blog.quppa.net\/?p=366"},"modified":"2013-01-02T00:05:16","modified_gmt":"2013-01-01T13:05:16","slug":"retrieving-windows-8-theme-colours","status":"publish","type":"post","link":"https:\/\/www.quppa.net\/blog\/2013\/01\/02\/retrieving-windows-8-theme-colours\/","title":{"rendered":"Retrieving Windows 8 Theme Colours"},"content":{"rendered":"<p><i>See also<\/i>: <a href=\"http:\/\/www.quppa.net\/win8col\/\" title=\"Windows 8 Theme Colours Reference\">Windows 8 Theme Colours Reference<\/a>.<\/p>\n<p>Windows 8 doesn\u2019t offer developers access to system theme colours, <a title=\"MSDN: Theme resources for Windows Phone\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windowsphone\/develop\/ff769552.aspx\">unlike its cousin, Windows Phone<\/a>. Even for a version 1 product, this seems like a strange omission. Then again, <a title=\"Within Windows: Retrieving Aero Glass base color for opaque surface rendering\" href=\"http:\/\/www.withinwindows.com\/2010\/07\/01\/retrieving-aero-glass-base-color-for-opaque-surface-rendering\/\">we still don\u2019t have a working public API for retrieving the Aero glass colour<\/a> (or whatever we call it now that Aero\u2019s gone) 6 years after the release of Windows Vista.<\/p>\n<p>The functions that the system uses to retrieve colours are defined in UxTheme.dll. In particular, we\u2019re interested in GetImmersiveColorSetCount (export #94), GetImmersiveColorFromColorSetEx (export #95), GetImmersiveColorTypeFromName (export #96), GetImmersiveUserColorSetPreference (export #98) and GetImmersiveColorNamedTypeByIndex (export #100). Relying on undocumented functions is <a title=\"The Old New Thing: When programs grovel into undocumented structures...\" href=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2003\/12\/23\/45481.aspx\">a bad idea<\/a>, and <strong>will cause your program to fail certification<\/strong>, so you won\u2019t be able to use them in apps distributed through the Windows Store anyway.<\/p>\n<p>For desktop developers who still want to use these functions, read on. Just assume that they\u2019ll break in future versions of Windows (or even with patches to Windows 8).<\/p>\n<p><a href=\"https:\/\/www.quppa.net\/blog\/wp-content\/uploads\/colours.png\"><img loading=\"lazy\" decoding=\"async\" title=\"Windows 8 Colours\" style=\"border-width: 0px; margin: 5px; display: inline; background-image: none;\" border=\"0\" alt=\"Screenshot of Windows 8 Colours\" src=\"https:\/\/www.quppa.net\/blog\/wp-content\/uploads\/colours_thumb.png\" width=\"600\" height=\"24\" \/><\/a><\/p>\n<p><!--more--><\/p>\n<p>There are 25 colour sets available in Windows 8, pictured above. Users can switch between these in the Metro control panel (under Personalise &gt; Start screen). Additionally, when a high contrast theme is enabled, colours in the start screen are based on <a title=\"Windows System Colours Reference\" href=\"http:\/\/www.quppa.net\/syscol\/\">traditional window element colours<\/a>, retrieved with the <a title=\"MSDN: GetSysColor function\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/ms724371.aspx\">GetSysColor function<\/a>. With the four high contrast themes included in Windows 8, this means there are effectively 29 different colour sets for a standard setup. Use the GetImmersiveColorSetCount function to retrieve the number of colour sets available and the GetImmersiveUserColorSetPreference function to retrieve the ID of the active colour set. The ID is also stored in the registry key HKCUSoftwareMicrosoftWindowsCurrentVersionExplorerAccent with the name ColorSet_Version3. It occurred to me that one could hard-code values from the 25 colour schemes and read this registry value, but Metro-style apps aren\u2019t even allowed to access the registry \u2013 so much for that idea.<\/p>\n<p>The GetImmersiveUserColorSetPreference functions takes two boolean parameters. The first should be set to true to force UxTheme to read the value stored in the registry (and update the system setting if what\u2019s in the registry is different to what\u2019s in memory). To be honest, I\u2019m not entirely sure what the second parameter does \u2013 setting it to true will stop the function attempting to retrieve the user preference a second time if the first call returns \u20131. I think this is only relevant in the event that UxTheme doesn\u2019t have permission to update the system setting with the value from the registry. In any case, you should be able to disregard these parameters in most scenarios (set them both to false).<\/p>\n<p><a href=\"https:\/\/www.quppa.net\/blog\/wp-content\/uploads\/settings1.png\"><img loading=\"lazy\" decoding=\"async\" title=\"Windows 8 Personalisation Settings\" style=\"margin: 5px; border: 0px currentcolor; display: inline; background-image: none;\" border=\"0\" alt=\"Screenshot of Windows 8 Personalisation Settings\" src=\"https:\/\/www.quppa.net\/blog\/wp-content\/uploads\/settings_thumb1.png\" width=\"640\" height=\"391\" \/><\/a><\/p>\n<p>The GetImmersiveColorNamedTypeByIndex function returns a (pointer to a) string containing the name of an element like \u2018StartBackground\u2019 or \u2018StartDesktopTilesBackground\u2019. There are 767 (0x2ff) names in total \u2013 unfortunately there seems to be no function to retrieve this number. To get the colour type (ID) from a name, we use the GetImmersiveColorTypeFromName function. We must prepend \u2018Immersive\u2019 to the string first, however, or the function will fail (\u2018StartBackground\u2019 becomes \u2018ImmersiveStartBackground\u2019, for example). (In fact, any 9 characters at the start will do \u2013 \u2018xxxxxxxxxStartBackground\u2019 will work just as well.)<\/p>\n<p>GetImmersiveColorTypeFromName returns a number between 0 and 766 (0x2fe). Only the first 108 types (0 to 107) correspond to colours that change according to the colour set \u2013 the remaining 659 are static (unless high contrast mode is enabled).<\/p>\n<p>GetImmersiveColorFromColorSetEx takes four parameters. The first is the colour set ID (between 0 and 24 for Windows 8) and the second is the colour type (e.g. 0 for \u2018StartBackground\u2019). If the third parameter determines whether high contrast mode should be ignored \u2013 set it to 1 to retrieve the active colour set\u2019s colours even when high contrast mode is enabled. The fourth parameter can be set to 1 to force UxTheme to check whether the system is in high contrast mode even with it already thinks it is (this check would otherwise only occur if high contrast mode had previously not been enabled).<\/p>\n<h1>Detecting User Preference Updates<\/h1>\n<p>Listen for WM_SETTINGCHANGE to detect when the user changes the colour scheme. lParam will point to a string with the value \u2018ImmersiveColorSet\u2019. When high contrast mode is enabled or disabled, lParam will point to a string with the value \u2018WindowsThemeElement\u2019.<\/p>\n<h1>P\/Invoke Signatures<\/h1>\n<p>These P\/Invoke signatures should be of help to C# developers wishing to use these functions in desktop programs (again, assume they could stop working at any time):<\/p>\n<pre class=\"lang:c# decode:true \">[DllImport(&quot;uxtheme.dll&quot;, EntryPoint = &quot;#94&quot;)]\npublic static extern int GetImmersiveColorSetCount();<\/pre>\n<pre class=\"lang:c# decode:true \">\/\/\/ &lt;summary&gt;\n\/\/\/ Retrieves an immersive colour from the specified colour set.\n\/\/\/ &lt;\/summary&gt;\n\/\/\/ &lt;param name=\"dwImmersiveColorSet\"&gt;Colour set index. Use &lt;see cref=\"GetImmersiveColorSetCount\"\/&gt; to get the number of colour sets available.&lt;\/param&gt;\n\/\/\/ &lt;param name=\"dwImmersiveColorType\"&gt;The colour type. Use &lt;see cref=\"GetImmersiveColorTypeFromName\"\/&gt; to get the type from an element name.&lt;\/param&gt;\n\/\/\/ &lt;param name=\"bIgnoreHighContrast\"&gt;Set this to true to return colours from the current colour set, even if a high contrast theme is being used.&lt;\/param&gt;\n\/\/\/ &lt;param name=\"dwHighContrastCacheMode\"&gt;Set this to 1 to force UxTheme to check whether high contrast mode is enabled. If this is set to 0, UxTheme will only perform this check if high contrast mode is currently disabled.&lt;\/param&gt;\n\/\/\/ &lt;returns&gt;Returns a colour (0xAABBGGRR).&lt;\/returns&gt;\n[DllImport(\"uxtheme.dll\", EntryPoint = \"#95\")]\npublic static extern uint GetImmersiveColorFromColorSetEx(uint dwImmersiveColorSet, uint dwImmersiveColorType, bool bIgnoreHighContrast, uint dwHighContrastCacheMode);<\/pre>\n<pre class=\"lang:c# decode:true \">\/\/\/ &lt;summary&gt;\n\/\/\/ Retrieves an immersive colour type given its name.\n\/\/\/ &lt;\/summary&gt;\n\/\/\/ &lt;param name=\"pName\"&gt;Pointer to a string containing the name preprended with 9 characters (e.g. \"Immersive\" + name).&lt;\/param&gt;\n\/\/\/ &lt;returns&gt;Colour type.&lt;\/returns&gt;\n[DllImport(\"uxtheme.dll\", EntryPoint = \"#96\")]\npublic static extern uint GetImmersiveColorTypeFromName(IntPtr pName);<\/pre>\n<pre class=\"lang:c# decode:true \">\/\/\/ &lt;summary&gt;\n\/\/\/ Gets the user's colour set preference (or default colour set if the user isn't allowed to modify this setting according to group policy).\n\/\/\/ &lt;\/summary&gt;\n\/\/\/ &lt;param name=\"bForceCheckRegistry\"&gt;Forces update from registry (HKCUSoftwareMicrosoftWindowsCurrentVersionExplorerAccentColorSet_Version3).&lt;\/param&gt;\n\/\/\/ &lt;param name=\"bSkipCheckOnFail\"&gt;Skip second check if first result is -1.&lt;\/param&gt;\n\/\/\/ &lt;returns&gt;User colour set preference.&lt;\/returns&gt;\n[DllImport(\"uxtheme.dll\", EntryPoint = \"#98\")]\npublic static extern int GetImmersiveUserColorSetPreference(bool bForceCheckRegistry, bool bSkipCheckOnFail);<\/pre>\n<pre class=\"lang:c# decode:true \">\/\/\/ &lt;summary&gt;\n\/\/\/ Retrieves names of colour types by index.\n\/\/\/ &lt;\/summary&gt;\n\/\/\/ &lt;param name=\"dwIndex\"&gt;Colour type index (0 to 766\/0x2fe).&lt;\/param&gt;\n\/\/\/ &lt;returns&gt;Pointer to a string containing the colour type's name.&lt;\/returns&gt;\n[DllImport(\"uxtheme.dll\", EntryPoint = \"#100\")]\npublic static extern IntPtr GetImmersiveColorNamedTypeByIndex(uint dwIndex);<\/pre>\n<h1>Sample Code (C#)<\/h1>\n<p>The following code retrieves the \u2018StartSelectionBackground\u2019 colour from the active colour set (assuming the above P\/Invoke signatures).<\/p>\n<pre class=\"lang:c# decode:true \">int colourset = Colour.GetImmersiveUserColorSetPreference(false, false);\nIntPtr pElementName = Marshal.StringToHGlobalUni(&quot;ImmersiveStartSelectionBackground&quot;);\nuint type = Colour.GetImmersiveColorTypeFromName(pElementName);\nMarshal.FreeCoTaskMem(pElementName);\nuint colourdword = Colour.GetImmersiveColorFromColorSetEx((uint)colourset, type, false, 0);\nbyte[] colourbytes = new byte[4];\ncolourbytes[0] = (byte)((0xFF000000 &amp; colourdword) &gt;&gt; 24); \/\/ A\ncolourbytes[1] = (byte)((0x00FF0000 &amp; colourdword) &gt;&gt; 16); \/\/ B\ncolourbytes[2] = (byte)((0x0000FF00 &amp; colourdword) &gt;&gt; 8); \/\/ G\ncolourbytes[3] = (byte)(0x000000FF &amp; colourdword); \/\/ R\nColor colour = Color.FromArgb(colourbytes[0], colourbytes[3], colourbytes[2], colourbytes[1]);<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>See also: Windows 8 Theme Colours Reference. Windows 8 doesn\u2019t 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\u2019t have a working public API for retrieving the Aero glass colour (or whatever we call it &hellip; <a href=\"https:\/\/www.quppa.net\/blog\/2013\/01\/02\/retrieving-windows-8-theme-colours\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Retrieving Windows 8 Theme Colours&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,9],"tags":[28,34,35,83,160,171,174,181],"class_list":["post-366","post","type-post","status-publish","format-standard","hentry","category-programming","category-windows","tag-c","tag-colour","tag-colours","tag-metro","tag-uxtheme","tag-windows-2","tag-windows-8","tag-winrt"],"_links":{"self":[{"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/posts\/366","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/comments?post=366"}],"version-history":[{"count":0,"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/posts\/366\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/media?parent=366"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/categories?post=366"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.quppa.net\/blog\/wp-json\/wp\/v2\/tags?post=366"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}