Создание приложения Hello world! на C++/CX

Важно!

В этом руководстве используется язык C++/CX. Корпорация Майкрософт выпустила C++/WinRT. Это полностью соответствующая стандартам современная проекция языка C++17 для интерфейсов API среды выполнения Windows (WinRT). Дополнительные сведения об этом языке см. в разделе C++/WinRT.

В Microsoft Visual Studio вы можете использовать C++/CX для разработки приложения для Windows с пользовательским интерфейсом, определенным на языке XAML.

Примечание

В этом руководстве используется Visual Studio Community 2019. Если вы используете другую версию Visual Studio, она может выглядеть иначе.

Прежде чем начать

  • Для работы с этим руководством необходимо использовать Visual Studio Community (или более позднюю версию) либо одну из других версий Visual Studio на компьютере с Windows. Для скачивания перейдите на страницу Получение инструментов.
  • Чтобы продолжить работу, требуются общие знания о C++/CX и XAML, а также представление об основных понятиях, описанных в статье Общие сведения об XAML.
  • Для выполнения этой процедуры следует использовать в Visual Studio макет окна по умолчанию. Чтобы вернуться к макету по умолчанию, выберите в строке меню пункт Окно>Сброс макета окон.

Сравнение классических приложений C++ с приложениями UWP

Если у вас есть опыт создания классических приложений для Windows на C++, значит, некоторые аспекты создания приложений для UWP вам, вероятно, покажутся хорошо знакомыми, а другие потребуют изучения.

Сходство с традиционным программированием на C++

  • Вы можете использовать STL, CRT (за некоторыми исключениями) и любую другую библиотеку C++, если код вызывает только функции Windows, которые доступны из среды выполнения Windows.

  • Если вы привыкли работать с областями визуальных конструкторов, можно использовать конструктор, встроенный в Microsoft Visual Studio, или использовать полнофункциональное приложение Blend для Visual Studio. Если вы обычно пишете код для пользовательского интерфейса вручную, значит, вы точно так же можете писать код XAML.

  • Создаваемые приложения могут использовать типы операционной системы Windows и ваши собственные настраиваемые типы.

  • Вы по-прежнему можете использовать отладчик, профилировщик и другие инструменты разработки Visual Studio.

  • Для компиляции созданных вами приложений в машинный код так же используется компилятор Visual C++. Выполнение приложений UWP на C++/CX не поддерживается в управляемой среде выполнения.

Новые возможности

  • Принципы разработки приложений UWP существенно отличаются от принципов разработки классических приложений. Утрачивают значение границы окон, подписи, диалоговые окна и прочее. Наибольшее значение приобретает содержимое. При создании приложений UWP этим принципам необходимо следовать с самого начала стадии планирования.

  • Для определения всего пользовательского интерфейса используется XAML. Разделение между пользовательским интерфейсом и основной логикой в приложении UWP намного более очевидно, чем в приложениях MFC или Win32. В то время как вы работаете над поведением приложения в файле кода, другие специалисты могут работать над внешним видом пользовательского интерфейса в файле XAML.

  • Программирование выполняется главным образом с помощью нового объектно-ориентированного API среды выполнения Windows с улучшенной навигацией, хотя на устройствах Windows для ряда функций можно по-прежнему использовать Win32.

  • С помощью C++/CX можно использовать и создавать объекты среды выполнения Windows. C++/CX разрешает обработку исключений C++, делегаты, события и автоматический подсчет ссылок для динамически создаваемых объектов. При использовании C++/CX особенности базовой архитектуры COM и Windows скрыты от кода приложения. Подробнее: Справочник по языку C++/CX.

  • Приложение компилируется в пакет, также включающий метаданные о типах, которые содержатся в приложении, используемых ресурсах и требуемых возможностях (доступ к файловой системе, Интернету, камере и т. д.).

  • В Microsoft Store и Windows Phone Store приложение проходит сертификацию для подтверждения его надежности, после чего оно становится доступным для миллионов потенциальных клиентов.

Приложение Hello World на C++/CX для Store

Наше первое приложение Hello World демонстрирует некоторые основные возможности взаимодействия, стилей и макета. Мы создадим приложение, используя шаблон проекта универсального приложения для Windows. Если вы разрабатывали приложения для Windows 8.1 и Windows Phone 8.1 ранее, возможно, вы помните, что вам нужны были три проекта в Visual Studio: один для приложения для Windows, один для приложения для телефона и еще один с общим кодом. Благодаря универсальной платформе Windows (UWP) в Windows можно создать всего один проект, который работает на всех устройствах, в том числе на компьютерах и ноутбуках под управлением Windows, таких устройствах, как планшеты, мобильные телефоны, устройства виртуальной реальности и т. д.

Начнем с основ.

  • Создание проекта универсального приложения для Windows в Visual Studio.

  • Общее представление о проектах и создаваемых файлах.

  • Общее представление о расширениях в расширениях компонентов Visual C++ (C++/CX) и способах их использования

Сначала создайте решение в Visual Studio

  1. В Visual Studio в строке меню последовательно выберите Файл>Создать>Проект.

  2. В диалоговом окне Создание проекта выберите Пустое приложение (универсальное приложение для Windows — C++/CX) . Если этот параметр не отображается, убедитесь, что вы установили средства разработки универсальных приложений для Windows. Дополнительные сведения см. в статье Подготовка.

C++/CX project templates in the Create a new project dialog box

  1. Нажмите кнопку Далее и введите имя для проекта. Он будет называться HelloWorld.

  2. Нажмите кнопку Создать.

Примечание

Если вы используете Visual Studio впервые, может открыться диалоговое окно с запросом включить параметр Режим разработчика. Режим разработчика — это специальный параметр, включающий определенные функции, например разрешение на непосредственный запуск приложений, а не только через Store. Дополнительные сведения см. в разделе Подготовка устройства к разработке. Чтобы продолжить работу с этим руководством, выберите Режим разработчика, нажмите Да и закройте диалоговое окно.

Файлы вашего проекта созданы.

Перед тем как продолжить работу, давайте изучим файлы решения.

Universal app solution with nodes collapsed

Информация о файлах проекта

Каждый файл с расширением XAML в папке проекта имеет соответствующий файл .XAML.H и файл .XAML.CPP в той же папке, а также файл .G и файл .G.HPP в папке "Generated Files", которая находится на диске, но не является частью проекта. Следует изменить эти XAML-файлы, чтобы создать элементы пользовательского интерфейса и соединить их с источниками данных (привязка данных). Следует изменить файлы .H и .CPP, чтобы добавить настраиваемую логику для обработчиков событий. Автоматически создаваемые файлы представляют преобразование разметки XAML в C++/CX. Не изменяйте эти файлы, но вы можете изучить их, чтобы лучше понимать, как работает код программной части. В основном созданный файл содержит частичное определение класса для корневого элемента XAML. Это тот же класс вы изменяете в файлах *.xaml.h и .cpp. Созданные файлы объявляют дочерние элементы пользовательского интерфейса XAML как члены класса, чтобы вы могли ссылаться на них в своем коде. Во время выполнения сборки созданный код и ваш код объединяются в полное определение класса, а затем компилируются.

Давайте сначала посмотрим на файлы проекта.

  • App.xaml, App.xaml.h, App.xaml.cpp: представляют объект приложения, который является точкой входа приложения. App.xaml не содержит разметки пользовательского интерфейса, относящейся к отдельным страницам, но вы можете добавить стили и другие элементы пользовательского интерфейса, которые следует сделать доступными с любой страницы. Файлы кода программной части содержат обработчики для событий OnLaunched и OnSuspending. Обычно сюда добавляется пользовательский код для инициализации приложения при запуске, а также здесь выполняется очистка при приостановке и завершении работы.
  • MainPage.xaml, MainPage.xaml.h, MainPage.xaml.cpp: содержат разметку XAML и код программной части для стандартной начальной страницы в приложении. Эта страница не поддерживает навигацию и не имеет встроенных элементов управления.
  • pch.h, pch.cpp: предварительно скомпилированный файл заголовка и файл, который включает его в ваш проект. В файле pch.h вы можете добавлять любые заголовки, которые не изменяются часто и которые добавлены в другие файлы в решении.
  • Package.appxmanifest: XML-файл, описывающий возможности устройства, которые необходимы вашему приложению. Также содержит информацию о версии приложения и другие метаданные. Чтобы открыть этот файл в конструкторе манифеста, просто дважды щелкните его.
  • HelloWorld_TemporaryKey.pfx: — ключ, разрешающий развертывание приложения на этом компьютере из Visual Studio.

Начало работы с программным кодом

Если вы изучите код в файлах App.xaml.h, App.xaml.cpp в общем проекте, то заметите, что в основном понимаете код C++. Тем не менее есть и некоторые незнакомые элементы синтаксиса, если вы ранее не сталкивались с приложениями для среды выполнения Windows, или если вы работали с C++/CLI. Вот общие нестандартные элементы синтаксиса, которые вы можете увидеть в C++/CX:

Ссылочные классы

Почти все классы среды выполнения Windows, которые включают в себя все типы в API Windows (элементы управления XAML, страницы в вашем приложении, сам класс App, все объекты устройств и сетевые объекты, все типы контейнеров), объявляются как ref class. (Несколько типов в Windows: класс значения или структура значения). Класс ref может использоваться из любого языка. В C++/CX время существования этих типов регулируется с помощью автоматического подсчета ссылок (а не сборки мусора), чтобы не приходилось явно удалять эти объекты. Вы также можете создавать свои собственные классы "ref".

namespace HelloWorld
{
   /// <summary>
   /// An empty page that can be used on its own or navigated to within a Frame.
   /// </summary>
   public ref class MainPage sealed
   {
      public:
      MainPage();
   };
}

Все типы среды выполнения Windows должны объявляться в пространстве имен и, в отличие от самих типов в C++ стандарта ISO, иметь модификатор доступа. Модификатор public делает класс видимым для компонентов среды выполнения Windows, которые находятся вне пространства имен. Ключевое слово sealed означает, что класс не может быть базовым классом. Почти все классы ref запечатаны. Наследование классов широко не используется, потому что JavaScript его не понимает.

ref new и ^ (крышка)

Переменная класса ref объявляется с помощью оператора «^» («крышка»), и создается экземпляр объекта с помощью ключевого слова «ref new». После этого вы получаете доступ к методам экземпляров объекта, используя оператор "->" почти так же, как указатель C++. Доступ к статическим методам можно получить с помощью оператора "::", как в C++ стандарта ISO.

В следующем коде мы используем полное имя, чтобы создать экземпляр объекта, и оператор "->", чтобы вызвать метод экземпляров.

Windows::UI::Xaml::Media::Imaging::BitmapImage^ bitmapImage =
     ref new Windows::UI::Xaml::Media::Imaging::BitmapImage();

bitmapImage->SetSource(fileStream);

Обычно в файле .CPP мы бы добавили директиву using namespace Windows::UI::Xaml::Media::Imaging и ключевое слово "auto", чтобы тот же код выглядел так:

auto bitmapImage = ref new BitmapImage();
bitmapImage->SetSource(fileStream);

Свойства

Класс "ref" может иметь свойства, которые, как и в управляемых языках, являются специальными функциями-членами. Они отображаются в виде полей в потребляющем коде.

public ref class SaveStateEventArgs sealed
{
   public:
   // Declare the property
   property Windows::Foundation::Collections::IMap<Platform::String^, Platform::Object^>^ PageState
   {
      Windows::Foundation::Collections::IMap<Platform::String^, Platform::Object^>^ get();
   }
   ...
};

   ...
   // consume the property like a public field
   void PhotoPage::SaveState(Object^ sender, Common::SaveStateEventArgs^ e)
   {    
      if (mruToken != nullptr && !mruToken->IsEmpty())
   {
      e->PageState->Insert("mruToken", mruToken);
   }
}

Делегаты

Как и в управляемых языках, делегат — это ссылочный тип, который инкапсулирует функцию с помощью специальной подписи. Делегаты часто используются с событиями и обработчиками событий.

// Delegate declaration (within namespace scope)
public delegate void LoadStateEventHandler(Platform::Object^ sender, LoadStateEventArgs^ e);

// Event declaration (class scope)
public ref class NavigationHelper sealed
{
   public:
   event LoadStateEventHandler^ LoadState;
};

// Create the event handler in consuming class
MainPage::MainPage()
{
   auto navigationHelper = ref new Common::NavigationHelper(this);
   navigationHelper->LoadState += ref new Common::LoadStateEventHandler(this, &MainPage::LoadState);
}

Добавление содержимого в приложение

Давайте добавим содержимое в приложение.

Шаг 1. Изменение начальной страницы

  1. В Обозревателе решений откройте файл MainPage.xaml.

  2. Создайте элементы управления для пользовательского интерфейса, добавив следующий код XAML в корневой элемент Grid сразу после его закрывающего тега. В нем содержится StackPanel с TextBlock, который запрашивает имя пользователя; элемент TextBox, который принимает имя пользователя; элемент Button и еще один элемент TextBlock.

    <StackPanel x:Name="contentPanel" Margin="120,30,0,0">
        <TextBlock HorizontalAlignment="Left" Text="Hello World" FontSize="36"/>
        <TextBlock Text="What's your name?"/>
        <StackPanel x:Name="inputPanel" Orientation="Horizontal" Margin="0,20,0,20">
            <TextBox x:Name="nameInput" Width="300" HorizontalAlignment="Left"/>
            <Button x:Name="inputButton" Content="Say &quot;Hello&quot;"/>
        </StackPanel>
        <TextBlock x:Name="greetingOutput"/>
    </StackPanel>
    
  3. На этот момент вы создали очень простое универсальное приложение для Windows. Если вы хотите увидеть, как выглядит приложение UWP, нажмите клавишу F5, чтобы выполнить сборку, развернуть и запустить приложение в режиме отладки.

Сначала появится экран-заставка по умолчанию. На нем будет присутствовать изображение (Assets\\SplashScreen.scale-100.png) и цвет фона, указанный в файле манифеста приложения. Подробнее о том, как настраивать экран-заставку, см. в разделе о добавлении экрана-заставки.

После того как экран-заставка исчезнет, появится ваше приложение. Отображается основная страница приложения.

UWP app screen, with controls

Пока это приложение мало что умеет, но вас можно поздравить с успешным созданием первого универсального приложения для Windows.

Чтобы завершить отладку и закрыть приложение, вернитесь в Visual Studio и нажмите клавиши SHIFT+F5.

Дополнительные сведения см. в статье Выполнение приложения Магазина в Visual Studio.

В приложении можно вводить информацию в TextBox, но при нажатии Button ничего не происходит. Позднее мы создадим для кнопки обработчик события Click, который отображает персонализированное приветствие.

Шаг 2. Создание обработчика событий

  1. В файле MainPage.xaml в коде XAML или в представлении конструирования выберите элемент Say Hello Button в добавленном ранее элементе StackPanel.

  2. Нажмите клавишу F4, чтобы открыть окно Свойства, а затем нажмите кнопку "События" (Events button).

  3. Найдите событие Click. В текстовом поле введите имя функции, которая обрабатывает событие Click. Для этого примера введите Button\_Click.

    Properties window, Events view

  4. Нажмите клавишу ВВОД. Метод обработчика событий создается в файле MainPage.xaml.cpp и открывается в редакторе кода. Вы можете добавить код, который выполняется при возникновении события.

В то же время в MainPage.xaml код XAML для Button обновляется, чтобы объявить обработчик событий Click следующим образом.

<Button Content="Say &quot;Hello&quot;" Click="Button_Click"/>

Вы также можете просто добавить это значение к коду xaml вручную. Это может быть удобно, если не загружается конструктор. При вводе вручную введите "Щелкнуть" и позвольте IntelliSense отобразить параметр, чтобы добавить новый обработчик событий. Таким образом, Visual Studio создает необходимую декларацию о методе и заглушку.

Конструктор не сможет загрузиться, если во время отрисовки возникнет необработанное исключение. Отрисовка в конструкторе предусматривает запуск версии времени разработки страницы. Это может быть удобно для отключения запущенного кода пользователя. Это можно сделать, изменив значение параметра в диалоговом окне "Сервис ", "Параметры" . В разделе Конструктор XAML снимите флажок Запускать код проекта в конструкторе XAML (если поддерживается) .

  1. В файле MainPage.xaml.cpp добавьте следующий код в обработчик событий Button\_Click, который вы только что создали. В этом коде вы получаете имя пользователя из элемента управления nameInputTextBox и используете его, чтобы создать приветствие. greetingOutputTextBlock отображает результат.
void HelloWorld::MainPage::Button_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
    greetingOutput->Text = "Hello, " + nameInput->Text + "!";
}
  1. Назначьте проект запускаемым, а затем нажмите клавишу F5, чтобы выполнить сборку и запустить приложение. При вводе имени в текстовое поле и нажатии кнопки приложение отображает персонализированное приветствие.

App screen with message display

Шаг 3. Стиль начальной страницы

Выбор темы

Внешний вид и функциональность приложения можно легко изменить. По умолчанию ваше приложение использует ресурсы со светлым стилем. Системные ресурсы также включают светлую тему. Примените ее и посмотрите, как будет выглядеть приложение.

Переключение на темную тему

  1. Откройте файл App.xaml.

  2. В открывающем теге Application измените свойство RequestedTheme и установите для него значение Dark:

    RequestedTheme="Dark"
    

    Вот полный тег Application с темной темой:

    <Application
    x:Class="HelloWorld.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HelloWorld"
    RequestedTheme="Dark">
    
  3. Чтобы выполнить сборку и запустить приложение, нажмите клавишу F5. Обратите внимание, что проект использует темную тему.

    App screen with dark theme

Какую тему использовать? Любую, какую пожелаете! Мы рекомендуем для приложений, которые главным образом отображают изображения или видео, лучше использовать темную тему, а для приложений с большим объемом текста — светлую тему. Если применяется пользовательская цветовая схема, используйте тему, которая лучше всего сочетается с внешним видом вашего приложения. В остальных разделах настоящего руководства мы используем светлую тему на снимках экрана.

Примечание. Тема применяется после запуска приложения. Она не изменится, пока приложение работает.

Использование системных стилей

В данный момент в приложении для Windows текст является слишком мелким и трудным для чтения. Давайте исправим это, применив системный стиль.

Изменение стиля элемента

  1. Откройте файл MainPage.xaml в проекте Windows.

  2. В коде XAML или в представлении конструирования выберите добавленный ранее элемент What's your name? TextBlock.

  3. В окне Свойства (F4) нажмите кнопку "Свойства" (Properties button) в правом верхнем углу.

  4. Разверните группу Текст и установите размер шрифта 18 пикселей.

  5. Разверните группу Разное и найдите свойство Style.

  6. Щелкните маркер свойств (зеленый прямоугольник справа от свойства Стиль), а затем в меню выберите пункты Системный ресурс>BaseTextBlockStyle.

    BaseTextBlockStyle — это ресурс, который определен в ResourceDictionary в <корневой папке>\Program Files\Windows Kits\10\Include\winrt\xaml\\design\generic.xaml.

    Properties window, Properties view

    Вид текста в рабочей области конструирования XAML изменится. В редакторе XAML обновляется код XAML для TextBlock.

<TextBlock Text="What's your name?" Style="{ThemeResource BaseTextBlockStyle}"/>
  1. Повторите процесс, чтобы установить размер шрифта, и назначьте значение BaseTextBlockStyle элементу greetingOutputTextBlock.

    Совет. Хотя в этом элементе TextBlock нет текста, при наведении указателя мыши на область конструктора XAML голубой контур показывает его расположение, чтобы его можно было выбрать.  

    XAML-код теперь выглядит так:

<StackPanel x:Name="contentPanel" Margin="120,30,0,0">
    <TextBlock Style="{ThemeResource BaseTextBlockStyle}" FontSize="18" Text="What's your name?"/>
    <StackPanel x:Name="inputPanel" Orientation="Horizontal" Margin="0,20,0,20">
        <TextBox x:Name="nameInput" Width="300" HorizontalAlignment="Left"/>
        <Button x:Name="inputButton" Content="Say &quot;Hello&quot;" Click="Button_Click"/>
    </StackPanel>
    <TextBlock Style="{ThemeResource BaseTextBlockStyle}" FontSize="18" x:Name="greetingOutput"/>
</StackPanel>
  1. Чтобы выполнить сборку и запустить приложение, нажмите клавишу F5. Теперь оно выглядит следующим образом:

App screen with larger text

Шаг 4. Адаптация пользовательского интерфейса к различным размерам окна

Теперь мы адаптируем пользовательский интерфейс к различным размерам экрана, чтобы приложение выглядело хорошо на мобильных устройствах. Для этого добавьте VisualStateManager и установите свойства, применяемые для различных визуальных состояний.

Настройка макета пользовательского интерфейса

  1. В редакторе XAML добавьте этот блок XAML после открывающего тега корневого элемента Grid.
<VisualStateManager.VisualStateGroups>
    <VisualStateGroup>
        <VisualState x:Name="wideState">
            <VisualState.StateTriggers>
                <AdaptiveTrigger MinWindowWidth="641" />
            </VisualState.StateTriggers>
        </VisualState>
        <VisualState x:Name="narrowState">
            <VisualState.StateTriggers>
                <AdaptiveTrigger MinWindowWidth="0" />
            </VisualState.StateTriggers>
            <VisualState.Setters>
                <Setter Target="contentPanel.Margin" Value="20,30,0,0"/>
                <Setter Target="inputPanel.Orientation" Value="Vertical"/>
                <Setter Target="inputButton.Margin" Value="0,4,0,0"/>
            </VisualState.Setters>
        </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>
  1. Выполните отладку приложения на локальном компьютере. Обратите внимание, что пользовательский интерфейс выглядит так же, как и раньше, пока ширина окна не станет меньше 641 аппаратно-независимого пикселя (DIP).
  2. Выполните отладку приложения на эмуляторе мобильного устройства. Обратите внимание, что пользовательский интерфейс использует свойства, указанные вами в narrowState, и правильно отображается на маленьком экране.

Mobile app screen with styled text

Если вы использовали VisualStateManager в предыдущих версиях XAML, можно заметить, что в XAML здесь используется упрощенный синтаксис.

У VisualState с именем wideState имеется AdaptiveTrigger, для свойства MinWindowWidth которого задано значение 641. Это означает, что состояние будет применяться только тогда, когда ширина окна составляет не менее минимального значения 641 DIP. Вы не указываете никакие объекты Setter для этого состояния, поэтому оно использует свойства макета, заданные в XAML для содержимого страницы.

У второго VisualState, narrowState, имеется AdaptiveTrigger, для свойства MinWindowWidth которого задано значение 0. Это состояние применяется, когда ширина окна больше 0, но меньше 641 DIP. (Для 641 DIP-пикселя применяется wideState.) В этом состоянии необходимо указать некоторые объекты Setter, чтобы изменить свойства макета элементов управления в пользовательском интерфейсе.

  • Вы уменьшаете левое поле элемента contentPanel со 120 до 20.
  • Вы изменяете Orientation для элемента inputPanel с Horizontal на Vertical.
  • Вы добавляете верхнее поле высотой 4 DIP к элементу inputButton.

Сводка

Поздравляем, вы завершили изучение первого учебника. Вы научились добавлять содержимое в универсальные приложения для Windows, менять их внешний вид и реализовывать возможности взаимодействия.

Дальнейшие действия

Если у вас есть проект универсального приложения для Windows, ориентированный на Windows 8.1 и (или) Windows Phone 8.1, вы можете перенести его в Windows 10 или Windows 11. Для этого действия нет автоматического процесса, но его можно выполнить вручную. Начните новый проект универсального приложения для Windows, чтобы получить последнюю структуру системы и файлы манифеста проекта, скопируйте файлы кода в структуру каталогов проекта, добавьте элементы в проект и перепишите код XAML, используя VisualStateManager в соответствии с рекомендациями в этом разделе. Дополнительные сведения см. в разделах: Перенос проекта среды выполнения Windows 8 в проект универсальной платформы Windows (UWP) и Перенос на универсальную платформу Windows (C++).

Если у вас есть код на C++, который вы хотите включить в приложение UWP, например для создания нового пользовательского интерфейса UWP для существующего приложения, изучите раздел Практическое руководство. Использование существующего кода C++ в приложении универсальной платформы Windows.