【问题标题】:How to enable visual styles without a manifest如何在没有清单的情况下启用视觉样式
【发布时间】:2010-11-29 21:57:47
【问题描述】:

根据docs

“如果您希望您的应用程序使用 ComCtl32.dll 版本 6,您必须添加一个应用程序清单或编译器指令来指定应该使用版本 6(如果可用)。”

注意到上面的逻辑或了吗?那么这个神秘的编译器指令是什么?

我有一个完全包含在单个 .cpp 文件中的本机 Win32 C++ 应用程序。没有资源文件、清单文件等。我想保持这种方式,但我也想使用视觉样式。

【问题讨论】:

    标签: c++ winapi comctl32 visual-styles


    【解决方案1】:

    实际上还有第三种方式,没有任何清单,虽然它相当hacky:

    #include <windows.h>
    
    // NOTE: It is recommended that you delay-load ComCtl32.dll (/DelayLoad:ComCtl32.dll)
    // and that you ensure this code runs before GUI components are loaded.
    // Otherwise, you may get weird issues, like black backgrounds in icons in image lists.
    ULONG_PTR EnableVisualStyles(VOID)
    {
        TCHAR dir[MAX_PATH];
        ULONG_PTR ulpActivationCookie = FALSE;
        ACTCTX actCtx =
        {
            sizeof(actCtx),
            ACTCTX_FLAG_RESOURCE_NAME_VALID
                | ACTCTX_FLAG_SET_PROCESS_DEFAULT
                | ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID,
            TEXT("shell32.dll"), 0, 0, dir, (LPCTSTR)124
        };
        UINT cch = GetSystemDirectory(dir, sizeof(dir) / sizeof(*dir));
        if (cch >= sizeof(dir) / sizeof(*dir)) { return FALSE; /*shouldn't happen*/ }
        dir[cch] = TEXT('\0');
        ActivateActCtx(CreateActCtx(&actCtx), &ulpActivationCookie);
        return ulpActivationCookie;
    }
    

    【讨论】:

    • 因此,这将打破微软在某些未来版本的 Windows 中将资源 ID 124 更改为其他值的那一天。
    • @MichaelWalz:是的,这就是为什么它很hacky。
    • @herzlshemuelian 唯一可能的无效参数是CreateActCtx() 返回的HANDLE,它在失败时返回INVALID_HANDLE_VALUE。如果CreateActCtx() 失败,请使用GetLastError() 找出原因(可能是Win10 中更改了资源ID?此代码在Win7 中有效)。此外,如果CreateActCtx() 成功,此代码会泄漏HANDLE。使用完激活上下文后,您需要调用ReleaseActCtx(),但此代码不会将HANDLE 保存在任何地方。
    • 看来 CreateActCtx 总是会在某个时候使用清单。在这种情况下,它从 Shell32.dll 中获取资源 #124,而这恰好是 Manifest 资源。在 Windows XP 和 Windows 10 之间,资源 #124 一直是清单文件。
    • 此外,使用CreateActCtx 不是“Hacky”,它是所有 Windows 窗体程序用来启用视觉样式的。它使用 System.Windows.Forms.dll 中的资源 #101(清单)。
    【解决方案2】:

    如果您使用的是 Visual Studio,您可以将此行添加到您的 stdafx.cpp 例如:

    #pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
    

    【讨论】:

      【解决方案3】:

      如果你继续阅读,你会发现the answer

      如果您使用的是 Microsoft Visual C++ 2005 或更高版本,您可以将以下编译器指令添加到您的源代码中,而不是手动创建清单。为便于阅读,此处将指令分为两行。

      #pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' 
      version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
      

      【讨论】:

      • 大声笑,我确实打开了那个链接,但是略过了那条线。看起来它完全是关于清单的。
      • 问题(对于强迫症类型)仍然存在于上述而不是如果一个人已经包含了其他事物的清单,那么上述仍然有效吗? 答:如果我们将“手动创建清单”理解为“手动创建清单专门为此目的”,是的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-02
      • 1970-01-01
      • 1970-01-01
      • 2013-07-31
      • 2016-08-25
      • 2018-12-30
      相关资源
      最近更新 更多