How do IsThemeActive, IsAppThemed, and IsCompositionActive differ?

There are three functions which test very similar things, and sometimes applications pick the wrong one. Here's the rundown:

  • IsThemeActive checks whether visual styles are enabled for the user. This is not an application-specific setting; it tells you whether visual styles are enabled in general. Note that this does not tell you whether the current application is using visual styles.
  • IsAppThemed checks whether visual styles are enabled for the current application. Windows may disable visual styles for a specific application (even though they are enabled in general) for compatiblity reasons.
  • IsCompositionActive checks whether desktop composition is enabled for the current application. As with visual styles, Windows may disable desktop composition for a specific application (even though it is enabled in general) for compatiblity reasons.

Note that these functions do not answer the question "Is the application using the visual-styles-enabled version of the common controls library?" That question is harder to answer because the decision to use the visual-styles-enabled version of the common controls library is not a process-wide one but is rather made on a window-by-window basis. You can have an application where half of the button controls are the old non-visual-styles version and half of the button controls participate in visual styles. (You may have seen this in action in Explorer, where the OK button on the Run dialog participates in visual styles, yet a button in a shell extension does not.)

How can you tell whether a particular button is an old-school button or a fancy new button? I don't know either.

Bonus emphasis: From the comments, it appears that people have confused "a window was created with the visual-styles-enabled version of the common controls library" with "themes are enabled". The two are independent concepts. All four combinations are possible. I thought I called this out in the article, but apparently I didn't call it out clearly enough.

Comments (16)
  1. Adam says:

    Out of inexperience, why would someone need to know?

  2. JS Bangs says:

    So why is theming enabled per-window rather than per-process? I find that somewhat counterintuitive, but I assume there must be a good reason. (And I assume that when you say "window-by-window basis" you mean window = HWND, rather than window = top-level window (the layman's definition.)

  3. dalek says:

    "How can you tell whether a particular button is an old-school button or a fancy new button? I don't know either." Wow, maybe the end of the world did start last Saturday, it's just not happening as fast as everyone expects :)

  4. Joel says:

    @Adam I actually found myself in a position where I needed to know.  Due to some bugs in Windows Forms, toolbars and a few other controls, when placed in a tab page, would not correctly pick up the white background of the tabpage, resulting in a slightly jarring (to me, at least) visual experience.  The only solution I found, ultimately, was to check for themes, and if so, manually set the toolbar background color to the background color of the tabpage.  It's an ugly way to do things, I know.  Don't chastise me too much :).

  5. Roland says:

    I use GetWindowTheme(buttonhwnd) to determine whether a button is themed or not, and it seems to work reliably.

  6. Jonathan says:

    @JS Bangs: If theming were per-process, an appcompat-requiring shell extension would cause all windows of Explorer.exe to be unthemed.

  7. henke37 says:

    Here are some ideas of stuff to look at (given a hwnd) to find out if it is fancy:

    window procedure (better have a plan for those chained ones)

    window class (remember to check the hinstance too)

    window extra data

    [Yay, relying on undocumented behavior. Keeping the application compatibility team in business! -Raymond]
  8. Joshua says:

    Okay, apparently anything Raymond says he doesn't know is a challenge.

  9. James Schend says:

    Joshua: Everything Raymond says people see as a challenge, period. 2/3rds of the comments here are people trying to "correct" Raymond's post, generally either by being a pedant nitpicker, or by putting forth arguments he already addressed in the post.

  10. Nitpicker says:

    James: Let me tell you something about that…

  11. WndSks says:

    The MSDN pages for IsThemeActive and IsAppThemed both talk about the current application and not the user, this confuses me every time I have to look this stuff up.

    IsAppThemed can't be trusted anyway, it will return 0 if you "Disable visual themes" on the compatibility tab, but it will return != 0 for a simple hello world app without a manifest (If themes (Visual Styles really) are on systemwide). I'm guessing IsAppThemed returns true if comctl v6 is used to draw, even when using the classic look. This probably makes sense internally, but most people would expect IsAppThemed to return false for a app with the classic look.

    What most people care about is if comctl v6 is used or not since it provides more features so you don't have to owner draw (Listview/Header sort arrow, EM_SETCUEBANNER etc), I don't know if it is a good idea to use IsAppThemed to detect the version, it is probably better to stick with DllGetVersion.

    The hard part is to detect classic look (comctl v4/5 & v6) vs "real" visual styles (Luna etc). Most people probably don't need to know, but there might be edge cases where classic look is drawn differently…

  12. Ian Boyd says:

    The "manifest" does not enable theming in your application. Theming is a feature provided by the operating system, exposed as a set of APIs. Your application is free to use, or not use them, at your own discretion. If you create your own controls, then you should pay your taxes and be sure to respect the users preferences – in this case their visual styles.

    Your app is also free to use whatever 3rd party controls you like. Microsoft even updated their "common controls" library to take advantage of the theme API. These updated controls are available in version 6 of the common controls library, which are available as a side-by-side assembly. That's what the manifest gets you: a version of the common controls that draw themselves with the theme API (if available).

    You can still call the theme API and not load v6 common controls. Your app can draw itself themed, while not using any common controls. Nothing requires a themed application to have a manifest.

  13. WndSks says:

    @Ian Boyd: Yes, I skipped talking about activation contexts and the horrible ISOLATION_AWARE_ENABLED headerfile hack. I only said "without a manifest" to make it clear that I tried to opt-out of getting the v6 comctl. My point was that the look/style/mode of the v6 common controls might not match the return value of IsAppThemed.

  14. asdbsd says:

    @WndSks: Re-read what Ian Boyd is talking about, you're clearly not getting it. To simplify matters further, here's a table:

    V5comctl: NOT themed.

    V6comctl: themed, if IsAppThemed returns true.

    comctl = HasManifest ? V6comctl : V5comctl.

    In other words, if you don't have a manifest, you're creating V5 common controls and it does not matter what IsAppThemed returns – they're not styled.

    On the other hand, some other DLL in your application could explicitly access theming API and draw themed controls. Even though you're not getting any!

    Manifest is not some magic "enable/disable themes" thing. It's just "replace STANDARD controls by themed versions". IsAppThemed does not talk about comctl, it talks about themes at all.

  15. Medinoc says:

    How can common controls V6 usage be determined on a per-window basis? Isn't it rather on a per-module basis, depending on each module's manifest?

    If it is indeed on a per-window basis, how does one choose?

  16. DaveK says:

    @Joel: Why wouldn't just always indiscriminately manually setting the toolbar background colour to the tabpage background colour work, regardless of themes or no themes?

Comments are closed.

Skip to main content