原文地址:http://blog.ehomy.net/archives/94
最近在在把一些程序从VC6迁移到VS2008,由此而关注到了Winodws版本的定义问题。
关于版本定义的关键无外乎为程序头文件中对于#define WINVER 和 #define _WIN32_WINNT 的使用,具体为:
#define WINVER 0xXXXX #define _WIN32_WINNT 0xXXXX
该定义一般用于标示程序对运行环境的要求,另外在某些头文件中也有这样的宏定义。如果版本匹配的话就会在编译的时候将这些内容编译,否则就不编译。
定义正确的Windows版本,不仅关系到程序的正确编译,同时也关系到程序的正确运行;在升级的过程中,我就碰到了程序编译正确但运行出错的问题。实例稍候再续。
版本的定义关系到被编译到程序中的内容,这里主要是指系统提供的功能代码。Windows各个版本的功能虽然大差不差,但特定于某个系统功能还是存在的,于是关系到这些功能的API代码也就有所不一样。当我们在程序中定义了错误的系统版本,被编译进程序的内容便可能包含当前系统不支持的代码片段,这样的程序即使可能正确编译通过,但在运行的时候,由于在当前系统中找不到相应的内容资源,从而发生错误。这一点熟悉动态链接库(DLL)的人都很清楚,其实该问题就是和系统动态链接库有关。
Example:
下面为一段获取系统信息提示框的字体信息的代码片段:(编译环境从VC6迁移至VS2008,运行系统为Windows XP)
// Retrieves the message font info NONCLIENTMETRICS ncm; ncm.cbSize = sizeof(NONCLIENTMETRICS); VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)); // Creates the font according to the message font info m_Font.CreateFontIndirect(&(ncm.lfMessageFont));
程序在VC6下编译运行都正确,迁移至VS2008后,编译正确,但运行时出错。原因是SystemParametersInfo调用失败,这和其传入的参数有关,根本在于 NONCLIENTMETRICS 这个结构体变量的定义。
在新的 Windows SDK 6.0 中,其定义如下:
typedef struct tagNONCLIENTMETRICSA { UINT cbSize; int iBorderWidth; int iScrollWidth; int iScrollHeight; int iCaptionWidth; int iCaptionHeight; LOGFONTA lfCaptionFont; int iSmCaptionWidth; int iSmCaptionHeight; LOGFONTA lfSmCaptionFont; int iMenuWidth; int iMenuHeight; LOGFONTA lfMenuFont; LOGFONTA lfStatusFont; LOGFONTA lfMessageFont; #if(WINVER >= 0x0600) int iPaddedBorderWidth; #endif /* WINVER >= 0x0600 */ } #ifdef UNICODE #define NONCLIENTMETRICSW NONCLIENTMETRICS #else #define NONCLIENTMETRICSA NONCLIENTMETRICS #endif
注意最后一个成员的定义条件,其指明了,该成员只能应用于 WINVER >= 0×0600 的系统环境(这里指明了系统为Vista)。
考虑到我迁移程序的时候,是直接利用VS2008将VC6程序转化的方式,然后按VS2008新建项目的StdAfx.h文件内容更新了原来的StdAfx.h头文件,并添加了VS2008项目才有的targerver.h头文件。
根据targetver.h头文件里的下列定义:
#ifndef WINVER // 指定要求的最低平台是 Windows Vista。 #define WINVER 0x0600 // 将此值更改为相应的值,以适用于 Windows 的其他版本。 #endif #ifndef _WIN32_WINNT // 指定要求的最低平台是 Windows Vista。 #define _WIN32_WINNT 0x0600 // 将此值更改为相应的值,以适用于 Windows 的其他版本。 #endif
我的程序便使用了新的Windows SDK版本的定义。于是编译的时候,NONCLIENTMETRICS 的最后一个成员便编译进了程序,由于系统DLL是动态加载的,所以程序在此可以正确编译。但是在运行的过程中,当前XP系统的DLL不支持该成员(新增的成员,在该系统下为不可用),这里表现为来自系统API的SystemParametersInfo函数,找不到匹配该系统预定义的NONCLIENTMETRICS 结构体参数,从而导致程序在运行时出错。
解决方法:
考虑当前系统的版本,添加合适的版本预定义,以程序在当前系统的正确运行。
如上述程序可以在项目的StdAfx.h头文件中添加如下预定义:
#define WINVER 0x0500 #define _WIN32_WINNT 0x0500
PS:0×0500 表示Windows 2000,0×0501为Windows XP,0×0502为Windows Server 2003,0×0600 为 Windows Vista。
以上问题并不复杂,主要是对Windows程序中关于版本定义问题的一些了解,以求得在以后的程序中涉及到该类问题,诸如程序移植等等,有一个明确的认识!
相关推荐
在Jan Axelson上修改而来,下载文件中包含可以直接使用的可执行文件。修改了usbhidio_vc6的接收数据显示,不显示Report ID,只显示接收到的真实数据。...则需要在stdafx.h里面增加#define WINVER 0x0500就OK了。
#define WINVER 0x0501 // 改变为适当值,以针对Windows XP和更新版本。 #endif #ifndef _WIN32_WINNT // 允许使用 Windows NT 4 或更高版本的特定功能。 #define _WIN32_WINNT 0x0501 // 改变为适当值,以针对...
amcap源代码,visual studio 亲测通过,打开摄像头设备。 // File: AMCap.h // // Desc: DirectShow sample code - audio/video capture. // ...//-------------------------------------------------...#endif // WINVER
#define WINVER 0x0501 // 改为支持 Windows XP SP1 及以上版本 #endif #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0501 // 同上 #endif #ifndef _WIN32_WINDOWS #define _WIN32_WINDOWS 0x0501 // 同上 #endif...
#define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define GAP 1 #ifndef OBM_CHECK #define OBM_CHECK 32760 // from winuser.h #endif #if _MFC_VER #error This code does...
winuser.h这个头文件中包含了很多windows编程需要的常量.在用c#调用api时经常会用到这些常量.每次需要用时就要去winuser.h中查找常量的定义,比较麻烦,所以...如将#define SW_HIDE 0 转为 public const int SW_HIDE = 0;
#define WINVER 0x0501 // 允许使用特定于Windows XP或更高版本的功能。 #endif ``` 删除以下代码: ```cpp #include #include #include #pragma comment(lib, "aygshell.lib") ``` 并在文件末尾添加以下代码:...
摘要:VC/C++源码,控件相关,CGfxOutBarCtrl CGfxOutBarCtrl类源码和使用实例,类库中包括了如下文件的下载: GfxOutBarCtrl.h、GfxOutBarCtrl.cpp、GfxGroupEdit.cpp... #define WINVER 0x0500 //为 Windows98 和 W
- **修改`targetver.h`文件**:将`#define WINVER 0x0600`修改为`#define WINVER 0x0501`,以及相应的`_WIN32_WINNT`定义。 - **包含头文件**:在C++源文件中,通过`#include "qrfact.h"`来引入MATLAB函数接口。 - *...
#define WINVER 0x0600 // 设置为对应VS2010的Windows SDK版本 #endif ``` 编译可能需要半小时左右,完成后,VTK将在指定的bin目录下生成所需的库文件和可执行文件,至此,VTK已在你的Win7和VS2010环境中成功安装。...
在VC6.0和VC2008之间进行代码移植时,最常见的问题是关于宏定义`_WIN32_WINNT`与`_WIN32_IE`之间的冲突。这两个宏用于指定编译时使用的Windows API版本。例如,在VC6中,常见的宏定义如下: ```cpp #ifndef _WIN32_...
#define WINVER 0x0501 // Windows XP SP2 #endif #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0500 // Windows 2000 #endif ``` 2. **解决dll缺失问题** - 如果在构建过程中遇到`vtkio.dll`等动态库缺失...
- `#define WINVER 0x0500`: 定义了最小支持的操作系统版本号为Windows 2000。 - `LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM)`: 定义了窗口过程函数的原型,该函数负责处理所有发送给窗口的消息。 - ...
#define __AFXWIN_H__ ///////////////////////////////////////////////////////////////////////////// // Make sure 'afx.h' is included first #ifndef __AFX_H__ #include #endif // Note: WINDOWS.H ...
#define _WIN32_WINNT 0x0400 #endif #endif ``` 这样,只有在使用VC6(对应_MSC_VER为1200)或更早版本时,才会设置 `_WIN32_WINNT` 为0x0400,而在VC9中则会使用更高版本的定义,避免冲突。 接下来,我们来看第...
尽管已经解决了一些已知问题,例如 WINVER 的设置、`<iostream>` 的使用以及 `std` 命名空间的处理等,但仍然存在两个主要的编译错误:C2440 和 C2660。 #### 二、错误 C2440 详解 **错误描述**: 错误 C2440 在 `...