admin管理员组文章数量:1631214
windows.h与windef.h
vc++ 2009-03-15 11:14:58 阅读566 评论0 字号:大中小
今天在用到了一个求最大值的max函数的时候,需要include一个头文件,查找了一下msdn,上面说应该添加windef.h头文件,结果编译的时候却报错了。我也搞不懂是为什么啦,上网查一下,说包含windows.h就可以了。这样是调通了。查看了一下windows.h,的确在这个头文件里又是包含了windef.h的,查了一下windef.h,这里面有的的确确是定义了max的,有点糊涂了。但是网上说最好还是包含windows.h,不管了就先这样吧,以后慢慢再说吧。以下是查到的一些网上的资料(来自http://blog.csdn/fengningning/archive/2008/04/19/2306650.aspx),有时间再看。
关于有没有必要解构“这么一个”头文件,作为初学者,我实在没有太多的见解要发表。我在Microsoft Visual Studio .NET 2005中打开的这个只有260多行(实际占用的行数可能更少)的文件,是所有(我知道用“所有”这个词似乎不大严谨,但据我所知——是的)Windows程序必须先包含的文件,既然是“必须”的,也就是无法规避的,那么又有什么理由阻止我去解构它呢?
刚开头的一段注释是对该头文件的描述: /*++ BUILD Version: 0001 Increment this if a change has global effects Copyright (c) 1985-1997, Microsoft Corporation Module Name: windows.h Abstract: Master include file for Windows applications. --*/ 这个文件似乎没有经历过重大的变化,至今仍是第一个版本。“Increment this if a change has global effects”,意思大概是“如果某个变化有全局性的影响,就将该变化增添至这个头文件”。话本身是没有歧义的,可转而一想,换做是我,我肯定不会擅作主张来修改这个文件的——道理很简单,这样做会导致代码移植更加复杂,还有其他一些不利因素。那么,这句话大概是微软开发人员对“自己人”说的罢。而摘要部分说:“Master include file for windows applications”,就不用多做解释了。 #ifndef _WINDOWS_ #define _WINDOWS_ 这种宏定义应该是最常见的了,一个作用是防止重复包含。 #ifndef WINVER #define WINVER 0x0400 #else #if defined(_WIN32_WINNT) && (WINVER < 0x0400) && (_WIN32_WINNT > 0x0400) #error WINVER setting conflicts with _WIN32_WINNT setting #endif #endif WINVER这个宏与Windows版本相关,也就是该宏变量取不同值时对应不同的Windows版本,Platform SDK文档中的相关说明如下: Windows Server 2003 WINVER>=0x0502 Windows XP WINVER>=0x0501 Windows 2000 WINVER>=0x0500 Windows NT 4.0 WINVER>=0x0400 Windows Me WINVER>=0x0500 Windows 98 WINVER>=0x0410 Windows 95 WINVER>=0x0400 (如何查看自己Windows操作系统的版本号呢?下面提供其中一种方法:调出任务管理器->帮助—>关于任务管理器,在Windows XP中如上操作可以查得版本号是5.1,而在Windows server 2003中是5.2,Windows 2000中则是5.0。哈哈,确实如此,和Platform SDK文档中的描述是一致的!)_WIN32_WINNT这个宏其实也代表版本号,因此如果你同时定义了这个宏,却又与WINVER的定义不一致,那么,编译器就提示错误“WINVER setting conflicts with _WIN32_WINNT”。 #if (WINVER >= 0x0500) #pragma message ("") #pragma message ("NOTE: WINVER has been defined as 0x0500 or greater which enables") #pragma message ("Windows NT 5.0 and Windows 98 features. When these headers were released,") #pragma message ("Windows NT 5.0 beta 1 and Windows 98 beta 2.1 were the current versions.") #pragma message ("") #pragma message ("For this release when WINVER is defined as 0x0500 or greater, you can only") #pragma message ("build beta or test applications. To build a retail application,") #pragma message ("set WINVER to 0x0400 or visit http://www.microsoft/msdn/sdk") #pragma message ("to see if retail Windows NT 5.0 or Windows 98 headers are available.") #pragma message ("") #pragma message ("See the SDK release notes for more information.") #pragma message ("") #endif 如果定义的WINVER>=0x0500,即要求最低的Windows版本是Windows NT 5.0(Windows 2000)和Windows 98,此时编译器在进行编译时会提示以#pragma message定义的一系列信息作为提示。 #ifndef _INC_WINDOWS #define _INC_WINDOWS #if defined (_MSC_VER) && (_MSC_VER >= 1020) #pragma once #endif /* If defined, the following flags inhibit definition * of the indicated items. * * NOGDICAPMASKS - CC_*, LC_*, PC_*, CP_*, TC_*, RC_ * NOVIRTUALKEYCODES - VK_* * NOWINMESSAGES - WM_*, EM_*, LB_*, CB_* * NOWINSTYLES - WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_* * NOSYSMETRICS - SM_* * NOMENUS - MF_* * NOICONS - IDI_* * NOKEYSTATES - MK_* * NOSYSCOMMANDS - SC_* * NORASTEROPS - Binary and Tertiary raster ops * NOSHOWWINDOW - SW_* * OEMRESOURCE - OEM Resource values * NOATOM - Atom Manager routines * NOCLIPBOARD - Clipboard routines * NOCOLOR - Screen colors * NOCTLMGR - Control and Dialog routines * NODRAWTEXT - DrawText() and DT_* * NOGDI - All GDI defines and routines * NOKERNEL - All KERNEL defines and routines * NOUSER - All USER defines and routines * NONLS - All NLS defines and routines * NOMB - MB_* and MessageBox() * NOMEMMGR - GMEM_*, LMEM_*, GHND, LHND, associated routines * NOMETAFILE - typedef METAFILEPICT * NOMINMAX - Macros min(a,b) and max(a,b) * NOMSG - typedef MSG and associated routines * NOOPENFILE - OpenFile(), OemToAnsi, AnsiToOem, and OF_* * NOSCROLL - SB_* and scrolling routines * NOSERVICE - All Service Controller routines, SERVICE_ equates, etc. * NOSOUND - Sound driver routines * NOTEXTMETRIC - typedef TEXTMETRIC and associated routines * NOWH - SetWindowsHook and WH_* * NOWINOFFSETS - GWL_*, GCL_*, associated routines * NOCOMM - COMM driver routines * NOKANJI - Kanji support stuff. * NOHELP - Help engine interface. * NOPROFILER - Profiler interface. * NODEFERWINDOWPOS - DeferWindowPos routines * NOMCX - Modem Configuration Extensions */ 接下来的所有内容都是用来定义另外一些需要包含的头文件的,当然也包含了其他信息。 _MSC_VER这个宏定义了编译器的版本,相关信息如下: C Compiler version 6.0 600C/C++ compiler version 7.0 700
Visual C++, Windows, version 1.0 800
Visual C++, 32-bit, version 1.0 800
Visual C++, Windows, version 2.0 900
Visual C++, 32-bit, version 2.x 900
Visual C++, 32-bit, version 4.0 1000
Visual C++, 32-bit, version 5.0 1100
Visual C++, 32-bit, version 6.0 1200 这个宏是必须定义的 ,#pragma once指示编译器在编译过程中最多包含一次该头文件。 有意思的是下面一大段注释,说明了当定义了_MSC_VER这个宏,并且它的版本号>=1020,那么接下来所列出的一系列标志是不能够被定义的。 #if defined(RC_INVOKED) && !defined(NOWINRES) #include <winresrc.h> #else #if defined(RC_INVOKED) /* Turn off a bunch of stuff to ensure that RC files compile OK. */ #define NOATOM #define NOGDI #define NOGDICAPMASKS #define NOMETAFILE #define NOMINMAX #define NOMSG #define NOOPENFILE #define NORASTEROPS #define NOSCROLL #define NOSOUND #define NOSYSMETRICS #define NOTEXTMETRIC #define NOWH #define NOCOMM #define NOKANJI #define NOCRYPT #define NOMCX #endif #if !defined(_68K_) && !defined(_MPPC_) && !defined(_PPC_) && !defined(_ALPHA_) && !defined(_MIPS_) && !defined(_X86_) && defined(_M_IX86) #define _X86_ #endif #if !defined(_68K_) && !defined(_MPPC_) && !defined(_PPC_) && !defined(_ALPHA_) && !defined(_X86_) && !defined(_MIPS_) && defined(_M_MRX000) #define _MIPS_ #endif #if !defined(_68K_) && !defined(_MPPC_) && !defined(_PPC_) && !defined(_ALPHA_) && !defined(_X86_) && !defined(_MIPS_) && defined(_M_ALPHA) #define _ALPHA_ #endif #if !defined(_68K_) && !defined(_MPPC_) && !defined(_PPC_) && !defined(_ALPHA_) && !defined(_X86_) && !defined(_MIPS_) && defined(_M_PPC) #define _PPC_ #endif #if !defined(_68K_) && !defined(_MPPC_) && !defined(_PPC_) && !defined(_ALPHA_) && !defined(_X86_) && !defined(_MIPS_) && defined(_M_M68K) #define _68K_ #endif #if !defined(_68K_) && !defined(_MPPC_) && !defined(_PPC_) && !defined(_ALPHA_) && !defined(_X86_) && !defined(_MIPS_) && defined(_M_MPPC) #define _MPPC_ #endif #ifndef _MAC #if defined(_68K_) || defined(_MPPC_) #define _MAC #endif #endif #ifndef RC_INVOKED #if ( _MSC_VER >= 800 ) #pragma warning(disable:4001) #pragma warning(disable:4201) #pragma warning(disable:4214) #pragma warning(disable:4514) #endif #include <excpt.h> #include <stdarg.h> #endif /* RC_INVOKED */ 这一段有些长,但因为是一体的,所以放在一起分析是必然的。 宏RC_INVOKED似乎是这一段的核心,就从它开始。RC(资源编译器)定义了这个宏,使得你能够有选择地编译资源头文件的不同部分。为什么会有这种需要呢?当你考虑选择用C编译器还是用RC编译器来编译的资源头文件的时候,你就必须直面这个问题。因为RC所支持的定义语句只是C编译器的一个子集,因此,如果选择用RC来编译,那么就该注意不能用RC所不支持的语法来编写资源头文件。 NO_WINRES这个宏实在winresrc.h这个头文件里定义的,而winresrc.h这个文件里的内容实在是很少: #ifndef _WINRESRC_ #define _WINRESRC_ #include <winuser.rh> #include <commctrl.rh> #include <dde.rh> #include <winnt.rh> #include <dlgs.h> #include <winver.h> #endif 呵呵,看过之后,不难理解了。 接下来的一些定义 #if !defined(_68K_) && !defined(_MPPC_) ……是和平台相关的,由于大多数人(包括我在内)可能只会在一种硬件平台下如X86,所以这些定义大可不必太过计较的。 如果没有定义RC_INVOKED并且_MSC_VER(编译器的版本号)>=800的话就禁用几个与编译器版本相关的几个警告信息。如果没有定义RC_INVOKED这个宏,还要包含excpt.h和stdarg.h这两个头文件(excpt .h是一个未文档化的头文件,包含了关于SEH(结构化异常处理)的一些定义;stdarg.h为具有多个参数的函数定义了ANSI类型的宏),那么,在这种情况下为什么要包含这两个头文件呢?Platform SDK中是这样解释的:“RC不支持一些ANSI C型的预定义宏(如__DATE__, __FILE__, __LINE__, __STDC__, __TIME__, __TIMESTAMP__等)”,而excpt.h和stdarg.h这两个头文件确实定义了一些ANSI C型的宏,因此,为避免编译出错,只有在不使用RC的情况下(也就是不定义RC_INVOKED这个宏)才包含这些头文件。 #include <windef.h> #include <winbase.h> #include <wingdi.h> #include <winuser.h> 这几个是windows.h中包含的几个最重要的和最基本的头文件: windef.h——基本型态定义 winbase.h——Kernel函数 wingdi.h——图形设备接口函数 winuser.h——使用者接口函数 #ifdef _MAC DECLARE_HANDLE(HKEY); typedef HKEY *PHKEY; #endif
本文标签: Windows
版权声明:本文标题:windows.h分析 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1729089207a1185948.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论