第一个有点莫名其妙,就不说了,textout也有一个参数是设置透明背景的
第二个:come from msdn
造成应用程序无法安装在 Windows 2000 上的第一位原因,是它们无法正确处理版本号。
我们发现很多应用程序都进行以下示例代码所做的操作。它们在运行过程中会调用
GetVersionEX,然后写下一条“if”语句,该语句规定:“如果系统是版本 3,
因为没有新的 Shell,我不能正常运行,所以我可能无法安装。如果系统是版本 4,
我可以进行安装和设置”。问题出在如果系统是版本 5,这一“if”语句就没有了下文
。因为版本号是 5.0,这些应用程序由于自身原因而无法安装,所以我们发现了一系列
这样那样的问题。
if (osvi.dwMajorVersion == 3)
{
// 请这样做
}
else if (osvi.dwMajorVersion == 4)
{
// 请那样做
}
测试组继续寻找解决方案,并蒙蔽了许多此类应用程序。在早期的编译中,我们能够采取
措施改变 GetVersionEx 的返回值。我们可以改变其返回值,欺骗应用程序,告诉它版本号
就是 4.0,然后程序就能够继续安装,并正常运行。但有部分应用程序的设计思想就是不
能安装在 Windows 2000 上。对于病毒扫描程序或其他低级实用程序来说,受限于某一操
作系统版本是可以理解的。不过,这些应用程序会显示消息来说明这一点。我们查找的是
那些不能安装或无法正常运行、又根本没有通知用户的应用程序。
怎样才能正确地检查版本号?在 Windows 2000 中我们将添加一个新的 API:
VerifyVersionInfo,这一 API 在运行时将依次检查主版本号、次版本号以及服务包。
如果出现了操作系统的新版本,应用程序仍然能够在其上安装并运行。实际上应用
VerifyVersionInfo 的选项和方式还有很多,但如果只是检查“要是操作系统升级了,
应用程序该如何处理”这一类问题,您只需调用这三个标志,然后检查主版本号、
次版本号以及服务包。您能够定义以下语句:“我的程序需要运行在
Windows NT 4.0、SP2 上”,然后询问 VerifyVersionInfo“我正在运行的操作系统
是否已达到这一标准?”,该 API 将返回真值或假值。
VerifyVersionInfo(&osvi,
VER_MAJORVERSION |
VER_MINORVERSION |
VER_SERVICEPACKMAJOR,
dwlConditionMask);
采用这一方式检查版本,就可以符合 Windows 2000 应用程序的规范,其基本思想是“
只要存在新版本的操作系统,就要在新版本上进行安装。”
应用 VerifyVersionInfo 的一个问题是目前该 API 只能在 Windows 2000 平台上运行。
为了检查 Windows 95 等旧平台的版本,您必须应用GetVersionEx。查看以下示例代码
,即可发现它的功能与 VerifyVersionInfo 基本相同:依次检查主版本号、次版本号以
及服务包。
BOOL bIsWindowsVersionOK(DWORD dwMajor, DWORD dwMinor, DWORD dwSPMajor )
{
OSVERSIONINFO osvi;
// 初始化 OSVERSIONINFO 结构
//
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx((OSVERSIONINFO*)&osvi);
// 首先,主版本
if ( osvi.dwMajorVersion > dwMajor )
return TRUE;
else if ( osvi.dwMajorVersion == dwMajor )
{
// 然后,次版本
if (osvi.dwMinorVersion > dwMinor )
return TRUE;
else if (osvi.dwMinorVersion == dwMinor )
{
// 对,最好检查一下 Service Pack
if ( dwSPMajor && osvi.dwPlatformId == VER_PLATFORM_WIN32_NT )
{
HKEY hKey;
DWORD dwCSDVersion;
DWORD dwSize;
BOOL fMeetsSPRequirement = FALSE;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"System//CurrentControlSet//Control//Windows", 0,
KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
{
dwSize = sizeof(dwCSDVersion);
if (RegQueryValueEx(hKey, "CSDVersion",
NULL, NULL, (unsigned char*)&dwCSDVersion,
&dwSize) == ERROR_SUCCESS)
{
fMeetsSPRequirement = (LOWORD(dwCSDVersion) >= dwSPMajor);
}
RegCloseKey(hKey);
}
return fMeetsSPRequirement;
}
return TRUE;
}
}
return FALSE;
}
//
// 此示例适用于 Windows 2000 和更新版本
//
BOOL bIsWindowsVersionOK(DWORD dwMajor, DWORD dwMinor, DWORD dwSPMajor )
{
OSVERSIONINFOEX osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osvi.dwMajorVersion = dwMajor;
osvi.dwMinorVersion = dwMinor;
osvi.wServicePackMajor = dwSPMajor;
// 设置条件掩码。
VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL );
VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL );
VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL );
// 执行测试。
return VerifyVersionInfo(&osvi,
VER_MAJORVERSION | VER_MINORVERSION
| VER_SERVICEPACKMAJOR,dwlConditionMask);
}
首先,需要检查主版本号。如果当前操作系统的主版本号高于所需主版本号,则不需要
进行任何检查,直接向下运行即可。如果主版本号相等,则以同样方式检查次版本号。
最后再检查服务包号。在我们获得发布的某一版本时,就可以说“没关系,我们不在乎
是 Service Pack 3、4 还是 5”。如果主版本号或次版本号有所增长,系统同样可以处
理。我们查找了所有要检查版本信息的应用程序,发现它们将分别检查每一组件。它们
在运行中会说“噢,主版本号是 5,我只要求 4,不错。次版本号是 .0,很好,但
Service Pack 是 0,我需要的是 3”。很明显,Windows 2000 还没有推出 SP3,
所以这种检查版本信息的方法是错误的。
检查 Windows NT 的版本号时需要注意以下细节:检查版本号和服务包信息的方法有三种
。第一种是获取 GetVersionEx 的返回值,然后检查“szCSDVersion”字符串。实际的
服务包号嵌入在该字符串的某一位置。分析这一串字符实在是比较繁琐,而且您必须始终
牢记它是否进行了本地化,这是很难做到的。这不是一种最好的方式。如果系统运行的是
Windows NT 4.0,您只需检查以下注册键值,其中有一个数字是服务包号。提取这一数字,
并进行一个“等于”或“大于”比较即可:
HCLM/System/CurrentControlSet/Control/Windows/CSDVersion
如果您运行的是 Windows 2000 或更高版本,则仍可以使用 GetVersionEx,但需要将其传
递到 OSVERSIONINFOEX 结构,而不是正在使用的OSVERSIONINFO 结构。考虑到起始处操作
员成员的大小,Windows 2000 会将其视为一个较大的结构,并且给出一个新的字段(服务
包、主版本、次版本),作为进行比较时所用的整数。如果您还是使用
VerifyVersionInfo,您会发现这是最方便的一种方式。