Начало работы с C++/WinRTGet started with C++/WinRT

В этой статье рассматривается простой пример кода на основе нового проекта консольного приложения для Windows (C++/WinRT) , который поможет вам начать работу с C++/WinRT.To get you up to speed with using C++/WinRT, this topic walks through a simple code example based on a new Windows Console Application (C++/WinRT) project. Здесь также показано, как добавить поддержку C++/WinRT в проект классического приложения для Windows.This topic also shows how to add C++/WinRT support to a Windows Desktop application project.

Примечание

Хотя мы рекомендуем выполнять разработку с последними версиями 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.While we recommend that you develop with the latest versions of Visual Studio and the Windows SDK, if you're using Visual Studio 2017 (version 15.8.0 or higher), and targeting the Windows SDK version 10.0.17134.0 (Windows 10, version 1803), then a newly created C++/WinRT project may fail to compile with the error "error C3861: 'from_abi': identifier not found", and with other errors originating in base.h. Следует разрабатывать проект с более поздней (лучше соответствующей) версией Windows SDK или задать свойство проекта C/C++ > Язык > Режим совместимости: Нет. (Кроме того, если параметр /permissive- отображается в свойстве проекта C/C++ > Язык > Командная строка в разделе Дополнительные параметры, удалите его).The solution is to either target a later (more conformant) version of the Windows SDK, or set project property C/C++ > Language > Conformance mode: No (also, if /permissive- appears in project property C/C++ > Language > Command Line under Additional Options, then delete it).

Краткое руководство по C++/WinRTA C++/WinRT quick-start

Примечание

Сведения об установке Visual Studio для разработки с использованием C++/WinRT, включая установку и использование расширения C++/WinRT для Visual Studio (VSIX) и пакета NuGet (которые вместе обеспечивают поддержку шаблона проекта и сборки), приведены в разделе Поддержка Visual Studio для C++/WinRT, XAML, расширения VSIX и пакета NuGet.For info about setting up Visual Studio for C++/WinRT development—including installing and using the C++/WinRT Visual Studio Extension (VSIX) and the NuGet package (which together provide project template and build support)—see Visual Studio support for C++/WinRT.

Создайте проект консольного приложения для Windows (C++/WinRT) .Create a new Windows Console Application (C++/WinRT) project.

Отредактируйте файлы pch.h и main.cpp следующим образом.Edit pch.h and main.cpp to look like this.

// 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;
    SyndicationFeed syndicationFeed = syndicationClient.RetrieveFeedAsync(rssFeedUri).get();
    for (const SyndicationItem syndicationItem : syndicationFeed.Items())
    {
        winrt::hstring titleAsHstring = syndicationItem.Title().Text();
        std::wcout << titleAsHstring.c_str() << std::endl;
    }
}

Подробно рассмотрим небольшой пример кода выше с объяснением того, что происходит в каждой части.Let's take the short code example above piece by piece, and explain what's going on in each part.

#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Web.Syndication.h>

В соответствии с параметрами проекта по умолчанию включенные заголовки берутся из пакета Windows SDK внутри папки %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt.With the default project settings, the included headers come from the Windows SDK, inside the folder%WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt. Visual Studio включает этот путь в своем макросе IncludePath.Visual Studio includes that path in its IncludePath macro. Строгой зависимости от пакета Windows SDK нет, потому что проект (с помощью средства cppwinrt.exe) создает те же самые заголовки в своей папке $(GeneratedFilesDir) .But there's no strict dependency on the Windows SDK, because your project (via the cppwinrt.exe tool) generates those same headers into your project's $(GeneratedFilesDir) folder. Они будут загружены из этой папки, если их невозможно найти в другом расположении или если вы измените параметры проекта.They'll be loaded from that folder if they can't be found elsewhere, or if you change your project settings.

Заголовки содержат API-интерфейсы Windows, проецируемые в C++/WinRT.The headers contain Windows APIs projected into C++/WinRT. Другими словами, для каждого типа Windows проекция C++/WinRT определяет эквивалентный тип для C++ (проецируемый тип).In other words, for each Windows type, C++/WinRT defines a C++-friendly equivalent (called the projected type). Проецируемый тип имеет то же полное доменное имя, что и тип в Windows, но он размещается в пространстве имен C++ winrt.A projected type has the same fully-qualified name as the Windows type, but it's placed in the C++ winrt namespace. Добавление этих инструкций include в предварительно скомпилированный заголовок сокращает время сборки.Putting these includes in your precompiled header reduces incremental build times.

Важно!

Каждый раз, когда вы хотите использовать тип из пространств имен Windows, необходимо включить (#include) соответствующий файл заголовков пространства имен C++/WinRT для Windows, как показано выше.Whenever you want to use a type from a Windows namespaces, you must #include the corresponding C++/WinRT Windows namespace header file, as shown above. Соответствующий заголовок — это заголовок с таким же именем, как у пространства имен типа.The corresponding header is the one with the same name as the type's namespace. Например, чтобы использовать проекцию C++/WinRT для класса среды выполнения Windows::Foundation::Collections::PropertySet, добавьте заголовок winrt/Windows.Foundation.Collections.h.For example, to use the C++/WinRT projection for the Windows::Foundation::Collections::PropertySet runtime class, include the winrt/Windows.Foundation.Collections.h header.

Как правило, заголовок проекции C++/WinRT автоматически включает файл заголовка соответствующего родительского пространства имен.It's usual for a C++/WinRT projection header to automatically include its parent namespace header file. Так, например, winrt/Windows.Foundation.Collections.h включает winrt/Windows.Foundation.h.So, for example, winrt/Windows.Foundation.Collections.h includes winrt/Windows.Foundation.h. Но не следует полагаться на такое поведение, так как это сведения о реализации, которые меняются со временем.But you shouldn't rely on this behavior, since it's an implementation detail that changes over time. Необходимо явно включить все требуемые заголовки.You must explicitly include any headers that you need.

using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Web::Syndication;

Директивы using namespace являются необязательными, но удобными.The using namespace directives are optional, but convenient. Приведенный выше шаблон для таких директив (позволяющий выполнять поиск любых элементов в пространстве имен winrt по неполному имени) подходит при начале работы с новым проектом, при этом C++/WinRT — единственная проекция языка, которую вы используете внутри этого проекта.The pattern shown above for such directives (allowing unqualified name lookup for anything in the winrt namespace) is suitable for when you're beginning a new project and C++/WinRT is the only language projection you're using inside of that project. Если, с другой стороны, вы объединяете код C++/WinRT с кодом C++/CX или двоичным интерфейсом приложения SDK (ABI) (вы осуществляете перенос или взаимодействуете с этим кодом либо используете обе этих модели), изучите статьи Взаимодействие между C++/WinRT и C++/CX, Переход на C++/WinRT из C++/CX и Взаимодействие между C++/WinRT и интерфейсом ABI.If, on the other hand, you're mixing C++/WinRT code with C++/CX and/or SDK application binary interface (ABI) code (you're either porting from, or interoperating with, one or both of those models), then see the topics Interop between C++/WinRT and C++/CX, Move to C++/WinRT from C++/CX, and Interop between C++/WinRT and the ABI.

winrt::init_apartment();

Вызов winrt::init_apartment инициализирует поток в среде выполнения Windows (по умолчанию — в многопотоковом подразделении).The call to winrt::init_apartment initializes the thread in the Windows Runtime; by default, in a multithreaded apartment. Вызов также инициализирует COM.The call also initializes COM.

Uri rssFeedUri{ L"https://blogs.windows.com/feed" };
SyndicationClient syndicationClient;

Разместите в стеке два объекта: они представляют URI блога о Windows и клиент синдикации.Stack-allocate two objects: they represent the uri of the Windows blog, and a syndication client. Мы создаем URI с помощью простого литерала широкой строки (дополнительные способы работы со строками см. в статье Обработка строк в C++/WinRT).We construct the uri with a simple wide string literal (see String handling in C++/WinRT for more ways you can work with strings).

SyndicationFeed syndicationFeed = syndicationClient.RetrieveFeedAsync(rssFeedUri).get();

SyndicationClient::RetrieveFeedAsync является примером асинхронной функции среды выполнения Windows.SyndicationClient::RetrieveFeedAsync is an example of an asynchronous Windows Runtime function. Этот пример кода получает объект асинхронной операции от RetrieveFeedAsync и вызывает get для этого объекта, чтобы заблокировать вызывающий поток и дождаться результата (в данном случае это веб-канал синдикации).The code example receives an asynchronous operation object from RetrieveFeedAsync, and it calls get on that object to block the calling thread and wait for the result (which is a syndication feed, in this case). Дополнительные сведения о параллелизме и неблокирующих методах см. в статье Параллельная обработка и асинхронные операции с помощью C++/WinRT.For more about concurrency, and for non-blocking techniques, see Concurrency and asynchronous operations with C++/WinRT.

for (const SyndicationItem syndicationItem : syndicationFeed.Items()) { ... }

SyndicationFeed.Items является диапазоном, определяемым итераторами, возвращенными функциями begin и end (или их постоянными, обратными, либо постоянно-обратными вариантами).SyndicationFeed.Items is a range, defined by the iterators returned from begin and end functions (or their constant, reverse, and constant-reverse variants). По этой причине вы можете перечислять Items с помощью основанного на диапазоне оператора for или функции шаблона std::for_each.Because of this, you can enumerate Items with either a range-based for statement, or with the std::for_each template function. Всякий раз, когда вы проходите подобную коллекцию среды выполнения Windows, вам требуется #include <winrt/Windows.Foundation.Collections.h>.Whenever you iterate over a Windows Runtime collection like this, you'll need to #include <winrt/Windows.Foundation.Collections.h>.

winrt::hstring titleAsHstring = syndicationItem.Title().Text();
std::wcout << titleAsHstring.c_str() << std::endl;

Этот код получает текст заголовка канала в виде объекта winrt::hstring (см. сведения в статье Обработка строк в C++/WinRT).Gets the feed's title text, as a winrt::hstring object (more details in String handling in C++/WinRT). Затем hstring выводится с помощью функции c_str, которая отражает шаблон, используемый в строках стандартной библиотеки C++.The hstring is then output, via the c_str function, which reflects the pattern used with C++ Standard Library strings.

Как видно, C++/WinRT поощряет использование современных аналогичных классам выражений C++, таких как syndicationItem.Title().Text().As you can see, C++/WinRT encourages modern, and class-like, C++ expressions such as syndicationItem.Title().Text(). Это более ясный стиль программирования, отличающийся от традиционного COM-программирования.This is a different, and cleaner, programming style from traditional COM programming. Вам не нужно напрямую инициализировать COM или работать с указателями СОМ.You don't need to directly initialize COM, nor work with COM pointers.

Вам также не нужно обрабатывать коды возврата HRESULT.Nor do you need to handle HRESULT return codes. C++/ WinRT преобразует ошибки HRESULT в исключения, такие как winrt::hresult-error, для использования естественного и современного стиля программирования.C++/WinRT converts error HRESULTs to exceptions such as winrt::hresult-error for a natural and modern programming style. Дополнительные сведения об обработке ошибок и примеры кода см. в статье Обработка ошибок в C++/WinRT.For more info about error-handling, and code examples, see Error handling with C++/WinRT.

Добавление поддержки C++/WinRT в проекте классического приложения для WindowsModify a Windows Desktop application project to add C++/WinRT support

В этом разделе показано, как добавить поддержку C++/WinRT в проект классического приложения для Windows.This section shows you how you can add C++/WinRT support to a Windows Desktop application project that you might have. Если у вас нет проекта классического приложения для Windows, вы можете выполнить эти шаги, чтобы создать его.If you don't have an existing Windows Desktop application project, then you can follow along with these steps by first creating one. Например, откройте Visual Studio и создайте проект Visual C++ > Рабочий стол Windows > Классическое приложение для Windows.For example, open Visual Studio and create a Visual C++ > Windows Desktop > Windows Desktop Application project.

При желании можно установить расширение C++/WinRT для Visual Studio (VSIX) и пакет NuGet.You can optionally install the C++/WinRT Visual Studio Extension (VSIX) and the NuGet package. Дополнительные сведения см. в разделе о поддержке C++/WinRT в Visual Studio.For details, see Visual Studio support for C++/WinRT.

Настройка свойств проектаSet project properties

Перейдите к свойству проекта Общие > Версия пакета SDK для Windows и выберите Все конфигурации и Все платформы.Go to project property General > Windows SDK Version, and select All Configurations and All Platforms. Убедитесь, что для версии пакета Windows SDK установлено значение 10.0.17134.0 (Windows 10 версии 1803) или выше.Ensure that Windows SDK Version is set to 10.0.17134.0 (Windows 10, version 1803) or greater.

Убедитесь, что у вас не возникает ситуация, описанная в разделе Почему мой новый проект не компилируется?.Confirm that you're not affected by Why won't my new project compile?.

Так как C++/WinRT использует компоненты стандарта C++17, необходимо установить для свойства проекта C/C++ > Язык > Стандарт языка C++ значение Стандарт ISO C++17 (/std:c++17) .Because C++/WinRT uses features from the C++17 standard, set project property C/C++ > Language > C++ Language Standard to ISO C++17 Standard (/std:c++17).

Предварительно скомпилированный заголовокThe precompiled header

Шаблон проекта по умолчанию создает для вас предварительно скомпилированный заголовок с именем framework.h или stdafx.h.The default project template creates a precompiled header for you, named either framework.h, or stdafx.h. Переименуйте его на pch.h.Rename that to pch.h. Если у вас есть файл stdafx.cpp, переименуйте его на pch.cpp.If you have a stdafx.cpp file, then rename that to pch.cpp. Установите для свойства проекта C/C++ > Предварительно скомпилированные заголовки > Предварительно скомпилированный заголовок значение Create (/Yc) (Создать (/Yc)), а для свойства Предварительно скомпилированный заголовочный файл значение pch.h.Set project property C/C++ > Precompiled Headers > Precompiled Header to Create (/Yc), and Precompiled Header File to pch.h.

Найдите и замените все элементы #include "framework.h" (или #include "stdafx.h") на #include "pch.h".Find and replace all #include "framework.h" (or #include "stdafx.h") with #include "pch.h".

В pch.h добавьте winrt/base.h.In pch.h, include winrt/base.h.

// pch.h
...
#include <winrt/base.h>

СвязываниеLinking

Языковая проекция C++/WinRT зависит от определенных свободных функций среды выполнения Windows (не являющихся членами) и точек входа, для которых требуется связывание с библиотекой WindowsApp.lib.The C++/WinRT language projection depends on certain Windows Runtime free (non-member) functions, and entry points, that require linking to the WindowsApp.lib umbrella library. В этом разделе описываются три варианта соответствия компоновщику.This section describes three ways of satisfying the linker.

Первый вариант — добавить в ваш проект Visual Studio все свойства и цели C++/WinRT MSBuild.The first option is to add to your Visual Studio project all of the C++/WinRT MSBuild properties and targets. Для этого установите пакет NuGet Microsoft.Windows.CppWinRT в проект.To do this, install the Microsoft.Windows.CppWinRT NuGet package into your project. В Visual Studio откройте проект, щелкните Проект > Управление пакетами NuGet... > Обзор, введите или вставьте Microsoft.Windows.CppWinRT в поле поиска, выберите элемент в результатах поиска, а затем нажмите кнопку Установить, чтобы установить пакет для этого проекта.Open the project in Visual Studio, click Project > Manage NuGet Packages... > Browse, type or paste Microsoft.Windows.CppWinRT in the search box, select the item in search results, and then click Install to install the package for that project.

Вы также можете использовать параметры компоновки проекта для явного включения WindowsApp.lib.You can also use project link settings to explicitly link WindowsApp.lib. Кроме того, это можно сделать в исходном коде (например, в pch.h) следующим образом.Or, you can do it in source code (in pch.h, for example) like this.

#pragma comment(lib, "windowsapp")

Теперь вы можете выполнить компиляцию, связать и добавить код C++/WinRT в ваш проект (например, код, подобный тому, который показан в разделе Краткое руководство по C++/WinRT выше).You can now compile and link, and add C++/WinRT code to your project (for example, code similar to that shown in the A C++/WinRT quick-start section, above).

Три основных сценария для C++/WinRTThe three main scenarios for C++/WinRT

По мере работы с C++/WinRT и ознакомления с остальной частью документации вы, скорее всего, заметите, что есть три основных сценария. Они описаны в следующих разделах.As you use and become familiar with C++/WinRT, and work through the rest of the documentation here, you'll likely notice that there are three main scenarios, as described in the following sections.

Использование API и типов среды выполнения WindowsConsuming Windows Runtime APIs and types

Иными словами, это использование и вызовы API.In other words, using, or calling APIs. Например, вы можете выполнять вызовы API для обмена данными по Bluetooth, потоковую передачу и воспроизведение видео, интеграцию с оболочкой Windows и т. д.For example, making API calls to communicate using Bluetooth; to stream and present video; to integrate with the Windows shell; and so on. В C++/WinRT реализована полная поддержка этого сценария.C++/WinRT fully and uncompromisingly supports this category of scenario. Дополнительные сведения см. в статье Использование API-интерфейсов с помощью C++/WinRT.For more info, see Consume APIs with C++/WinRT.

Создание API и типов среды выполнения WindowsAuthoring Windows Runtime APIs and types

Иными словами, это создание API и типов.In other words, producing APIs and types. Например, вы можете создавать описанные в разделе выше типы API, графические API, API хранилища и файловой системы, сетевые API и т. д.For example, producing the kinds of APIs described in the section above; or the graphics APIs; the storage and file system APIs; the networking APIs, and so on. Дополнительные сведения см. в статье Создание API-интерфейсов в C++/WinRT.For more info, see Author APIs with C++/WinRT.

Разработка API с помощью C++/WinRT — это более сложный процесс, чем их использование, так как вам нужно работать с IDL для определения API перед его реализацией.Authoring APIs with C++/WinRT is a little more involved than consuming them, because you must use IDL to define the shape of the API before you can implement it. Описание процесса см. в статье Элементы управления XAML; привязка к свойству C++/WinRT.There's a walkthrough of doing that in XAML controls; bind to a C++/WinRT property.

Приложения XAMLXAML applications

Этот сценарий предполагает создания приложений и элементов управления в пользовательском интерфейсе на основе XAML.This scenario is about building applications and controls on the XAML UI framework. Работа с приложением, созданным с использованием XAML, включает процессы использования и разработки.Working in a XAML application amounts to a combination of consuming and authoring. Но так как сегодня XAML является основным средством описания пользовательского интерфейса в Windows, которое оказывает огромное влияние на среду выполнения Windows пропорционально этому, для него предусмотрен отдельный сценарий.But since XAML is the dominant UI framework on Windows today, and its influence over the Windows Runtime is proportionate to that, it deserves its own category of scenario.

Помните, что XAML лучше всего сочетается с языками программирования, в которых используется рефлексия.Be aware that XAML works best with programming languages that offer reflection. В C++/WinRT, чтобы взаимодействовать с XAML, иногда необходимо выполнить некоторую дополнительную работу.In C++/WinRT, you sometimes have to do a little extra work in order to interoperate with the XAML framework. Все эти случаи описаны в документации.All of those cases are covered in the documentation. Лучше всего начать со статей Элементы управления XAML; привязка к свойству C++/WinRT и Создание пользовательских (на основе шаблона) элементов управления XAML с помощью C++/WinRT.Good places to start are XAML controls; bind to a C++/WinRT property and XAML custom (templated) controls with C++/WinRT.

Примеры приложений, написанные на C++/WinRTSample apps written in C++/WinRT

См. раздел Где можно найти примеры приложений C++/WinRT?.See Where can I find C++/WinRT sample apps?.

Важные APIImportant APIs