admin管理员组

文章数量:1631188

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                                               600  
        C/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