4

I must really know which Windows theme my user is using.
More precisely, Classic, XP, Basic or Aero. (Basic theme as in Vista/7 Windows Basic theme)
I already know how to find if it's aero, but how about the others?


The answer can be in any .NET language (C#, VB.NET or C++).


If you really have to know why on Earth I need to know the theme then here you go:
I have some floating buttons over the caption of a form and I need to change their appearance according to the windows theme.
So far I've managed to find Aero/Classic.


Screen shots of the result, after solving the issue: Minimize to tray button

Vercas
  • 8,931
  • 15
  • 66
  • 106

2 Answers2

5

You can check the registry for the current theme at:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes

under String "CurrentTheme" which has the path to the current theme. below is the code for checking it in C#.

using Microsoft.Win32;

public string GetTheme()
{
  string RegistryKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes";
  string theme;
  theme = (string) Registry.GetValue(RegistryKey, "CurrentTheme", string.Empty);
  theme = theme.Split('\\').Last().Split('.').First().ToString();
  return theme;
}
Shekhar_Pro
  • 18,056
  • 9
  • 55
  • 79
  • My guess is that this will not be able to detect situations where Aero is disabled, e.g. remote desktop, VNC mirror driver. What would help would be for @Vercas to indicate what he wants to do with the information. – David Heffernan Dec 19 '10 at 10:01
  • well i haven't tried it in that situation, but yeah @Vercas should mention whether he will have any such scenario. @David thanx for the point – Shekhar_Pro Dec 19 '10 at 11:47
  • 1
    This is not an option. I need lightning fast solutions. Registries and generally file IO aren't fast enough. Imagine moving a form in Seven/Vista. The form follows the cursor instantly, unlike XP. This could mean reading that registry key even a thousand times per second. – Vercas Dec 19 '10 at 12:10
  • I dont think they are that slower, and moreover you cant change themes while dragging windows could you :P . – Shekhar_Pro Dec 19 '10 at 12:18
  • At least on my computers, they are. An antivirus program will do even worse. Plus, requiring UAC just for this is a waste! (Yes, HKEY_CURRENT_USER is protected!) – Vercas Dec 19 '10 at 12:44
  • @Vercas reading from the registry like this is fast. What's more you only need to do it once and cache the result. Refresh the result when you get sent a WM_THEMECHANGED message. – David Heffernan Dec 19 '10 at 12:47
  • 1
    @Vercas @Shekhar_Pro Also this isn't going to work on XP. No such key as CurrentTheme in that location. Registry keys are an implementation detail and subject to change from version to version. – David Heffernan Dec 19 '10 at 15:26
  • @Vercas I've already given you the solution in my answer. What is your problem with what I have given you. It would be very useful to understand what you are really trying to do. What is it that drives you to need this information? Also, an up-vote or two wouldn't hurt! – David Heffernan Dec 19 '10 at 15:28
  • @Vercas @Shekhar_Pro The code returns the name of the theme, on Vista/7 only, but that name can be chosen by the user. How then are you meant to work out whether or not it is Aero, Basic or Classic? And that's not to mention the potential issues with remote desktop and VNC mirror drivers and so on. And the answer gets 2 up-votes. SO clearly having a bad day!!! – David Heffernan Dec 20 '10 at 09:46
  • I need a working solutions for all versions of windows and, over all, I'm not going to read registries from an application ran from my network. – Vercas Dec 20 '10 at 12:05
  • 1
    @David Thanx for mentioning, i know it may not work in xp, an upvote for your answer, have a good day :) – Shekhar_Pro Dec 20 '10 at 13:44
  • @Shekar_Pro thanks for your kindness - I've no idea why @Vercas is so allergic to the registry - after all .net will be making extensive use of it so there's no reason to be scared of a single read! – David Heffernan Dec 20 '10 at 13:48
  • 1
    @David you are absolutely right, Almost every software in computer use registry. Remember even windows use registry for checking themes and Desktop settings. – Shekhar_Pro Dec 20 '10 at 13:51
  • @David I am indeed registrophobic, but I am not going to wait until UAC checks my application everytime I want to start it just to read a registry. And, as stated above, this is for Vista/Seven, but I target Windows XP and older operating systems too. – Vercas Dec 20 '10 at 14:44
  • @Vercas My app reads the registry quite regularly and there's no UAC checking. It's clearly up to you if you want to keep hold on to this erroneous opinion, but you really are incorrect in your belief! – David Heffernan Dec 20 '10 at 16:09
  • Alright. But in my humble opinion the accepted answer is faster. – Vercas Dec 20 '10 at 16:21
  • @Vercas It likely is, but you shouldn't read the registry, or even call IsAppThemed etc. every time you handle WM_NCPAINT! You work out what your target is once, and then cache that value. – David Heffernan Dec 20 '10 at 17:22
  • That's what I'm doing PLUS I do no NC Paint, I have a floating form that never gets focus and I'm listening to the event you have specified. :D – Vercas Dec 21 '10 at 10:08
  • @Vercas How do you paint to the non client area without handling WM_NCPAINT? Please please don't tell me you are re-painting on a timer! – David Heffernan Dec 21 '10 at 14:24
  • @Vercas Also, if you want me to be notified of your comments, include an @David Heffernan in them. – David Heffernan Dec 21 '10 at 14:25
  • @David, You include @Vercas and I get no notification. :/ And no, don't worry, I am not repainting them. I have a floating form over the caption! And the buttons are panels. ;) – Vercas Dec 21 '10 at 17:10
  • @Vercas Floating form over the caption is a terrible way of doing this! Why don't you just do it in WM_NCPAINT like you are supposed to. – David Heffernan Dec 21 '10 at 17:15
  • does work with aero but you need to change up some. There's a question on the subject here on stack overflow from the famous ben goodger. – David Heffernan Dec 21 '10 at 17:44
  • @David Heffernan got anything for a C# programmer? xD – Vercas Dec 21 '10 at 18:00
  • @David Heffernan, I wasn't speaking rubbish, it really does not work with Aero! – Vercas Dec 21 '10 at 22:44
  • @vercas do the websearch it does work on aero how does firefox 4 draw its non client area? – David Heffernan Dec 21 '10 at 23:54
  • @David Heffernan, it simply doesn't work! Do you have Windows Vista or 7? If so, then please have a look at this: http://vercas.webuda.com/WindowsFormsApplication6.zip and test it with Windows Aero and Windows Basic. – Vercas Dec 22 '10 at 12:13
  • @Vercas You just don't listen do you? And you don't even appear to know how to do a websearch! Sorry to be harsh but you have some lessons to learn. Just because your code doesn't work does not imply that WM_NCPAINT and Aero are not compatible. If you did a websearch for Aero and WM_NCPAINT as I suggested then you would find this: http://stackoverflow.com/questions/1146365 . And as I already said, if it's impossible then how do apps like Firefox 4 manage it? – David Heffernan Dec 22 '10 at 18:23
  • That will disable the Aero glass (Replace it with a white frame, actually), and I wish to keep it! That'd be useful for theming the whole window, not just to draw a little image on it. – Vercas Dec 23 '10 at 10:52
  • @Vercas Well, if you want to believe that it's not possible to interact with DWM and draw your button on the glass, then that's up to you! – David Heffernan Dec 23 '10 at 11:12
  • I'll believe it when I see a working example. My humble guess is that Opera, Google and Mozilla use the same technique as I use. – Vercas Dec 23 '10 at 11:58
  • @Vercas The examples you give are interesting. Do you know who Ben Goodger is? – David Heffernan Dec 23 '10 at 14:01
  • @Vercase I've done some more research into this, the issue has tickled my fancy. I can now see that WM_NCPAINT can't be used to draw custom caption bar items and retain glass. However, the method you are meant to use is to extend the glass into the client area with DwmExtendFrameIntoClientArea. It's described here http://www.codeproject.com/KB/dialog/AeroNonClientAreaButtons.aspx - you've probably read this. The bottom line is that you really should not be using an extra floating form. I can guarantee that Firefox, IE, Chrome, Opera etc. do not do that! Your buttons might even glow! – David Heffernan Dec 23 '10 at 19:58
  • @David Heffernan I have indeed read that article and I am experiencing many problems with that method, including black non client area when maximizing. And yes, I have taken that into counting a while ago. – Vercas Dec 23 '10 at 21:31
3

You can check whether themes are active by calling IsAppThemed/IsThemeActive and then check for Aero by calling DwmIsCompositionEnabled. There may well be other ways of doing this!!

EDIT

The logic would be:

  1. Can I import IsAppThemed and IsThemeActive? If no then I must be in Windows Classic (Win9x or Win2k).
  2. What does IsAppThemed and IsThemeActive return? If false then I must be in Windows Classic.
  3. Can I import DwmIsCompositionEnabled? If no then I must be XP themed.
  4. What does DwmIsCompositionEnabled return? If true then I am Aero, otherwise I am Windows Basic.
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • `IsThemeActive` is the equivalent of `Application.RenderWithVisualStyles`(C#), which doesn't quite work... – Vercas Dec 18 '10 at 18:56
  • @Vercas See my edit. It is conceivable that asking these questions from inside a .net app might have different results. I've no idea how WinForms, WPF etc. are implemented and how themes impact on .net GUI apps. – David Heffernan Dec 18 '10 at 19:03
  • But what if IsThemeActive always returns false? :| – Vercas Dec 18 '10 at 19:24
  • @Vercas: That's item 2 in my list. Windows Classic. – David Heffernan Dec 18 '10 at 19:25
  • The point is that I am using **ANYTHING BUT WINDOWS CLASSIC AND I STILL GET FALSE**. – Vercas Dec 18 '10 at 19:34
  • @Vercas Perhaps it's a .net thing. The logic above certainly works in a native app. Incidentally, I now see that the logic should be replace calls to IsThemeActive with a test of both IsAppThemed and IsThemeActive. – David Heffernan Dec 18 '10 at 19:43
  • @Vercas Are you running this in a console app? I get True for both IsAppThemed and IsThemeActive in a WinForms app. – David Heffernan Dec 18 '10 at 20:02
  • 1
    Definitely WinForms. I will look into `VisualStyleInformation.IsEnabledByUser`. – Vercas Dec 19 '10 at 12:12
  • @Vercas are you building the app with a manifest specifying comctl32 v6? – David Heffernan Dec 19 '10 at 12:18
  • @Vercas Hmm, you'll be needing one to get anywhere with this technique – David Heffernan Dec 19 '10 at 12:46
  • @Vercas You must be doing it wrong! A vanilla WinForms app for me on Windows 7 behaves as I describe. Can you check which version of comctl32 is loaded into your app's process? I would use Process Explorer for that task. – David Heffernan Dec 20 '10 at 12:12
  • It was a f*****g inheriting problem, sorry... Finally, IsThemeActive works! Many thanks! – Vercas Dec 20 '10 at 12:18
  • @Vercas It occurs to me that you are interested in knowing the appearance of the non-client area of the window and there are situations in which an app may not be themed, but the NC drawing is themed. – David Heffernan Dec 20 '10 at 13:50
  • Yes, I am making another boring "minimize to tray" button and, so far, I have themed it for Windows Classic, Windows XP (blue), Windows Basic and Windows Aero. The aero appearance leaves some desire, unfortunately, because I cannot make the button transparent... :( But I will, at least, state that my application is doing it's best to integrate with the user's OS. – Vercas Dec 20 '10 at 14:11
  • @Vercas I'm not sure you need to theme it yourself since the theme API supplied in uxtheme.dll should do this for you. However it is rather dreadfully documented. The bottom line is that you don't need to draw themed buttons yourself, rather you let the system do it for you and it knows how to work with the current theme. – David Heffernan Dec 20 '10 at 14:19
  • But I am making a custom button. I am adding some screenshots to the main post. – Vercas Dec 20 '10 at 14:45
  • (Too late for edit) Are you saying that I can draw the background of a system button and paint my "content" afterwards? o.o – Vercas Dec 20 '10 at 14:54
  • 1
    @Vercas Indeed that is what I am saying. You use the DrawThemeBackground API. – David Heffernan Dec 20 '10 at 15:12
  • @Vercas I'd start with a web search. – David Heffernan Dec 20 '10 at 15:20
  • A very wise start... I am on my way! :D – Vercas Dec 20 '10 at 15:22
  • I can draw the system buttons but I cannot draw just parts of them. Well, for now, my method will do fine... – Vercas Dec 20 '10 at 15:32
  • @Vercas Yes I think you can draw parts of them. In particular you can draw an empty button, with transparency, then fill in your customised bit. As you say though, you seem happy enough with your method. – David Heffernan Dec 20 '10 at 15:38
  • Yes, but the problem is how can I have variable transparency on a form? And I cannot draw images with transparency on a transparent form. – Vercas Dec 20 '10 at 15:55
  • @Vercas I don't know what you are talking about here. You just call the API and let it work out the details! – David Heffernan Dec 20 '10 at 15:56
  • But there are details that I must take care of, and I can't. The only ways to accomplish this are non-client drawing and my method. So far I have accomplished my method. – Vercas Dec 20 '10 at 15:59