參考
http://blog.csdn.net/fengningning/article/details/2306650?locationNum=1&fps=1
windows.h解構web
剛開頭的一段註釋是對該頭文件的描述: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」,就不用多作解釋了。markdown
#ifndef _WINDOWS_
#define _WINDOWS_
這種宏定義應該是最多見的了,一個做用是防止重複包含。app
#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文檔中的相關說明以下:svg
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.com/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定義的一系列信息做爲提示。ui
#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,那麼接下來所列出的一系列標誌是不可以被定義的。this
#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這個文件裏的內容實在是不多:spa
#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.h中的函數:
參考windows.h的函數
1.得到當前工做目錄
char* _getcwd( char *buffer, int maxlen );
// 功 能 : 得到當前工做目錄.
// 頭文件 : #include <direct.h>
// 返回值 : 成功返回指向buffer的pointer
// 失敗返回NULL,且設置errno爲如下三個值之一:
// ENODEV 無該設備
// ENOMEM 內存不夠
// ERANGE 結果超出範圍
// 注 意 : 當第一個參數爲 NULL 時, 第二個參數 maxlen 長度設置無效,且函數
// 使用 malloc 分配足夠內存, 須要將函數返回值傳遞給 free() 函數來
// 釋放內存. 當第一個參數不爲 NULL 時,maxlen 指定長度不夠函數返回
// 錯,設置errno爲ERANGE
2.修改當前工做目錄
int _chdir( const char *dirname );
// 功 能 : 更改當前工做目錄.
// 頭文件 : #include <direct.h>
// 返回值 : 成功返回0
// 失敗返回-1,且設置errno以下:
// ENOENT 該路徑不存在
3.文件遍歷(查找)
long _findfirst( char *filespec, struct _finddata_t *fileinfo );
// 功 能 : 提供與filespec指定入口泛式匹配的第一個文件.一般後繼用_findnext函
// 數後續使用來完成某泛式下的文件遍歷.
// 頭文件 : #include <io.h>
// 參 數 : filespec - 目標文件規範,能夠包含通配符
// fileinfo - 文件信息buffer
// 返回值 : 成功返回惟一的搜索句柄
// 出錯返回-1,且設置errno爲以下值:
// ENOENT 該泛式沒法匹配
// EINVAL 無效文件名
// 注 意 : _finddata_t 說明
struct _finddata_t
{
unsigned attrib;
time_t time_create;
time_t time_access;
time_t time_write;
_fsize_t size;
char name[_MAX_FNAME];
};
// 其中 :
// unsigned atrrib : 文件屬性的存儲位置。它存儲一個unsigned單元,用於表示文件的
// 屬性。文件屬性是用位表示的,主要有如下一些:_A_ARCH(存檔)、
// _A_HIDDEN(隱藏)、_A_NORMAL(正常)、_A_RDONLY(只讀)、
// _A_SUBDIR(文件夾)、_A_SYSTEM(系統)。這些都是在<io.h>中
// 定義的宏,能夠直接使用,而自己的意義實際上是一個無符號整型
// (只不過這個整型應該是2的幾回冪,從而保證只有一位爲1,而其餘
// 位爲0)。既然是位表示,那麼當一個文件有多個屬性時,它每每是
// 經過位或的方式,來獲得幾個屬性的綜合。例如只讀+隱藏+系統屬性,
// 應該爲:_A_HIDDEN | _A_RDONLY |_A_SYSTEM 。
// time_t time_create:這裏的time_t是一個變量類型,用來存儲文件建立時間。
// time_t time_access: 文件最後一次被訪問的時間。
// time_t time_write : 文件最後一次被修改的時間。
// _fsize_t size : 文件的大小。這裏的_fsize_t應該能夠至關於unsigned整型,表示
// 文件的字節數。
// char name[_MAX_FNAME]:文件的文件名。這裏的_MAX_FNAME是一個常量宏,它在<stdlib.h>頭
// 文件中被定義,表示的是文件名的最大長度。
int _findnext( long handle, struct _finddata_t *fileinfo );
// 功 能 : 按照前面_findfirst中的泛式規則,查找下一個符合該泛式的文件,並以此爲依據
// 修改fileinfo中的值
// 頭文件 : #include <io.h>
// 參 數 : long handle - 搜索句柄(一般由緊靠其前的_findfirst()返回)
// fileinfo - 文件信息buffer
// 返回值 : 成功返回0
// 出錯返回-1,且設置errno爲以下值:
// ENOENT 沒有更多的符合該泛式的文件
int _findclose( long handle );
// 功 能 : 關閉搜尋句柄並釋放相應資源
// 頭文件 : #include <io.h>
// 參 數 : long handle - 搜索句柄(一般由緊靠其前的_findfirst()返回)
// 返回值 : 成功返回0
// 出錯返回-1,且設置errno爲以下值:
// ENOENT 沒有更多的符合該泛式的文件
4.建立目錄
int _mkdir( const char *dirname );
// 功 能 : 建立一個新目錄,目錄名爲dirname.
// 頭文件 : #include <direct.h>
// 返回值 : 成功返回0
// 失敗返回-1,且設置errno爲如下三個值之一:
// EACCESS 權限不容許
// EEXIST 該目錄已存在
// ENOENT 無該文件或目錄
5.刪除目錄
int _rmdir( const char *dirname );
// 功 能 : 刪除名爲dirname的目錄.
// 頭文件 : #include <direct.h>
// 返回值 : 成功返回0
// 失敗返回-1,且設置errno爲如下三個值之一:
// EACCESS : 權限不容許
// ENOTEMPTY : dirname不是文件夾;或者該文件夾不空;或
// 者dirname爲當前工做文件夾;或者dirname
// 爲當根文件夾;
// ENOENT : 無該文件或目錄
6.其餘操做
int _access( const char *path, int mode );
// 功 能 : 測定文件/目錄存取權限.
// 頭文件 : #include <io.h>
// 參 數 : path - 文件或者目錄
// mode - 權限設定,其值以下:
// 00 Existence only
// 02 Write permission
// 04 Read permission
// 06 Read and write permission
int _chdrive( int drive );
// 功 能 : 更改當前工做驅動器.
// 頭文件 : #include <direct.h>
// 返回值 : 成功返回0
// 失敗返回-1
// 注 釋 : 參數說明
// drive =1 : A盤
// drive =2 : B盤
// drive =3 : C盤 ...
char* _getdcwd( int drive, char *buffer, int maxlen );
// 功 能 : 得到指定驅動器的當前工做路徑.
// 頭文件 : #include <direct.h>
// 返回值 : 成功返回指向buffer的pointer
// 失敗返回NULL,且設置errno爲如下三個值之一:
// ENODEV 無該設備
// ENOMEM 內存不夠
// ERANGE 結果超出範圍
// 注 意 : 當第一個參數爲 NULL 時,該函數設置errno爲ERANGE