Поделиться через


Создание простого приложения Win2D

В этом руководстве представлены некоторые основные возможности рисования Win2D. Вы изучите следующие темы:

  • Добавьте Win2D в проект XAML XAML C#.
  • Рисование текста и геометрии.
  • Применение эффектов фильтра.
  • Анимируйте содержимое Win2D.
  • Следуйте рекомендациям Win2D.

Настройка компьютера разработки

Обязательно настройте компьютер со всеми необходимыми средствами:

Создание проекта Win2D

Выполните действия, описанные в кратком руководстве по Win2D "Hello, World!", чтобы создать проект с помощью Win2D и добавить ссылку на пакет NuGet Win2D. Вы можете использовать WinUI 3 (пакет SDK для приложений Windows) или универсальная платформа Windows (UWP).

Добавление Win2D CanvasControl в XAML приложения

  1. Чтобы использовать Win2D, вам нужно где-то нарисовать графику. В приложении XAML самый простой способ сделать это — добавить CanvasControl на страницу XAML.

Прежде чем продолжить, сначала убедитесь, что для параметра архитектуры проекта задано x86 значение или x64 нетAny CPU. Win2D реализован в C++, поэтому проекты, использующие Win2D, должны быть ориентированы на определенную архитектуру ЦП.

  1. MainPage.xaml Перейдите в проект, дважды щелкнув его в Обозреватель решений. Откроется файл. Для удобства можно дважды нажать кнопку XAML на вкладке конструктора; Это позволит скрыть визуальный конструктор и зарезервировать все пространство для представления кода.

  2. Перед добавлением элемента управления сначала необходимо указать XAML, где определен CanvasControl . Для этого перейдите к определению элемента Page и добавьте следующую директиву: xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml" Теперь xaml должен выглядеть следующим образом:

<Page
    ...
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
    mc:Ignorable="d">
  1. Теперь добавьте новый элемент canvas:CanvasControl в качестве дочернего элемента в корневой элемент Grid . Присвойте элементу управления имя, например "canvas". Теперь xaml должен выглядеть следующим образом:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <canvas:CanvasControl x:Name="canvas"/>
</Grid>
  1. Затем определите обработчик событий для события Draw . CanvasControl вызывает Draw всякий раз, когда приложению требуется рисование или перерисовка содержимого. Проще всего позволить Visual Studio AutoComplete помочь вам. В определении CanvasControl начните вводить новый атрибут для обработчика Draw событий:
<canvas:CanvasControl x:Name="canvas" Draw="canvas_Draw" />

Примечание.

После ввода Draw="в Visual Studio должен появиться окно с запросом на автоматическое заполнение правильного определения обработчика событий. Нажмите клавишу TAB, чтобы принять обработчик событий Visual Studio по умолчанию. Это также автоматически добавит правильный форматированный метод обработчика событий в коде позади ('MainPage.xaml.cs'' ). Не беспокойтесь, если вы не использовали автозавершение; Вы можете вручную добавить метод обработчика событий на следующем шаге.

Рисование первого текста в Win2D

  1. Теперь давайте перейдем к коду C#. Откройте MainPage.xaml.cs из Обозреватель решений.

  2. В верхней части файла C# находятся различные определения пространства имен. Добавьте приведенные ниже пространства имен.

using Windows.UI;
using System.Numerics;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
  1. Затем вы увидите следующий пустой обработчик событий, который был вставлен автозавершением:
private void canvas_Draw(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
}

(Если вы не использовали автозавершение на предыдущем шаге, добавьте этот код сейчас.)

  1. Параметр CanvasDrawEventArgs предоставляет элемент, DrawingSession, который является типом CanvasDrawingSession. Этот класс предоставляет большую часть основных функций рисования в Win2D: он имеет такие методы, как CanvasDrawingSession.DrawRectangle, CanvasDrawingSession.DrawImage, и метод, который необходимо нарисовать текст, CanvasDrawingSession.DrawText.

Добавьте следующий код в метод canvas_Draw:

args.DrawingSession.DrawText("Hello, World!", 100, 100, Colors.Black);

Первый аргумент — это строка, "Hello, World!"которую требуется отобразить Win2D. Два "100" сообщают Win2D, чтобы смещать этот текст на 100 ДИП (независимых от устройства пикселей) справа и вниз. Наконец, Colors.Black определяет цвет текста.

  1. Теперь вы готовы запустить свое первое приложение Win2D. Нажмите клавишу F5 для компиляции и запуска. Вы должны увидеть пустое окно с "Hello, world!" в черном.

Правильное удаление ресурсов Win2D

  1. Прежде чем продолжить рисование других типов содержимого, сначала следует добавить код, чтобы убедиться, что приложение избегает утечки памяти. Большинство приложений Win2D, написанных на языке .NET и используя элемент управления Win2D, например CanvasControl , необходимо выполнить следующие действия. Строго говоря, простое приложение Hello, world не влияет, но это хорошая практика, чтобы следовать в целом.

Дополнительные сведения см. в разделе "Избегание утечки памяти".

  1. Откройте MainPage.xaml и найдите элемент XAML страницы , содержащий элемент CanvasControl. Он должен быть первым элементом в файле.

  2. Добавьте обработчик для события Unloaded. Код XAML должен выглядеть следующим образом:

<Page
    ...
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
    mc:Ignorable="d"
    Unloaded="Page_Unloaded">
  1. MainPage.xaml.cs Перейдите к обработчику событий и найдите егоPage_Unloaded. Добавьте следующий код:
void Page_Unloaded(object sender, RoutedEventArgs e)
{
    this.canvas.RemoveFromVisualTree();
    this.canvas = null;
}
  1. Если приложение содержит несколько элементов управления Win2D, необходимо повторить описанные выше действия для каждой страницы XAML, содержащей элемент управления Win2D. В настоящее время приложение имеет только один CanvasControl , поэтому все готово.

Рисование некоторых фигур

  1. Так же легко добавить 2D-геометрию в приложение. Добавьте следующий код в конец canvas_Draw:
args.DrawingSession.DrawCircle(125, 125, 100, Colors.Green);
args.DrawingSession.DrawLine(0, 0, 50, 200, Colors.Red);

Аргументы этих двух методов похожи DrawTextна . Круг определяется точкой центра (125, 125), радиусом (100) и цветом (зеленым). Строка определяется началом (0, 0), концом (50, 200) и цветом (красным).

  1. Теперь нажмите клавишу F5, чтобы запустить приложение. Вы должны увидеть "Привет, мир!" вместе с зеленым кругом и красной линией.

Возможно, вам интересно, как управлять более сложными параметрами рисования, такими как толщина линии и дефисы, или более сложные варианты заливки, такие как использование кистей. Win2D предоставляет все эти параметры и многое другое и упрощает их использование при необходимости. Draw(...) Все методы предлагают множество перегрузок, которые могут принимать дополнительные параметры, такие как CanvasTextFormat (семейство шрифтов, размер и т. д.) и CanvasStrokeStyle (дефисы, точки, конечные капки и т. д.). Чтобы узнать больше об этих вариантах, вы можете изучить область API.

Динамическое создание параметров рисования

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

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

Random rnd = new Random();
private Vector2 RndPosition()
{
    double x = rnd.NextDouble() * 500f;
    double y = rnd.NextDouble() * 500f;
    return new Vector2((float)x, (float)y);
}

private float RndRadius()
{
    return (float)rnd.NextDouble() * 150f;
}

private byte RndByte()
{
    return (byte)rnd.Next(256);
}
  1. canvas_Draw Измените метод для рисования с помощью этих случайных параметров:
private void canvas_Draw(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
    args.DrawingSession.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
    args.DrawingSession.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
    args.DrawingSession.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
}

Давайте разберем, как DrawText изменилось. "Hello, World!" остается таким же, как и раньше. Параметры смещения x и y были заменены одним элементом System.Numerics.Vector2 , созданным RndPosition. Наконец, вместо использования предопределенного цвета можно определить цвет Color.FromArgb с помощью значений A, R, G и B. A — альфа- или уровень непрозрачности; В этом случае всегда требуется полностью непрозрачный (255).

DrawCircle и DrawLine работает аналогично DrawText.

  1. Наконец, заключите код рисования в for цикл. В конечном итоге вам потребуется следующий canvas_Draw код:
for (int i = 0; i < 100; i++)
{
    args.DrawingSession.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
    args.DrawingSession.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
    args.DrawingSession.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
}
  1. Снова запустите приложение. Вы должны увидеть целый ряд текста, линий и кругов со случайными позициями и размерами.

Применение эффекта изображения к содержимому

Эффекты изображения, также известные как эффекты фильтра, — это графические преобразования, применяемые к данным пикселей. Насыщенность, оттенок поворота и размытие Гауссиана являются некоторыми общими эффектами изображения. Эффекты изображения можно объединить, создавая сложный визуальный вид для минимальной работы.

Эффекты изображения используются путем предоставления исходного изображения (содержимого, с которым вы начинаете), создания эффекта, например GaussianBlurEffect, задания свойств, таких как BlurAmount, а затем рисование выходных данных эффекта.DrawImage

Чтобы применить эффект изображения к тексту и фигурам, необходимо сначала отобразить это содержимое в CanvasCommandList. Этот объект можно использовать как входные данные для вашего эффекта.

  1. Измените canvas_Draw метод, чтобы использовать следующий код:
CanvasCommandList cl = new CanvasCommandList(sender);

using (CanvasDrawingSession clds = cl.CreateDrawingSession())
{
    for (int i = 0; i < 100; i++)
    {
        clds.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
        clds.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
        clds.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
    }
}

Точно так же, как вы получаете CanvasDrawingSession , из CanvasDrawEventArgs которого можно рисовать, вы можете создать из CanvasDrawingSession нее CanvasCommandList. Единственное различие заключается в том, что при рисовании в сеансе рисования списка команд (clds), вы не выполняете прямую отрисовку в CanvasControl. Вместо этого список команд — это промежуточный объект, в который хранятся результаты отрисовки для последующего использования.

Возможно, вы заметили using блок, который упаковывает сеанс рисования списка команд. Сеансы рисования реализуют IDisposable и должны быть удалены при завершении отрисовки ( using блок делает это). Полученное CanvasDrawingSession автоматически закрыто для CanvasDrawEventArgs вас, но необходимо удалить все сеансы рисования, созданные явным образом.

  1. Наконец, определите GaussianBlurEffect , добавив следующий код в конец canvas_Draw метода:
GaussianBlurEffect blur = new GaussianBlurEffect();
blur.Source = cl;
blur.BlurAmount = 10.0f;
args.DrawingSession.DrawImage(blur);
  1. Снова запустите приложение. Вы должны видеть строки, текст и круги с размытым внешним видом.

Анимация приложения с помощью CanvasAnimatedControl

. Win2D позволяет обновлять и анимировать содержимое в режиме реального времени, например изменяя радиус размытия размытия размывателя с каждым кадром. Для этого вы будете использовать CanvasAnimatedControl.

CanvasControl лучше всего подходит для в основном статического графического содержимого. Оно вызывает Draw событие только в том случае, если содержимое должно быть обновлено или перезабрано. Если у вас постоянно меняющееся содержимое, вместо этого следует рассмотреть возможность использования CanvasAnimatedControl . Два элемента управления работают очень аналогично, за исключением CanvasAnimatedControl периодического вызова Draw события; по умолчанию он вызывается 60 раз в секунду.

  1. Чтобы переключиться CanvasAnimatedControlна , перейдите MainPage.xamlк разделу , удалите строку CanvasControl и замените ее следующим кодом XAML:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <canvas:CanvasAnimatedControl x:Name="canvas" Draw="canvas_DrawAnimated" CreateResources="canvas_CreateResources"/>
</Grid>

Как и в CanvasControl, пусть автозавершение создает Draw обработчик событий для вас. По умолчанию Visual Studio будет называть этот обработчик canvas_Draw_1 , так как canvas_Draw уже существует. Здесь мы переименовали метод canvas_AnimatedDraw , чтобы убедиться, что это другое событие.

Кроме того, вы также обрабатываете новое событие CreateResources. Еще раз позвольте автозавершения создать обработчик.

Теперь, когда приложение будет перерисовывать по 60 кадров в секунду, более эффективно создавать визуальные ресурсы Win2D один раз и повторно использовать их с каждым кадром. Это неэффективно для создания CanvasCommandList и рисования 300 элементов в него 60 раз в секунду, когда содержимое остается статическим. CreateResources — это событие, которое запускается только в том случае, если Win2D определяет необходимость повторного создания визуальных ресурсов, например при загрузке страницы.

  1. Переключитесь обратно MainPage.xaml.csна . canvas_Draw Найдите метод, который должен выглядеть следующим образом:
private void canvas_Draw(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
    CanvasCommandList cl = new CanvasCommandList(sender);
    using (CanvasDrawingSession clds = cl.CreateDrawingSession())
    {
        for (int i = 0; i < 100; i++)
        {
            clds.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
            clds.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
            clds.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
        }
    }

    GaussianBlurEffect blur = new GaussianBlurEffect();
    blur.Source = cl;
    blur.BlurAmount = 10.0f;
    args.DrawingSession.DrawImage(blur);
}

Подавляющее большинство существующего кода рисования не требуется выполнять с каждым кадром: список команд, содержащий текст, строки и круги, остается одинаковым с каждым кадром, и единственное, что изменяет радиус размытия. Поэтому этот статический код можно переместить в CreateResources.

Для этого сначала вырезать (CTRL+X) все содержимое canvas_Draw, за исключением самой последней строки (args.DrawingSession.DrawImage(blur);). Теперь вы можете удалить оставшуюся часть canvas_Draw , так как она больше не нужна: отзыв, имеющий CanvasAnimatedControl собственное отдельное Draw событие.

  1. Найдите автоматически созданный canvas_CreateResources метод:
private void canvas_CreateResources(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedControl sender, 
    Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
{}

Вставьте (CTRL+V) ранее вырезанный код в этот метод. Затем переместите объявление GaussianBlurEffect вне текста метода, чтобы переменная стала членом класса MainPage. Теперь код должен выглядеть так, как показано ниже.

GaussianBlurEffect blur;
private void canvas_CreateResources(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedControl sender,
    Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
{
    CanvasCommandList cl = new CanvasCommandList(sender);
    using (CanvasDrawingSession clds = cl.CreateDrawingSession())
    {
        for (int i = 0; i < 100; i++)
        {
            clds.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
            clds.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
            clds.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
        }
    }

    blur = new GaussianBlurEffect()
    {
        Source = cl,
        BlurAmount = 10.0f
    };
}
  1. Теперь вы можете анимировать размытие Гауссиана. canvas_DrawAnimated Найдите метод и добавьте следующий код:
private void canvas_DrawAnimated(
    Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender,
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedDrawEventArgs args)
{
    float radius = (float)(1 + Math.Sin(args.Timing.TotalTime.TotalSeconds)) * 10f;
    blur.BlurAmount = radius;
    args.DrawingSession.DrawImage(blur);
}

Это считывает общее истекшее время, предоставленное CanvasAnimatedDrawEventArgs , и использует это для вычисления требуемой суммы размытия; функция синуса предоставляет интересный вариант с течением времени. Наконец, GaussianBlurEffect отрисовывается.

  1. Запустите приложение, чтобы увидеть размытое содержимое с течением времени.

Поздравляем с завершением этого краткого руководства по началу работы! Надеюсь, вы узнали, как можно использовать Win2D для создания богатой анимированной визуальной сцены с несколькими строками кода C# и XAML.