代码之家  ›  专栏  ›  技术社区  ›  Mike Caron

windows是否在应用程序中预加载ComCtrl32.dll?

  •  4
  • Mike Caron  · 技术社区  · 14 年前

    我遇到了一个我知道密码的情况

    我在Visual Studio 2008中创建了一个MFC应用程序,它生成一个托盘图标和一些通知。我读过了我可以用一个不同的 NOTIFYICONDATA 通过设置 cbSize LoadIconMetric 在Windows Vista中加载通知的图标,而在Windows XP中,该功能对我不可用,我必须使用 LoadIcon

    在我的应用程序中,我设置了以下内容:

    #ifndef WINVER
    #define WINVER 0x0600 // Vista
    #endif
    
    #ifndef _WIN32_WINNT
    #define _WIN32_WINNT 0x0600 // Vista
    #end#if
    
    #ifndef _WIN32_WINDOWS
    #define _WIN32_WINDOWS 0x0600 // Vista
    #endif
    
    #ifndef _WIN32_IE
    #define _WIN32_IE 0x0700
    #endif
    

    我正在Visual Studio 2008中的Windows 7 x64计算机上编译和链接Windows 7 SDK。我对WindowsVista或更高版本的测试如下(直接从MSDN中取出):

    static BOOL IsWinVistaOrLater()
    {
        // Initialize the OSVERSIONINFOEX structure.
        OSVERSIONINFOEX osvi;
        ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
        osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
        osvi.dwMajorVersion = 6;
        osvi.dwMinorVersion = 1;
    
        // Initialize the condition mask.
        DWORDLONG dwlConditionMask = 0;
        VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
        VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
    
        // Perform the test.
        return VerifyVersionInfo(&osvi, 
                VER_MAJORVERSION | VER_MINORVERSION,
                dwlConditionMask);
    }
    

    下面是有趣的部分。我使用IsWinVistaOrLater确定是否应使用LoadIconMetric或LoadIcon:

    if (IsWinVistaOrLater())
    {
        tnd_Happy.dwInfoFlags = NIIF_LARGE_ICON | tnd_Happy.dwInfoFlags;
        LoadIconMetric(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON_HAPPY), LIM_SMALL, &(tnd_Happy.hIcon));
    } else {
        tnd_Happy.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE (IDI_ICON_HAPPY)); // ICON RESOURCE ID
    }
    

    在XP上,这与“在ComCtrl32.dll中找不到序号380”一起崩溃。如果我把电话留言给 负荷系数 ,一切都很快乐(即使所有目标版本都设置为Vista)。无论运行时代码路径如何,Windows是否尝试导入所有函数调用?

    3 回复  |  直到 14 年前
        1
  •  3
  •   Ajay    12 年前

    而不是 LoadLibrary GetProcAddress 根据Chris的建议,您可以编写一个Vista-only延迟加载链接DLL,其中包含所有Vista-only代码,而您的主项目仍然以XP为目标。然后,您不需要只加载Vista代码,除非执行通过Vista版本检查并调用从Vista代码DLL导出的函数。

        2
  •  10
  •   Siamoen    12 年前

    Common Control Versions

    我在包含CommCtrl.h之前添加了这一行,从而解决了这个问题(请注意,我的应用程序仅针对Windows Vista及更高版本):

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

    它源于Microsoft示例项目:

    Notification Icon Sample - NotificationIcon.zip

        3
  •  7
  •   Chris Becke    14 年前

    如果您为Vista设置了头文件,那么它将允许您构建不会在早期版本的Windows上加载的应用程序。这就是为什么正确设置该文件如此重要的原因。

    要解决您的问题:

    • 应该可以使用 /DELAYLOAD

    • 将目标版本头文件重置为0x0501(XP)。如果您尝试使用任何高级功能,Windows将自动发出警告。使用LoadLibrary(“comctl32.dll”)&getprocadaddress(“LoadIconMetric”)访问新功能。此方法的缺点是可以通过getprocadaddress进行新调用,但结构(如果它们已更改)将是旧结构。

    最后,许多comctl32.dll特性都是一个技巧:除非您有 Enabled Visual Styles