這很重要
如需設定 Visual Studio 以進行 C++/WinRT 開發的資訊,包括安裝和使用 C++/WinRT Visual Studio 延伸模組 (VSIX) 和 NuGet 套件 (一起提供專案範本和組建支援),請參閱 Visual Studio 對 C++/WinRT 的支援。
若要加快使用 C++/WinRT的速度,本主題會根據 新的 Windows 控制台應用程式(C++/WinRT) 專案,逐步解說簡單的程式代碼範例。 本主題也會示範如何將 C++/WinRT 支援新增至 Windows 桌面應用程式專案。
備註
雖然我們建議您使用最新版本的 Visual Studio 和 Windows SDK 進行開發, 如果您使用 Visual Studio 2017(版本 15.8.0 或更新版本),並以 Windows SDK 版本 10.0.17134.0 為目標(Windows 10 版本 1803),則新建立的 C++/WinRT 專案可能無法編譯,並出現錯誤“錯誤 C3861: 'from_abi': 找不到識別碼“,而其他錯誤源自 base.h。 解決方案是以更新版本的 Windows SDK 為目標,或設定專案屬性 C/C++>語言>一致性模式:如果沒有/permissive- 出現在專案屬性中,C/C++>Language>命令行 下 其他選項, 然後刪除它)。
C++/WinRT 快速入門
建立新的 Windows 控制台應用程式 (C++/WinRT) 專案。
請使 pch.h
和 main.cpp
看起來像這樣。
// pch.h
#pragma once
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Web.Syndication.h>
#include <iostream>
// main.cpp
#include "pch.h"
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Web::Syndication;
int main()
{
winrt::init_apartment();
Uri rssFeedUri{ L"https://blogs.windows.com/feed" };
SyndicationClient syndicationClient;
syndicationClient.SetRequestHeader(L"User-Agent", L"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
SyndicationFeed syndicationFeed = syndicationClient.RetrieveFeedAsync(rssFeedUri).get();
for (const SyndicationItem syndicationItem : syndicationFeed.Items())
{
winrt::hstring titleAsHstring = syndicationItem.Title().Text();
// A workaround to remove the trademark symbol from the title string, because it causes issues in this case.
std::wstring titleAsStdWstring{ titleAsHstring.c_str() };
titleAsStdWstring.erase(remove(titleAsStdWstring.begin(), titleAsStdWstring.end(), L'™'), titleAsStdWstring.end());
titleAsHstring = titleAsStdWstring;
std::wcout << titleAsHstring.c_str() << std::endl;
}
}
讓我們逐一取得上述簡短程式代碼範例,並說明每個部分會發生什麼事。
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Web.Syndication.h>
使用預設項目設定時,包含的標頭來自 Windows SDK,位於資料夾內 %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt
。 Visual Studio 在其 IncludePath 巨集中包含該路徑。 不過,您的專案不會嚴格依賴於 Windows SDK,因為您的專案會透過 cppwinrt.exe
工具在專案的 $(GeneratedFilesDir) 資料夾中生成相同的標頭檔案。 如果在別處找不到,或如果您變更項目設定,則會從該資料夾載入它們。
標頭包含投影至 C++/WinRT 的 Windows API。 換句話說,針對每個 Windows 類型,C++/WinRT 會定義 C++ 友好的對等類型(稱為 投影類型)。 投射類型與 Windows 類型具有相同的完整限定名稱,但它會放在 C++ winrt 命名空間中。 將這些包含放在先行編譯標頭中可減少累加建置時間。
這很重要
每當您想要使用來自 Windows 命名空間的類別時,必須 #include
相應的 C++/WinRT Windows 命名空間標頭檔案,如上所述。 對應 標頭 winrt/Windows.Foundation.Collections.h
標頭檔。
C++/WinRT 投影標頭通常會自動包含相關的命名空間頭檔。 例如, winrt/Windows.Foundation.Collections.h
包括 winrt/Windows.Foundation.h
。 但是您不應該依賴此行為,因為它是一個會隨時間變化的實作細節。 您必須明確包含您需要的任何標題。
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Web::Syndication;
using namespace
指令是選擇性的,但很方便。 上述針對此類指令顯示的模式(允許在 winrt 命名空間中任何項目進行非限定名稱查閱)適用於當您開始一個新專案時,並且 C++/WinRT 是您在該專案中唯一使用的語言投影。 另一方面,如果您要混合C++/WinRT 程式代碼與
winrt::init_apartment();
winrt::init_apartment呼叫会初始化 Windows 運行時間中的線程;根據預設,在多線程 Apartment 中。 呼叫也會初始化 COM。
Uri rssFeedUri{ L"https://blogs.windows.com/feed" };
SyndicationClient syndicationClient;
堆疊配置兩個物件:它們代表 Windows 部落格的 URI 和新聞訂閱用戶端。 我們會使用簡單的寬字串字面值來建構 uri(如需更多字串使用方式,請參閱 C++/WinRT 中的字串處理)。
SyndicationFeed syndicationFeed = syndicationClient.RetrieveFeedAsync(rssFeedUri).get();
SyndicationClient::RetrieveFeedAsync 是異步 Windows 運行時間函式的範例。 程式代碼範例會從 RetrieveFeedAsync接收異步操作物件,並呼叫 在該物件上取得,以封鎖呼叫線程並等候結果(在此案例中為新聞訂閱摘要)。 如需有關並行和非阻塞技術的詳細資訊,請參閱 C++/WinRT 的併發性和非同步操作 及。
for (const SyndicationItem syndicationItem : syndicationFeed.Items()) { ... }
SyndicationFeed.Items 是一個由自 begin 和 end 函式(或其常數、反向及常數反向變體)傳回的迭代器定義的範圍。 因此,您可以使用範圍型 語句或使用 for
範本函式來列舉 items。 每當您遍歷如下所示的 Windows 執行階段集合時,都必須 #include <winrt/Windows.Foundation.Collections.h>
。
winrt::hstring titleAsHstring = syndicationItem.Title().Text();
// Omitted: there's a little bit of extra work here to remove the trademark symbol from the title text.
std::wcout << titleAsHstring.c_str() << std::endl;
取得摘要的標題文字,作為
如您所見,C++/WinRT 鼓勵新式和類似類別的C++運算式,例如 syndicationItem.Title().Text()
。 這是與傳統 COM 程式設計不同且更簡潔的程式設計樣式。 您不需要直接初始化 COM,也不需要使用 COM 指標。
您也不需要處理 HRESULT 傳回碼。 C++/WinRT 會將錯誤 HRESULT 轉換成例外,例如 winrt::hresult_error,以實現自然和現代的程式設計風格。 如需有關錯誤處理和程式碼範例的詳細資訊,請參閱 使用 C++/WinRT 的錯誤處理。
修改 Windows 桌面應用程式專案以新增 C++/WinRT 支援
某些傳統型專案(例如 Visual Studio中的
但本節說明如何將C++/WinRT 支援新增至您可能擁有的任何 Windows Desktop 應用程式專案。 如果您沒有現有的 Windows 傳統型應用程式專案,您可以先建立一個專案來遵循這些步驟。 例如,開啟 Visual Studio 並建立 Visual C++>Windows Desktop>Windows Desktop 應用程式 專案。
您可以選擇性地安裝 C++/WinRT Visual Studio 擴充功能 (VSIX) 和 NuGet 套件。 如需詳細資訊,請參閱 Visual Studio 對 C++/WinRT 的支援。
設定項目屬性
請移至項目屬性 ,然後在 [一般>Windows SDK 版本] 中,選取 [所有組態 ] 和 [所有平台 ]。 請確定 Windows SDK 版本 設定為 10.0.17134.0 (Windows 10 版本 1803) 或更新版本。
確認您未受到「為什麼我的新專案無法編譯?」問題的影響。
由於 C++/WinRT 使用來自 C++17 標準的功能,因此請將 project 屬性 C/C++>Language>C++ Language Standard 設定為 ISO C++17 Standard (/std:c++17)。
預編譯標頭
預設專案範本會為您建立先行編譯標頭,名為 framework.h
或 stdafx.h
。 重新命名為 pch.h
。 如果您有 stdafx.cpp
檔案,請將該檔案重新命名為 pch.cpp
。 將專案屬性 C/C++>預編譯標頭>預編譯標頭 設定為 Create (/Yc),並將 預編譯標頭檔案 設定為 pch.h。
使用 #include "framework.h"
尋找並取代所有 #include "stdafx.h"
(或 #include "pch.h"
)。
在 pch.h
中,包含 winrt/base.h
。
// pch.h
...
#include <winrt/base.h>
連結
C++/WinRT 語言投影依賴一些特定的 Windows 執行階段自由(非成員)函式,以及進入點,這些都需要鏈接到 WindowsApp.lib 框架庫。 本節說明滿足連結器三種方式。
第一個選項是將所有 C++/WinRT MSBuild 屬性和目標新增至你的 Visual Studio 專案。 若要這樣做,請將 Microsoft.Windows.CppWinRT NuGet 套件 安裝到您的專案中。 在 Visual Studio 中開啟專案,單擊 [專案>管理 NuGet 套件...>流覽],在搜尋方塊中輸入或貼上 Microsoft.Windows.CppWinRT,選取搜尋結果中的專案,然後按兩下 [安裝],以安裝該專案的套件。
您也可以使用專案連結設定以明確地連結 WindowsApp.lib
。 或者,您可以在原始程式碼中執行此動作(例如,在 pch.h
中),如下所示。
#pragma comment(lib, "windowsapp")
您現在可以編譯和連結,並將C++/WinRT 程式代碼新增至專案(例如,類似上述 A C++/WinRT 快速入門 一節所示的程式代碼)。
C++/WinRT 的三個主要案例
當您使用並熟悉 C++/WinRT,並閱讀此處的其餘文件時,您可能會注意到有三個主要情境,如下列各節所述。
取用 Windows API 和類型
換句話說,使用,或 呼叫 API。 例如,透過 API 呼叫來使用藍牙通訊、串流及播放影片、整合 Windows 殼層等功能。 C++/WinRT 完全且不妥協地支援此案例類別。 如需詳細資訊,請參閱 使用 C++/WinRT取用 API。
撰寫 Windows API 和類型
換句話說,產生 API 和類型。 例如,產生上一節所述的 API 種類;或圖形 API;記憶體和檔案系統 API;網路 API 等等。 如需詳細資訊,請參閱使用 C++/WinRT撰寫 API
使用 C++/WinRT 撰寫 API 比取用 API 複雜一些,因為您必須先使用 IDL 來定義 API 的結構,然後才能實作它。 有一個逐步解說,在 XAML 控件中執行此動作;繫結至 C++/WinRT 屬性。
XAML 應用程式
此案例是關於在 XAML UI 架構上建置應用程式和控制件。 在 XAML 應用程式中工作相當於使用和創作的結合。 但是,由於 XAML 是目前 Windows 上的主要 UI 架構,而且它對 Windows 運行時間的影響是成正比的,因此它應該有它自己的案例類別。
請注意,XAML 最適合可以運用反射的程式設計語言。 在 C++/WinRT 中,您有時必須執行一些額外的工作,才能與 XAML 架構互操作。 這些文件涵蓋上述所有案例。 開始的好地方是
以 C++/WinRT 撰寫的範例應用程式
重要 API
- SyndicationClient 的 RetrieveFeedAsync 方法
- SyndicationFeed.Items 屬性
- winrt::hstring 結構
- winrt::hresult-error 結構體