`
dazhilao
  • 浏览: 244268 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

【转】关于 #define WINVER

阅读更多

原文地址: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程序中关于版本定义问题的一些了解,以求得在以后的程序中涉及到该类问题,诸如程序移植等等,有一个明确的认识!

分享到:
评论

相关推荐

    VC6编写的HID读写测试工具

    在Jan Axelson上修改而来,下载文件中包含可以直接使用的可执行文件。修改了usbhidio_vc6的接收数据显示,不显示Report ID,只显示接收到的真实数据。...则需要在stdafx.h里面增加#define WINVER 0x0500就OK了。

    c2010转化低版本VC过程后编译错误

    #define WINVER 0x0501 // 改变为适当值,以针对Windows XP和更新版本。 #endif #ifndef _WIN32_WINNT // 允许使用 Windows NT 4 或更高版本的特定功能。 #define _WIN32_WINNT 0x0501 // 改变为适当值,以针对...

    amcap source code源代码

    amcap源代码,visual studio 亲测通过,打开摄像头设备。 // File: AMCap.h // // Desc: DirectShow sample code - audio/video capture. // ...//-------------------------------------------------...#endif // WINVER

    vs2003移植到vs2012需要注意的几个问题

    #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头文件c#版

    winuser.h这个头文件中包含了很多windows编程需要的常量.在用c#调用api时经常会用到这些常量.每次需要用时就要去winuser.h中查找常量的定义,比较麻烦,所以...如将#define SW_HIDE 0 转为 public const int SW_HIDE = 0;

    WinCE平台的程序移植到Win32平台下运行的工程修改方法

    #define WINVER 0x0501 // 允许使用特定于Windows XP或更高版本的功能。 #endif ``` 删除以下代码: ```cpp #include #include #include #pragma comment(lib, "aygshell.lib") ``` 并在文件末尾添加以下代码:...

    CGfxOutBarCtrl类源码下载和使用实例

    摘要:VC/C++源码,控件相关,CGfxOutBarCtrl CGfxOutBarCtrl类源码和使用实例,类库中包括了如下文件的下载:  GfxOutBarCtrl.h、GfxOutBarCtrl.cpp、GfxGroupEdit.cpp... #define WINVER 0x0500 //为 Windows98 和 W

    matlab与vc混合编程及详细实例

    - **修改`targetver.h`文件**:将`#define WINVER 0x0600`修改为`#define WINVER 0x0501`,以及相应的`_WIN32_WINNT`定义。 - **包含头文件**:在C++源文件中,通过`#include "qrfact.h"`来引入MATLAB函数接口。 - *...

    VTK在WIN7,VS2010环境下安装(包含多个错误解决方案)

    #define WINVER 0x0600 // 设置为对应VS2010的Windows SDK版本 #endif ``` 编译可能需要半小时左右,完成后,VTK将在指定的bin目录下生成所需的库文件和可执行文件,至此,VTK已在你的Win7和VS2010环境中成功安装。...

    从VC6到VC9代码移植的问题总结 从VC6.0到VC2008代码移植的问题总结

    在VC6.0和VC2008之间进行代码移植时,最常见的问题是关于宏定义`_WIN32_WINNT`与`_WIN32_IE`之间的冲突。这两个宏用于指定编译时使用的Windows API版本。例如,在VC6中,常见的宏定义如下: ```cpp #ifndef _WIN32_...

    VTK 在VS 2010上安装与创建工程心得

    #define WINVER 0x0501 // Windows XP SP2 #endif #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0500 // Windows 2000 #endif ``` 2. **解决dll缺失问题** - 如果在构建过程中遇到`vtkio.dll`等动态库缺失...

    图形绘制API函数

    - `#define WINVER 0x0500`: 定义了最小支持的操作系统版本号为Windows 2000。 - `LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM)`: 定义了窗口过程函数的原型,该函数负责处理所有发送给窗口的消息。 - ...

    stdafx.h代码

    #define __AFXWIN_H__ ///////////////////////////////////////////////////////////////////////////// // Make sure 'afx.h' is included first #ifndef __AFX_H__ #include #endif // Note: WINDOWS.H ...

    vc2008转换

    #define _WIN32_WINNT 0x0400 #endif #endif ``` 这样,只有在使用VC6(对应_MSC_VER为1200)或更早版本时,才会设置 `_WIN32_WINNT` 为0x0400,而在VC9中则会使用更高版本的定义,避免冲突。 接下来,我们来看第...

    Problems Upgrading code from v6 to .NET

    尽管已经解决了一些已知问题,例如 WINVER 的设置、`<iostream>` 的使用以及 `std` 命名空间的处理等,但仍然存在两个主要的编译错误:C2440 和 C2660。 #### 二、错误 C2440 详解 **错误描述**: 错误 C2440 在 `...

Global site tag (gtag.js) - Google Analytics