共用方式為


開始使用 C++/WinRT

這很重要

如需設定 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.hmain.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 命名空間標頭檔案,如上所述。 對應 標頭 是與類型命名空間同名的標頭。 例如,若要使用 Windows::Foundation::Collections::PropertySet 執行階段類別的 C++/WinRT 映射,請包含 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 程式代碼與 C++/CX 和/或 SDK 應用程式二進位介面 (ABI) 程式代碼(您正在從 移植, 或與其中一個或兩個模型互通),然後查看 C++/WinRT 與 C++/CX之間的 Interop 主題,從 C++/CX移至 C++/WinRT。 和 C++/WinRT 與 ABI之間的 Interop。

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 是一個由自 beginend 函式(或其常數、反向及常數反向變體)傳回的迭代器定義的範圍。 因此,您可以使用範圍型 語句或使用 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;

取得摘要的標題文字,作為 winrt::hstring 物件(詳情請參閱 C++/WinRT中的 字串處理)。 接著,會透過 c_str 函式輸出 hstring,這反映了搭配 C++ 標準程式庫的字串使用模式。

如您所見,C++/WinRT 鼓勵新式和類似類別的C++運算式,例如 syndicationItem.Title().Text()。 這是與傳統 COM 程式設計不同且更簡潔的程式設計樣式。 您不需要直接初始化 COM,也不需要使用 COM 指標。

您也不需要處理 HRESULT 傳回碼。 C++/WinRT 會將錯誤 HRESULT 轉換成例外,例如 winrt::hresult_error,以實現自然和現代的程式設計風格。 如需有關錯誤處理和程式碼範例的詳細資訊,請參閱 使用 C++/WinRT 的錯誤處理

修改 Windows 桌面應用程式專案以新增 C++/WinRT 支援

某些傳統型專案(例如 Visual Studio中的 WinUI 3 範本)內建C++/WinRT 支援。

但本節說明如何將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.hstdafx.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 架構互操作。 這些文件涵蓋上述所有案例。 開始的好地方是 XAML 控制件;系結至具有 C++/WinRT的C++/WinRT 屬性XAML 自定義(樣板化)控件。

以 C++/WinRT 撰寫的範例應用程式

請參閱 哪裡可以找到C++/WinRT 範例應用程式?

重要 API