DLL版本的一些细节
下面这个文章介绍了一些没有被微软写进文档里的细节,但是最好选择性地参考,不要依赖一些微软没有写进文档的做法,可能会降低程序的兼容性。
XXXXXXXXXXXXXXXXXXXXXXXXXXXX/studies/windows/shell/comctl32/
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/murrays/2006/10/13/richedit-versions/
comctl32.dll版本的区别
传统版本:
需要manifest的版本:
关于SetWindowSubclass等函数
comctl32.dll中包含有SetWindowSubclass,GetWindowSubclass,RemoveWindowSubclass,DefSubclassProc四个函数,可以实现可拆卸的窗口过程替换。
不过个人并不推荐按序号使用这四个函数,因为微软并没有把这四个函数的序号写进文档里。推荐的做法:
riched20.dll v2.0和v3.0的区别
Win98/98SE/NT4自带的riched20.dll版本号是v2.0(文件版本v5.0),功能不全,不过我们可以用instmsia.exe和instmsiw.exe将其更新成v3.0(文件版本v5.30)。Win2000/Me/XP/2003的riched20.dll是v3.0,WinVista以上的riched20.dll是v3.1(文件版本v5.31)。
v2.0和v3.0下载:
一般来说,应该总是认为riched20.dll是v3.0版本,并使用"RichEdit20A"和"RichEdit20W"。除此之外,也可以使用WinXPSP1附带的msftedit.dll(v4.1,"RichEdit50W")。虽然Office 2003/2007/2010里边的riched20.dll版本更高,但是没有官方文档,用起来问题比较多。
判断DLL版本的方法
comctl32.dll导出了一个叫做DllGetVersion的函数,可以获取DLL版本。不过它没有被放到XXXXXXXXXXXb中,因为还有shell32.dll和shlwapi.dll也导出了这个函数。因此需要使用GetProcAddress调用它。它的原型在shlwapi.h头文件中定义为DLLGETVERSIONPROC。
不过由于像riched20.dll之类的大多数DLL都没有导出DllGetVersion函数,因此个人建议通过读取RT_VERSION资源的方式判断DLL文件版本号,这种方法才是最通用的方法。
这里要注意的是,riched20.dll版本v2.0的实际文件版本号是v5.0,而riched20.dll版本v3.0的实际文件版本号是v5.30。
<code class="language-cpp">#include <windows.h> #include <windowsx.h> #include <commctrl.h> #include <shlwapi.h> #include <tchar.h> //#include <strsafe.h> #include <stdio.h> #include <stdlib.h> #pragma comment(lib, "comctl32.lib") #pragma comment(lib, "version.lib") BOOL CALLBACK DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); BOOL CheckModuleFileVersion(LPCTSTR modname, WORD major, WORD minor, WORD build, WORD rev) { HMODULE hmod = GetModuleHandle(modname); if (!hmod) return FALSE; LPVOID verblock = LockResource(LoadResource(hmod, FindResource(hmod, MAKEINTRESOURCE(1), MAKEINTRESOURCE(RT_VERSION)))); if (!verblock) return FALSE; VS_FIXEDFILEINFO *pvsffi = NULL; UINT szvsffi = 0; if (!VerQueryValue(verblock, _T("\\"), (LPVOID*)&pvsffi, &szvsffi)) return FALSE; ULONGLONG ullFileVersion = ((ULONGLONG)pvsffi->dwFileVersionMS << 32) + pvsffi->dwFileVersionLS; ULONGLONG ullReqVersion = ((ULONGLONG)major << 48) + ((ULONGLONG)minor << 32) + ((ULONGLONG)build << 16) + rev; if (ullFileVersion < ullReqVersion) return FALSE; return TRUE; } BOOL CheckModuleProductVersion(LPCTSTR modname, WORD major, WORD minor, WORD build, WORD rev) { HMODULE hmod = GetModuleHandle(modname); if (!hmod) return FALSE; LPVOID verblock = LockResource(LoadResource(hmod, FindResource(hmod, MAKEINTRESOURCE(1), MAKEINTRESOURCE(RT_VERSION)))); if (!verblock) return FALSE; VS_FIXEDFILEINFO *pvsffi = NULL; UINT szvsffi = 0; if (!VerQueryValue(verblock, _T("\\"), (LPVOID*)&pvsffi, &szvsffi)) return FALSE; ULONGLONG ullProductVersion = ((ULONGLONG)pvsffi->dwProductVersionMS << 32) + pvsffi->dwProductVersionLS; ULONGLONG ullReqVersion = ((ULONGLONG)major << 48) + ((ULONGLONG)minor << 32) + ((ULONGLONG)build << 16) + rev; if (ullProductVersion < ullReqVersion) return FALSE; return TRUE; } void NoSupportedDllExit() { MessageBox(NULL, _T("此操作系统需要安装Internet Explorer 5.01和Windows Installer 1.0或以上版本的相应组件以运行此程序。"), _T("错误"), MB_ICONERROR); exit(1); } int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, _TCHAR *szCmdLine, int nShowCmd) { // 检查系统支持 #ifdef UNICODE if (!CheckModuleProductVersion(_T("kernel32.dll"), 5, 0, 0, 0)) #else if (!CheckModuleProductVersion(_T("kernel32.dll"), 4, 10, 0, 0)) #endif { MessageBox(NULL, _T("此操作系统不受支持。"), _T("错误"), MB_ICONERROR); exit(1); } // comctl32.dll v4.70-5.81 compatible HMODULE hcomctl32 = LoadLibrary(TEXT("comctl32.dll")); INITCOMMONCONTROLSEX icc = { sizeof icc }; typedef BOOL(WINAPI*TInitCommonControlsEx)(LPINITCOMMONCONTROLSEX); TInitCommonControlsEx pInitCommonControlsEx = NULL; if (hcomctl32) pInitCommonControlsEx = (TInitCommonControlsEx)GetProcAddress(hcomctl32, "InitCommonControlsEx"); if (pInitCommonControlsEx) for (int i = 0; i < 16; i++) icc.dwICC = 1 << i, pInitCommonControlsEx(&icc); // riched20.dll LoadLibrary(TEXT("riched20.dll")); // 要求comctl32.dll版本v5.81和riched20.dll版本v3.0(实际文件版本v5.30) if (!CheckModuleFileVersion(_T("comctl32.dll"), 5, 81, 0, 0) || !CheckModuleFileVersion(_T("riched20.dll"), 5, 30, 0, 0)) NoSupportedDllExit(); DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc, NULL); return 0; } </stdlib.h></stdio.h></strsafe.h></tchar.h></shlwapi.h></commctrl.h></windowsx.h></windows.h></code>
时段 | 个数 |
---|---|
{{f.startingTime}}点 - {{f.endTime}}点 | {{f.fileCount}} |