对于vs2008下MFC的编译或者说vc6到vs2008的移植性问题

 

 

对于vs2008下MFC的编译或者说vc6到vs2008的移植性问题

转自(http://hi.baidu.com/popey/blog/item/fbf66e275887890b908f9d21.html)

2009-04-21 23:28
刚刚转入2008下写MFC程序,出了很多问题,小结一下

1.

编译错误:syntax error : identifier '__RPC__in'


同样的程序,换个编译环境就出现如下错误:

syntax error : identifier '__RPC__in'
syntax error : identifier '__RPC__in_opt
syntax error : identifier '__RPC__out_ecount_part'

原因:不同版本的SDK头文件包含有所不同,而以上三个标识符都是定义在头文件"rpcsal.h"中。

解决办法:包含头文件"rpcsal.h"即可

#include <rpcsal.h>

----------------------------------------------------------感谢飘飘白云的文章


2.

关于 #define WINVER

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

 

你可能感兴趣的:(windows,api,struct,XP,mfc,dll)