常用控件版本

本主题列出了公共控件库 (ComCtl32.dll) 的可用版本,介绍了如何识别应用程序所使用的版本,并说明如何针对特定版本定位应用程序。

本主题包含以下各节:

公共控件 DLL 版本编号

所有 32 位和 64 位版本的 Windows 包括的 ComCtl32.dll 提供对公共控件的支持。 DLL 的每个后续版本都支持早期版本的功能和 API,并添加新功能。

由于各种版本的 ComCtl32.dll 随 Internet Explorer 一起分发,因此活动版本有时与操作系统随附的版本不同。 因此,应用程序必须直接确定存在哪个版本的 ComCtl32.dll。

在公共控件参考文档中,许多编程元素指定受支持的最小 DLL 版本号。 此版本号指示编程元素在该版本和 DLL 的后续版本中实现,除非另有指定。 如果未指定版本号,则编程元素将在 DLL 的所有现有版本中实现。

下表概述了不同的 DLL 版本,以及如何在受支持的 OS 上分发它们。

ComCtl32.dll

版本

分发平台

5.81

Microsoft Internet Explorer 5.01、Microsoft Internet Explorer 5.5 和 Microsoft Internet Explorer 6

5.82

Windows Server 2003、Windows Vista、Windows Server 2008 和 Windows 7

6.0

Windows Server 2003

6.10

Windows Vista、Windows Server 2008 和 Windows 7

 

不同公共控件版本的结构大小

对公共控件的持续增强导致需要扩展许多结构。 因此,结构的大小在 Commctrl.h 的不同版本之间发生了变化。 由于大多数公共控件结构采用结构大小作为参数之一,因此如果无法识别大小,消息或函数可能会失败。 为了解决此问题,已定义结构大小常量以帮助定位不同版本的 ComCtl32.dll。 以下列表定义结构大小常量。

结构大小常量 定义
HDITEM_V1_SIZE 版本 4.0 中的 HDITEM 结构的大小。
IMAGELISTDRAWPARAMS_V3_SIZE 版本 5.9 中的 IMAGELISTDRAWPARAMS 结构的大小。
LVCOLUMN_V1_SIZE 版本 4.0 中的 LVCOLUMN 结构的大小。
LVGROUP_V5_SIZE 版本 6.0 中的 LVGROUP 结构的大小。
LVHITTESTINFO_V1_SIZE 版本 4.0 中的 LVHITTESTINFO 结构的大小。
LVITEM_V1_SIZE 版本 4.0 中的 LVITEM 结构的大小。
LVITEM_V5_SIZE 版本 6.0 中的 LVITEM 结构的大小。
LVTILEINFO_V5_SIZE 版本 6.0 中的 LVTILEINFO 结构的大小。
MCHITTESTINFO_V1_SIZE 版本 4.0 中的 MCHITTESTINFO 结构的大小。
NMLVCUSTOMDRAW_V3_SIZE 版本 4.7 中的 NMLVCUSTOMDRAW 结构的大小。
NMTTDISPINFO_V1_SIZE 版本 4.0 中的 NMTTDISPINFO 结构的大小。
NMTVCUSTOMDRAW_V3_SIZE 版本 4.7 中的 NMTVCUSTOMDRAW 结构的大小。
PROPSHEETHEADER_V1_SIZE 版本 4.0 中的 PROPSHEETHEADER 结构的大小。
PROPSHEETPAGE_V1_SIZE 版本 4.0 中的 PROPSHEETPAGE 结构的大小。
REBARBANDINFO_V3_SIZE 版本 4.7 中的 REBARBANDINFO 结构的大小。
REBARBANDINFO_V6_SIZE 版本 6.0 中的 REBARBANDINFO 结构的大小。
TTTOOLINFO_V1_SIZE 版本 4.0 中的 TOOLINFO 结构的大小。
TTTOOLINFO_V2_SIZE 版本 4.7 中的 TOOLINFO 结构的大小。
TTTOOLINFO_V3_SIZE 版本 6.0 中的 TOOLINFO 结构的大小。
TVINSERTSTRUCT_V1_SIZE 版本 4.0 中的 TVINSERTSTRUCT 结构的大小。

 

使用 DllGetVersion 确定版本号

应用程序可以调用 DllGetVersion 函数,以确定系统上存在哪个 DLL 版本。

DllGetVersion 返回 DLLVERSIONINFO2 结构。 除了通过 DLLVERSIONINFO 提供的信息之外,DLLVERSIONINFO2 还提供用于标识最新安装的服务包的修补程序编号,从而提供一种比较版本号的更可靠方法。 由于 DLLVERSIONINFO2 的第一个成员是 DLLVERSIONINFO 结构,因此后面的结构向后兼容。

以下示例函数 GetVersion 加载指定的 DLL 并尝试调用其 DllGetVersion 函数。 如果成功,它会使用宏将 DLLVERSIONINFO 结构中的主版本号和次要版本号打包到返回到调用应用程序的 DWORD 中。 如果 DLL 不导出 DllGetVersion,该函数将返回零。 可以修改函数来处理 DllGetVersion 返回 DLLVERSIONINFO2 结构的可能性。 如果是这样,请使用该 DLLVERSIONINFO2 结构的 ullVersion 成员中的信息来比较版本、内部版本号和服务包版本。 MAKEDLLVERULL 宏可简化将这些值与 ullVersion 中的值进行比较的任务。

注意

错误地使用 LoadLibrary 可能会带来安全风险。 有关如何使用不同版本的 Windows 正确加载 DLL 的信息,请参阅 LoadLibrary 文档。

 

#include "stdafx.h"
#include "windows.h"
#include "windef.h"
#include "winbase.h"
#include "shlwapi.h"

#define PACKVERSION(major,minor) MAKELONG(minor,major)

DWORD GetVersion(LPCTSTR lpszDllName)
{
    HINSTANCE hinstDll;
    DWORD dwVersion = 0;

    // For security purposes, LoadLibrary should be provided with a fully qualified 
    // path to the DLL. The lpszDllName variable should be tested to ensure that it 
    // is a fully qualified path before it is used. 
    hinstDll = LoadLibrary(lpszDllName);
    
    if(hinstDll)
    {
        DLLGETVERSIONPROC pDllGetVersion;
        pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion");

        // Because some DLLs might not implement this function, you must test for 
        // it explicitly. Depending on the particular DLL, the lack of a DllGetVersion 
        // function can be a useful indicator of the version. 

        if(pDllGetVersion)
        {
            DLLVERSIONINFO dvi;
            HRESULT hr;

            ZeroMemory(&dvi, sizeof(dvi));
            dvi.info1.cbSize = sizeof(dvi);

            hr = (*pDllGetVersion)(&dvi);

            if(SUCCEEDED(hr))
            {
               dwVersion = PACKVERSION(dvi.info1.dwMajorVersion, dvi.info1.dwMinorVersion);
            }
        }
        FreeLibrary(hinstDll);
    }
    return dwVersion;
}

下面的代码示例演示如何使用 GetVersion 测试 ComCtl32.dll 是版本 6.0 还是更高版本。

LPCTSTR lpszDllName = L"C:\\Windows\\System32\\ComCtl32.dll";
DWORD dwVer = GetVersion(lpszDllName);
DWORD dwTarget = PACKVERSION(6,0);

if(dwVer >= dwTarget)
{
    // This version of ComCtl32.dll is version 6.0 or later.
}
else
{
    // Proceed knowing that version 6.0 or later additions are not available.
    // Use an alternate approach for older the DLL version.
}

项目版本

为了确保应用程序与 .dll 文件的不同目标版本兼容,版本宏存在于头文件中。 这些宏用于定义、排除或重新定义不同版本的 DLL 的某些定义。 有关这些宏的深入说明,请参阅使用 Windows 标头

例如,宏名称 _WIN32_IE 通常位于较旧的标头中。 你负责将宏定义为十六进制数。 此版本号定义使用 DLL 的应用程序的目标版本。 下表显示了可用的版本号以及每个版本号对应用程序的影响。

版本 说明
0x0300 该应用程序与 ComCtl32.dll 版本 4.70 及更高版本兼容。 应用程序无法实现版本 4.70 后添加的功能。
0x0400 该应用程序与 ComCtl32.dll 版本 4.71 及更高版本兼容。 应用程序无法实现版本 4.71 后添加的功能。
0x0401 该应用程序与 ComCtl32.dll 版本 4.72 及更高版本兼容。 应用程序无法实现版本 4.72 后添加的功能。
0x0500 该应用程序与 ComCtl32.dll 版本 5.80 及更高版本兼容。 应用程序无法实现版本 5.80 后添加的功能。
0x0501 该应用程序与 ComCtl32.dll 版本 5.81 及更高版本兼容。 应用程序无法实现版本 5.81 后添加的功能。
0x0600 该应用程序与 ComCtl32.dll 版本 6.0 及更高版本兼容。 应用程序无法实现版本 6.0 后添加的功能。

 

如果未在项目中定义 _WIN32_IE 宏,则会自动将其定义为 0x0500。 若要定义其他值,可以将以下内容添加到 make 文件中的编译器指令;替换 0x0400 所需的版本号。

/D _WIN32_IE=0x0400

另一种方法是在包含 Shell 头文件之前,在源代码中添加类似于以下内容的行。 替换 0x0400 所需的版本号。

#define _WIN32_IE 0x0400
#include <commctrl.h>

关于常用控件