Winapi

**Windows 應用程式介面**（Windows API），或俗稱的 **WinAPI**，是微軟 Windows 作業系統中的一套核心應用程式介面。Windows API 這一叫法實際上是多個 Windows 平台上相似介面的統稱，這些介面也擁有各自的名字，如 Win32 API。幾乎所有的 Windows 應用程式都在與 Windows API 進行互動。

Windows API 將與 Windows 系統有關的複雜操作封裝在簡單的函式當中，編譯成動態連結媒體櫃，再隨 Windows 一同發布。開發者可以簡單地藉助這些函式來完成複雜的操作，有效降低了編寫 Windows 程式的難度。

Windows 有一個軟體開發套件（SDK, software development kit）提供相應的文件和工具，以使程式設計師開發使用 Windows API 的軟體和利用 Windows 技術。

C 是 Windows API（Win32）的主要程式語言，在該 API 的文件中所公開的函式和資料結構均以該語言進行了描述。但是，如果某種程式語言能夠處理（明確定義的）低階資料結構，並能按照規定進行呼叫與回呼，那麼其編譯器或組譯器也可以呼叫 Windows API。類似地，在歷史上 Windows API 也由多種語言進行了開發。儘管 C 不是物件導向的程式語言，但 Windows API 和 Windows 都具有物件導向的特性；同時，也有許多物件導向語言的包裝類和擴充（如微軟基礎類別館 MFC、視覺化組件媒體櫃 VCL、GDI + 等）使這種物件導向的結構更加清晰。例如，Windows 8 提供的 Windows API 和 WinRT API 就是用 C++ 實現的，並且在設計上也是物件導向的。

## 概述

Windows API 所提供的功能可以歸為八類：

#### 基礎服務（Base Services）

提供了對 Windows 系統可用的基礎資源的存取介面，包括檔案系統（file system）、外部裝置（device）、處理程序（process）、執行緒（thread）和錯誤處理（error handling）等。這些功能介面在 16 位元 Windows 中位於 kernel.exe、krnl286.exe 或 krnl386.exe 中；在 32 位元和 64 位元 Windows 下位於 kernel32.dll 和 KernelBase.dll 中。這些檔案在所有 Windows 的 `\Windows\System32` 目錄中都可以被找到。

#### 進階服務（Advanced Services）

提供了對核心以外功能的存取，包括登錄檔（Windows registry）、關閉 / 重新啟動系統（shutdown/restart）、服務（Windows Service）、使用者帳戶（user accounts) 等。這些函式位於 32 位元 Windows 上的 `advapi32.dll` 和 `advapires32.dll` 中。

#### 圖形裝置介面（GDI）

提供了將圖形內容輸出到監視器、印表機和其他外部輸出裝置的功能。它位於 16 位元 Windows 下的 gdi.exe，以及 32 位元 Windows 下的 gdi32.dll 中。

#### 圖形化使用者介面（GUI）

提供了建立和管理視窗和大多數基本控制項（control）、接收滑鼠和鍵盤輸入，以及其他與 GUI 有關的功能。這些呼叫介面位於：16 位元 Windows 下的 user.exe，以及 32 位元 Windows 下的 user32.dll。從 Windows XP 版本之後，基本控制項和通用對話方塊控制項（Common Control Library）的呼叫介面放在 comctl32.dll 中。

#### 通用對話方塊連結媒體櫃（Common Dialog Box Library）

為應用程式提供標準對話方塊（如打開／儲存檔案對話方塊、顏色對話方塊和字型對話方塊等）。這個連結媒體櫃位於：16 位元 Windows 下的 commdlg.dll 中，以及 32 位元 Windows 下的 comdlg32.dll 中。它被歸類為 User Interface API 之下。

#### 通用控制項連結媒體櫃（Common Control Library）

為應用程式提供介面來存取作業系統提供的一些進階控制項。比如像：狀態列（status bar）、進度條（progress bars）、工具列（toolbar）和標籤（tab）。這個連結媒體櫃位於：16 位元 Windows 下的 commctrl.dll 中，以及 32 位元 Windows 下 comctl32.dll 中。它被歸類為 User Interface API 之下。使用 API 函式 InitCommonControls 或 InitCommonControlsEx 初始化（即註冊）相應的視窗類。InitCommonControlsEx 實際註冊指定的通用控制項的視窗類。注意 ICC\_WIN95\_CLASSES 代表 12 個控制項類的集合。InitCommonControls 是個空函式，但會使應用程式載入 comctl32.dll；在 comctl32.dll 載入到處理程序時會在 DLL 的入口點呼叫 InitCommonControlsEx 註冊 ICC\_WIN95\_CLASSES 控制項類。

#### Windows Shell

作為 Windows API 的組成部份，不僅允許應用程式存取 Windows Shell 提供的功能，還對之有所改進和增強。它位於 16 位元 Windows 下的 shell.dll 中，以及 32 位元 Windows 下的 shell32.dll 中（Windows 95 則在 shlwapi.dll 中）。它被歸類為 User Interface API 之下。

#### 網路服務（Network Services）

為存取作業系統提供的多種網路功能提供介面。它包括 NetBIOS、Winsock、NetDDE 及遠程過程調用（RPC）等。

### Web 相關 API

Internet Explorer 網頁瀏覽器還公開了許多經常被應用程式呼叫的 API，因此通常其也被視為是 Windows API 的一部份。IE 從 Windows 95 OSR2 起就包含在了 Windows 系統中，並從 Windows 98 起開始為應用程式提供 Web 相關服務。具體來說，它提供：

* 可嵌入的網頁瀏覽器控制項（以及 Trident / MSHTML 引擎），位於 shdocvw.dll 和 mshtml.dll 之中。
* urlmon.dll 中的命名服務（URL moniters service），利用 COM 物件為應用程式提供解析 URL 服務。應用程式也可以為其他程式提供自己的 URL 處理程式。
* WinInet IE 的網路層，支援 HTTP 和 HTTPS 等協定。
* 一個支援多種語言文字的連結媒體櫃（mlang.dll）。
* DirectX Transforms，一組圖像過濾組件。
* XML 支援（MSXML 組件）。

和 Windows 的郵件功能相關的 API，例如位址本和郵件 API，在 Windows 7 取消郵件功能之後也隨之從 Windows API 中去除。由於 Windows Mail 在 Windows Vista 上取代了 Outlook Express，對應的 API 也隨之變化。

### 多媒體相關 API

經典的 Windows 多媒體 API 位於 winmm.dll 中，包含了播放音訊、MIDI 通訊、遊戲手柄及其他促進多媒體體驗的功能。該 API 源自 Windows 3.x。

自從 Windows 95 OSR2 以來，Microsoft 把 DirectX API 作為 Windows 安裝的一部份。DirectX 提供一組鬆散相關的多媒體和遊戲服務，包括：

* Direct3D 可以作為 OpenGL 的替代，來存取 3D 加速硬體。
* DirectDraw 提供硬體加速 2D framebuffer（影格緩衝）存取介面。自 DirectX 9 以來，相比 Direct3D 更傾向於後者，因為 Direct3D 提供更全面的高效能圖形功能（畢竟 2D 彩現只是 3D 彩現的（不嚴格）子集）。已被 Direct2D 替代。
* DirectSound 提供底層次的硬體加速音效卡存取。被 XAudio 替代。
* DirectInput 用來與輸入裝置（搖桿和 gamepad）進行通信。已被 DirectX 9 中引入的 XInput 所替代。
* DirectPlay 提供一個多人遊戲的架構（multiplayer gaming infrastructure）。它已經被 DirectX 9 所替代，Microsoft 不建議用它開發遊戲。
* DirectShow 可以建立和執行通用的多媒體管道（generic multimedia pipelines）。它可以與 GStreamer 框架相媲美，並且經常被用來彩現遊戲影片和建立媒體播放器（Windows Media Player 及諸如 FFDShow 之類的編解碼器正是基於此；但在 Windows Vista 及更高版本中，DirectShow 被 Media Foundation 替代）。不建議用 DirectShow 開發遊戲。
* DirectMusic 提供類似 MIDI 的功能。與 DirectSound 一起被 XAudio 替代。

Microsoft 還提供了多個用於媒體編碼和播放的 API：

* DirectShow，用於構建和執行通用的媒體管道。它類似於 GStreamer 框架，常用於彩現遊戲內的影片和構建媒體播放器（著名的 Windows Media Player 即基於它）。如今 DirectShow 已不再被推薦用於開發。
* Media Foundation，一種較新的數位媒體 API，旨在取代 DirectShow。

### 程式通信 API

Windows API 最重要功能即為此：處理作業系統和應用程式之間的互動。對於不同的 Windows 應用程式之間的通信，Microsoft 發展了一系列的技術並開發了最主要的 Windows API。這些技術從動態資料交換（DDE）開始，隨後被物件連結和嵌入（OLE）取代，再被組件物件模型（COM）、自動化物件、ActiveX 控制項和.NET 框架取代。不過，這些技術之間區別並不總是十分明顯，並且有很多重疊之處。

這些技術的多樣性基本上是對軟體開發的不同方面進行細分的結果。自動化特別涉及了匯出應用程式和組件的功能為 API，以便使其可以由其他應用程式而不是人類來進行控制。.NET 是一種自包含的通用方法和技術，用於開發各種使用即時編譯語言編寫的桌面和 Web 應用程式。

Windows.pas 是一個 Pascal/Delphi 單元，其中包含了 Windows 特定的 API 聲明。它在 Pascal 中的作用就像 C 中的 windows.h 一樣。

### 封裝媒體櫃

微軟利用許多更底層的 Windows API 函式，開發出許多封裝媒體櫃（wrapper），讓應用程式以更抽象的方式與 Windows API 進行互動。MFC（Microsoft Foundation Class Library）用 C++ 類來封裝 Windows API 的功能，因而允許用更為物件導向的方式與 API 進行互動。ATL（Active Template Library）是對 COM 的面向範本（template oriented）的封裝。WTL（Windows Template Library）作為 ATL 的增強，被用來作為 MFC 的輕型的替代物。

其他著名的封裝媒體櫃是 Borland 公司的產品，為了與 MFC 競爭而推出的 OWL（Object Windows Library）提供了類似的物件導向封裝。不久 Borland 又推出 VCL（Visual Component Library）來取而代之。

大多數的 Windows 程式框架（application framework）是對 Windows API 的封裝，因而.NET Framework、Java 以及其他在 Windows 下的程式語言，都是（或者包含）封裝媒體櫃。

## 歷史

Windows API 總會為程式設計師提供大量的構建不同 Windows 的底層結構，這有助於為 Windows 程式設計師開發應用程式提供大量的靈活性和功能。但是，它同樣使 Windows 套用程式要負責處理大量底層且有時是繁瑣的與圖形化使用者介面（GUI）相關的操作。

例如，初學 C 的程式設計師通常會把編寫簡單的「Hello world」作為他們的第一項任務。程式的工作部份僅僅是主程式中的一個 printf 行，在連結到標準 I/O 媒體櫃時也僅需要一個 include 行：

Windows 版本的工作部份仍然只有一行程式碼，但除此之外它需要很多很多行的額外開銷。

許多有關 Windows API 的暢銷書的作者查爾斯・佩佐德（Charles Petzold）曾經說過：

這些年來，Windows 作業系統已經今非昔比，而 Windows API 也隨之改變和成長並反映出這種變化。Windows API 的 Windows 1.0 版本只提供不到 450 個函式調用（Subroutine），而現在的版本提供上千個。然而，整體而言，Windows 介面保持了相當好的一致性，習慣於現在版本 Windows API 的程式設計師對古老的 Windows 1.0 程式也並不會陌生。

微軟特別強調維持軟體的向下相容性。為了實現此一目標，有時微軟甚至不惜支援使用了非官方乃至（編程上）非法的 API 的軟體。一位致力於 Windows API 的 Windows 開發者雷蒙德・陳（Raymond Chen）曾提及：

對 Windows API 來說，其歷史上最大的變化之一就是從 Win16（在 Windows 3.1 及更早的版本中提供）到 Win32（Windows NT 和 Windows 95 及更高版本）的過渡。雖然 Win32 早已在 Windows NT 3.1 中引入，並在 Windows 95 前就已允許使用，但直到 Windows 95 應用程式才開始廣泛移植到 Win32。為了簡化轉換的過程，在 Windows 95 中對 Microsoft 內外的開發人員 Windows 使用了一種複雜的 API thunk 方案來允許 32 位元程式碼呼叫到 16 位元程式碼（對大多數 Win16 API 有效），反之亦然。同樣的，64 位元的 Windows 也可以通過 WoW64 執行 32 位元的應用程式，而位於 Windows 目錄下的 SysWOW64 資料夾中包含了多個用於支援 32 位元應用程式的工具。

## 版本

幾乎每個版本的 Windows 都引入了其對 Windows API 的添加和修改，但是 API 的名稱在不同版本的 Windows 間保持了一致，並且僅當 Windows 主要的架構和平台都更改時 API 的名稱才會改變。Microsoft 最終將當時名叫 Win32 的 API 家族改名為 Windows API，並使其成為過去和未來 API 版本的統稱。

* **Win16** 是第一個 16 位元版本 Windows 的 API。它最早被簡單地叫做 Windows API，但後來為了與較新的 32 位元 API 區分，它被重新命名為了 Win16。Win16 API 的功能主要駐留在作業系統的核心檔案中，如 _kernel.exe_（或 _krnl286.exe_、_krnl386.exe_）、_user.exe_ 和 _gdi.exe_。值得一提的是，儘管這些檔案採用了 exe 的副檔名，它們本質上其實是動態連結媒體櫃。
* **Win32** 是 Windows 95 及後續版本的 32 位元 API。與 Win16 相同，這個 API 由在系統 DLL 中實現的函式組成。Win32 的核心檔案是 _kernel32.dll_、_user32.dll_ 和 _gdi32.dll_。Win32 最早在 Windows NT 中引入，而不是 Windows 95。Windows 95 中的 Win32 最早被稱為 Win32c，其中的「c」表示相容性（英語：compatibility）；這個名稱後來被微軟捨棄，轉而使用 Win32。
* **Win32s** 是 Windows 3.1x 系列的擴充，它為這些系統實現了 Win32 API 的一部份功能。其中的「s」表示子集（英語：subset）。
* **Win64** 是 64 位元 Windows 上的 Windows API 變體。此時應用程式的 32 位元和 64 位元版本可以從同一個程式碼媒體櫃進行編譯。在預設情況下，所有記憶體指標都是 64 位元的（LLP64 型），因此部份程式的原始碼必須被重寫以相容 64 位元指標演算法。
* **WinCE** 是 Windows CE 作業系統中的 Windows API。

## 其它實現

儘管微軟的 Windows API 實現有著作權保護，但被普遍認可的是，根據美國的法律先例，其他廠商仍然可以通過提供一致的 API 來類比 Windows，而不會侵犯著作權。

Wine 專案為類 Unix 平台提供了一個在 Linux 核心 API 與 Windows API 程式之間的 Win32 API 相容層。ReactOS 則更進一步，想要實現一個完整的 Windows 作業系統；它通過與 Wine 專案的密切合作來促進其程式碼的重用和相容。DosWin32 和 HX DOS-Extender 是另外兩個類比 Windows API 的專案，它們允許通過 DOS 命令列來執行簡單的 Windows 程式。Odin 是一個在 OS/2 平台上類比 Win32 的專案。

## 編譯器支援

為了開發使用 Windows API 的軟體，編譯器必須能處理和匯入微軟相關的 DLLs 或者 COM 物件。編譯器必須接受一種 C 或 C++ 方言，或者能夠處理揭示了內部 API 函式名稱的介面定義語言（Interface description language）檔案和標頭檔及生成的類型媒體櫃（Type Library）。概括而言，這些預備條件（編譯器、開發工具、媒體櫃和標頭檔）被統稱為 Microsoft Platform SDK。很長時間以來，包含了編譯器和開發工具的專利產品如 Microsoft Visual Studio 系列和 Borland 編譯器（儘管至少在 Windows 下，SDK 是可以從整個 IDE 環境中剝離出來單獨免費下載的，據 Microsoft Platform SDK Update），是僅有的能提供整套開發環境的選擇。如今 MinGW 和 Cygwin 也能提供一套這樣的開發環境 —— 是基於採用一種獨立標頭檔集合來保證能與微軟 DLL 連接的 GCC。LCC-Win32 是由 Jacob Navia 維護的一種「非商業用途免費」的 C 編譯器。Pellesc 是由 Pelle Orinius 維護的一種免費 C 編譯器。MASM32 是一個成熟的專案，它通過自製或由 SDK 平台轉換的標頭檔和媒體櫃，並利用 32 位元微軟組譯器來實現支援 Windows API。

微軟相關的編譯器支援也是例外處理（Structured Exception Handling）特性所需要的。這個體制有雙重目的：它提供了語言相關的例外處理賴以實現的基礎，同時也是核心藉以通知程式發生諸如解除一個非法指標的參照或堆疊溢位之類異常狀況的管道。甫一被引入 Windows 95 和 NT，微軟／Borland C++ 編譯器就有使用這種體制的能力，然而實際實現未被公開，而且必須經過反向工程方可用於 Wine 專案和免費編譯器。SEH 的執行機制是先把異常的控制代碼推入堆疊，繼而將它們添加到儲存於執行緒本機資源（即執行緒環境塊的首欄位）的一個連結串列里。事實上，每一個未有程式本身處理的異常，都將由會彈出常規 Windows 崩潰對話方塊的預設 backstop 處理器處理。

API 在 Visual Basic 中的實現範例（這個簡化的例子使得使用者可以讓命令按鈕在表單上四處移動）：

## 注釋

## 參考資料

1. Diomidis Spinellis。A critique of the Windows application programming interface （頁面存檔備份，存於網際網路檔案館）. _Computer Standards & Interfaces_, 20(1):1–8, November 1998. doi:10.1016/S0920-5489(98)00012-9。

## 外部連結

* Microsoft Developer Network Windows API development guide （頁面存檔備份，存於網際網路檔案館）
* The Old New Thing （頁面存檔備份，存於網際網路檔案館） Weblog by Microsoft developer Raymond Chen，who works on the Windows API and posts extensively about it.
* Localization in Win32 （頁面存檔備份，存於網際網路檔案館）
* pinvoke.net: the interop wiki! （頁面存檔備份，存於網際網路檔案館） PINVOKE.NET attempts to address the difficulty of calling Win32 or other unmanaged APIs in managed code (languages such as C# and VB .NET).
* Windows API Notes
* WinapiZone （頁面存檔備份，存於網際網路檔案館） Free tutorials and extensions for Winapi
* Stromcode's Win32/C++ tutorial （頁面存檔備份，存於網際網路檔案館） (formerly Glowdot) an extensive, 20-part tutorial.
* Catch22 Tutorials Well documented Win32 API tutorials for developing small, nifty, and efficient programs in Windows.
* theForger's Win32 API Tutorial
* Using Win32 API in Visual FoxPro （頁面存檔備份，存於網際網路檔案館） online reference