以下内容来自如下链接:
http://www.easewe.com/Article/document/879.htm
http://www.rupeng.com/forum/thread-3214-1-1.html
有同学在如鹏论坛提问,在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函数的定义下面:
复制内容到剪贴板这个函数用来锁定操作系统。LockWorkStation安静的的躺在WinUser.h中,按理来说应该能轻松的调用,因此我在文件中调用 LockWorkStation却无情的报告了“LockWorkStation undeclared identifier”。为什么呢? 我们仔细看LockWorkStation函数的定义,看更大范围的:
复制内容到剪贴板对C/C++比较熟悉的同学应该知道“#if”是条件编译的意思,也就是说被“#if”、“#endif”包围的代码只有满足“#if”的条件的时候才会被编译,这个if判断是在编译的时候执行的,而不是运行的时候执行的。 _WIN32_WINNT是一个宏定义,它表示Windows的版本,它有很多取值,取值列表如下:
复制内容到剪贴板因此“#if(_WIN32_WINNT >= 0x0500)”这句话的意思是只有Windows的版本大于Windows 2000 的时候LockWorkStation函数的定义才会起作用,才会被编译。 为什么要根据操作系统的版本决定函数的定义是否编译 呢?道理很简单,因为有的API函数是高版本的Windows下才提供的,低版本的Windows没有那个API函数,所以需要根据操作系统进行判断。 不对呀!我的操作系统是WindowsXP,确实比Windows 2000高呀,为什么不能编译呢? 原因就是“_WIN32_WINNT”并不是像大家想象的那样真的会代表当前编译程序电脑的操作系统的版本,它需要程序员去指定 ,当然VC也给了“_WIN32_WINNT”一个默认值,不过这个默认值是VC从微软那发布的时候微软定义的:
复制内容到剪贴板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的版本,可取值列表如下:
复制内容到剪贴板估计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
我承认我很卑鄙,在这等着你们呢。我相信80%的同学跳过了刚才我贴的这段英文,“全是英文,密密麻麻,不看了”, 就像上面这段英文像梵文一样你看不懂。呵呵。学计算机的要锻炼自己阅读英文资料的能力,所以请跳过这段文章的同学现在回去读一读,“浪子回头金不换”!每个阅读的同学都把它翻译出来,最好落实到纸面上。 除了_WIN32_WINNT、WINVER这两个宏,还有一个重要的宏_WIN32_IE,显而易见,它表示IE的版本,可选值如下:
复制内容到剪贴板有部分函数也是依赖于IE的版本进行条件编译的,因此最好也把_WIN32_IE设置为0x0600。 总结一下,为了避免麻烦,最好每次新建项目的时候把下面几个宏定义加到StdAfx.h中,这样就免除了后顾之忧:
复制内容到剪贴板我也考虑更新“如鹏版对话框程序生成向导”(Rupeng DialogBased Application wizard),把上面的宏定义自动加到StdAfx.h中,在“如鹏版对话框程序生成向导”升级之前同学们先手动加吧。 有同学问:
当然可以改,因为我的电脑是xp,所以我设的是0x0600。其实VC6中设成0x0500以上的任意值已经没区别,因为翻遍了VC6中所有的头文件没有 发现依赖于0x0501以上的函数,很简单,VC6第一个版本发布的的时候是1998年,而VC6配套的SDK头文件最新的版本发布的时候还只有 Windows2000,那时候根本没有WindowsXP、Vista这些东西,所以哪怕 _WIN32_WINNT设成0x0900都行,只不过没意义,VC6下设成0x0500就足够了。