我們的生活充滿了抽象。作為開發人員,如果我們不瞭解抽象的定義就去使用它,則通常會讓我們 陷入困境。抽象有時是零散的,且無法完全隱藏基本複雜性。別誤解我的意思,其實抽象是很有用的。 它們能為使用者和開發人員提供協助,而如果您深入研究您通常依賴的抽象來瞭解其運作方式,則會讓您 受益匪淺。此外,承認這一現實的庫通常比不承認這一現實的庫更為成功,部分是因為前者允許您在必 要時繞過抽象。
Windows 運行時 (WinRT) 就是一個這樣的抽象,在本月的專欄中,我將通過研究 WinRT 核心應用 程式模型來說明此抽象。此抽象以 CoreWindow 類為中心,並且每個“新型”Windows 市集和 Windows Phone 應用中都包含一個該類的執行個體。但是很少有開發人員知道該執行個體的存在,更不必說該實 例的運作方式了。這可能是對抽象成功的最好證明。
自 Windows 8 API 最初於 2011 年發布以來,已有大量關於通過 Windows 運行時提供抽象的各種 語言投射的報道和文章。但是,瞭解 Windows 運行時的最佳方式是避開各種語言投射(包括 C++/CX) 並使用標準 C++ 和經典 COM。只有 C++ 能讓您透過表象看到實際情況(從技術上說,C 也可以,但會 造成一些不必要的麻煩)。您仍可以選擇使用這樣或那樣的語言投射(但願是 C++/CX),因為您可能 應該這樣做,但您至少要更清楚地瞭解實際情況。
若要開始此操作,請開啟 Visual Studio 2012 並為 Windows 市集或 Windows Phone 應用創 建新的 Visual C++ 項目。隨便您使用哪種模板。載入後,轉到方案總管並刪除一切不重要 的內容。如果您選取了基於 XAML 的模板,則刪除所有 XAML 檔案。您也可以刪除所有 C++ 源檔案。 您可能需要保留先行編譯頭,但請務必刪除其中包含的所有內容。應保留的內容是部署應用、映像、認證 和 XML 清單所需的包資產。
接下來,開啟項目的屬性頁面並選擇編譯器屬性 - 樹中左側的 C/C++ 節點。找到稱作“使用 Windows 運行時擴充”的 /ZW 編譯器選項對應的行,並選擇“否”以禁用 C++/CX 語言擴充。這樣, 您就可以確保不會有比標準 C++ 編譯器更神秘的東西了。到了這一步,您也可以將編譯器的警告層級 設定為 /W4。
如果您嘗試編譯項目,則應會收到一個連結器錯誤,告知您找不到項目的 WinMain 進入點函數。將 新的 C++ 源檔案添加到項目,您要做的第一件事是添加缺少的 WinMain 函數:
int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int){}
如您所見,這是用於基於 C 執行階段程式庫 (CRT) 的 Windows 應用程式的舊 WinMain 函數。 當然,HINSTANCE 和 PWSTR 不是基本 C++ 類型,因此您將需要包含 Windows 頭:
#include <windows.h>
如果您保留了項目的先行編譯頭,則可在此處包含它。 此外,由 於我還將使用 Windows 運行時 C++ 範本庫 (WRL) 中的 ComPtr,因此現在最好是包含它:
#include <wrl.h>
在接下來的幾個專欄中,我將更詳細地介紹 WRL。 現在,我將 利用 ComPtr 類模板來維護 COM 介面指標。 在這一階段中,您只需記住 WRL ComPtr 只是一個 COM 介面智能指標。 儘管它提供了某些特定於 Windows 運行時的功能,但我不會在本月的專欄中探討這些 功能。 您可以很輕鬆地改用Active Template Library (ATL) CComPtr 或您選擇的任何 COM 介面智能指標。 WRL ComPtr 是在 Microsoft::WRL 命名空間中定義的:
using namespace Microsoft::WRL;
我還將使用 ASSERT 宏和 HR 函數來進行錯誤處理。 由於我之前已討論這些,因此在這 裡不再講述。 如果您對這些步驟不確定,請參閱我在 2013 年 5 月撰寫的專欄“Direct2D 1.1 簡介 ”(msdn.microsoft.com/magazine/dn198239)。
最後,若要使用本專欄中提到的任何 WinRT 函 數,您需要為連結器提供 .lib 檔案的名稱:
#pragma comment(lib, "RuntimeObject.lib")