有同学在如鹏论坛提问,在VC6中使用GetListBoxInfo这个API函数的时候编译提示:
'GetListBoxInfo' : undeclared identifier
详见:http://www.rupeng.com/forum/thread-3214-1-1.html
他已经将GetListBoxInfo所在的头文件WinUser.h直接或者间接的包含进来了,打开WinUser.h文件,看到GetListBoxInfo就活生生的躺在那里呢,为什么还是报“'GetListBoxInfo' : undeclared identifier”呢?难道VC眼瞎了吗???
一开始就解决GetListBoxInfo的这个问题可能比较麻烦,咱们先来看另外一个API函数:LockWorkStation,他就在GetListBoxInfo函数的定义下面:
复制内容到剪贴板
代码:
WINUSERAPI BOOL WINAPI LockWorkStation(VOID);
这个函数用来锁定操作系统。LockWorkStation安静的的躺在WinUser.h中,按理来说应该能轻松的调用,因此我在文件中调用LockWorkStation却无情的报告了“LockWorkStation undeclared identifier”。为什么呢?我们仔细看LockWorkStation函数的定义,看更大范围的:
复制内容到剪贴板
代码:
#if(_WIN32_WINNT >= 0x0500)
WINUSERAPI
BOOL
WINAPI
LockWorkStation(
VOID);
#endif /* _WIN32_WINNT >= 0x0500 */
对C/C++比较熟悉的同学应该知道“#if”是条件编译的意思,也就是说被“#if”、“#endif”包围的代码只有满足“#if”的条件的时候才会被编译,这个if判断是在编译的时候执行的,而不是运行的时候执行的。
_WIN32_WINNT是一个宏定义,它表示Windows的版本,它有很多取值,取值列表如下:
复制内容到剪贴板
代码:
Windows XP _WIN32_WINNT>=0x0501
Windows 2000 _WIN32_WINNT>=0x0500
Windows NT 4.0 _WIN32_WINNT>=0x0400
因此“#if(_WIN32_WINNT >= 0x0500)”这句话的意思是只有Windows的版本大于Windows 2000 的时候LockWorkStation函数的定义才会起作用,才会被编译。为什么要根据操作系统的版本决定函数的定义是否编译呢?道理很简单,因为有的API函数是高版本的Windows下才提供的,低版本的Windows没有那个API函数,所以需要根据操作系统进行判断。
不对呀!我的操作系统是WindowsXP,确实比Windows 2000高呀,为什么不能编译呢?
原因就是“_WIN32_WINNT”并不是像大家想象的那样真的会代表当前编译程序电脑的操作系统的版本,它需要程序员去指定,当然VC也给了“_WIN32_WINNT”一个默认值,不过这个默认值是VC从微软那发布的时候微软定义的:
复制内容到剪贴板
代码:
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400
#endif
VC6是1998年发布的,那时候Windows98刚发布,微软当时肯定认为大部分人还是Windows NT 4.0操作系统,为了“主流”,微软就把VC6中_WIN32_WINNT宏的默认值设置成了Windows NT 4.0的0x0400。时光荏苒,日月如梭,现在已经是2009年了,主流的Windows桌面操作系统已经是WindowsXP了,还有相当一部分人用上了Vista甚至Windows7,那么“ _WIN32_WINNT 0x0400”这个默认值已经Out了!
那么咱们怎么修改_WIN32_WINNT的默认值呢?打开StdAfx.h文件,在文件最开始加入“#define _WIN32_WINNT 0x0501”就ok了,也就是设置为WindowsXP。再编译LockWorkStation函数就通过了!!!
晕呀,怎么GetListBoxInfo函数还是不能编译通过???还是“undeclared identifier”,难道LockWorkStation是“这个可以有”,而GetListBoxInfo是“这个真没有”吗?搞技术的不信邪,慢慢琢磨,是不是还是有其他的宏定义控制的条件编译呢?顺着GetListBoxInfo的定义向上搜“#if”,终于发现这么一句“#if(WINVER >= 0x0500)”,WINVER是什么宏呢?也是表示Windows的版本,可取值列表如下:
复制内容到剪贴板
代码:
Windows 95、98 and Windows NT 4.0 WINVER=0x0400
Windows 98 and Windows 2000 WINVER=0x0500
Windows 2000 WINVER=0x0500
Windows xp WINVER=0x0501
估计WINVER还是和_WIN32_WINNT一样的问题,因此我们同样打开StdAfx.h文件,在文件最开始加入“#define WINVER 0x0501”就ok了,也就是设置为WindowsXP。再编译GetListBoxInfo函数就通过了!!!有同学问,怎么微软还弄了_WIN32_WINNT、WINVER两个宏来表示Windows版本呢?详见这篇文章,我就不详细讲了:
http://blogs.msdn.com/oldnewthing/archive/2007/04/11/2079137.aspx
引用:
The WINVER symbol is the earliest one. That's the symbol that 16-bit Windows used to control the versioning of its header files, and its use carried forward into the 32-bit header files, presumably from the people who did the initial conversion of the header files to 32-bit and who grew up with the WINVER symbol. This symbol is still used a lot in the header files that can trace their origins to 16-bit Windows, such as winuser.h, wingdi.h, and mmsystem.h.
The _WIN32_WINNT symbol came next. I'...
本文解释了在使用Windows API函数时遇到的版本条件编译问题,通过修改宏定义来确保函数在不同Windows版本中正确编译和使用。
2000

被折叠的 条评论
为什么被折叠?



