65.9K
CodeProject 正在变化。 阅读更多。
Home

如何准确检测应用程序是否启用了主题?

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.58/5 (18投票s)

2005年6月2日

1分钟阅读

viewsIcon

90059

描述了一个克服 IsAppThemed 和 IsThemeActive 不足之处的函数。

图 1:系统级主题和应用程序特定主题已启用

图 2:系统级主题已启用,应用程序特定主题已禁用

图 3:系统级主题已禁用。(应用程序特定主题无关紧要)

概述

当您开发根据应用程序是否启用主题而以不同方式工作的自定义控件时,您需要检测当前运行的应用程序是否正在使用主题。MSDN 列出了两个函数 IsAppThemed IsThemeActive,以下是我从其文档中摘录的内容:-

IsAppThemed 函数 - 报告当前应用程序的用户界面是否使用视觉样式显示。
IsThemeActive 函数 - 测试当前应用程序的视觉样式是否处于活动状态。

您会认为您只需要使用其中一个或两个函数,不是吗? 猜猜怎么着? 在 XP(甚至 SP2)上,如果您的系统级主题设置已启用,这两个函数都会返回 TRUE。 因此,任何使用 XP 样式主题的系统都会始终使这两个函数返回 TRUE

我在网上搜索了一下,没有找到有价值的东西。 我看到 Jeff Partch (MVP) 发布了一条消息,建议在 comctl32.dll 上调用 GetModuleHandle,并将该模块句柄与通过在已知控件句柄上使用 GCLP_HMODULE 标志调用 GetClassLongPtr 返回的句柄进行比较。 虽然我实际上没有尝试过,但我认为调用 comctl32.dll 上的 DllGetVersion 并检查版本是否大于或等于 6 会更容易。

IsThemed 函数

该代码大量使用 LoadLibrary/GetProcAddress 以避免对 PSDK 的依赖(该代码现在可以在 VC++ 6 的默认安装上编译)。

#pragma once

#include "stdafx.h"
#include <Shlwapi.h>

BOOL IsThemed()
{
    BOOL ret = FALSE;
    OSVERSIONINFO ovi = {0};
    ovi.dwOSVersionInfoSize = sizeof ovi;
    GetVersionEx(&ovi);
    if(ovi.dwMajorVersion==5 && ovi.dwMinorVersion==1)
    {
        //Windows XP detected
        typedef BOOL WINAPI ISAPPTHEMED();
        typedef BOOL WINAPI ISTHEMEACTIVE();
        ISAPPTHEMED* pISAPPTHEMED = NULL;
        ISTHEMEACTIVE* pISTHEMEACTIVE = NULL;
        HMODULE hMod = LoadLibrary(_T("uxtheme.dll"));
        if(hMod)
        {
            pISAPPTHEMED = reinterpret_cast<ISAPPTHEMED*>(
                GetProcAddress(hMod,_T("IsAppThemed")));
            pISTHEMEACTIVE = reinterpret_cast<ISTHEMEACTIVE*>(
                GetProcAddress(hMod,_T("IsThemeActive")));
            if(pISAPPTHEMED && pISTHEMEACTIVE)
            {
                if(pISAPPTHEMED() && pISTHEMEACTIVE())                
                {                
                    typedef HRESULT CALLBACK DLLGETVERSION(DLLVERSIONINFO*);
                    DLLGETVERSION* pDLLGETVERSION = NULL;

                    HMODULE hModComCtl = LoadLibrary(_T("comctl32.dll"));
                    if(hModComCtl)
                    {
                        pDLLGETVERSION = reinterpret_cast<DLLGETVERSION*>(
                            GetProcAddress(hModComCtl,_T("DllGetVersion")));
                        if(pDLLGETVERSION)
                        {
                            DLLVERSIONINFO dvi = {0};
                            dvi.cbSize = sizeof dvi;
                            if(pDLLGETVERSION(&dvi) == NOERROR )
                            {
                                ret = dvi.dwMajorVersion >= 6;
                            }
                        }
                        FreeLibrary(hModComCtl);                    
                    }
                }
            }
            FreeLibrary(hMod);
        }
    }    
    return ret;
}

使用代码

if(IsThemed())
    m_bThemed = true;
else
    m_bThemed = false;

历史

  • 2005年6月2日 - 文章首次发表
© . All rights reserved.