// Создать объект System.Windows.Media.FormattedText.
FormattedText text = new FormattedText(
"Hello Visual Layer!",
new System.Globalization.CultureInfo("en-us"),
FlowDirection.LeftToRight,
new Typeface(this.FontFamily, FontStyles.Italic,
FontWeights.DemiBold, FontStretches.UltraExpanded),
TextFontSize,
Brushes.Green,
null,
VisualTreeHelper.GetDpi(this).PixelsPerDip);
// Создать объект DrawingVisual и получить объект DrawingContext.
DrawingVisual drawingVisual = new DrawingVisual;
using(DrawingContext drawingContext =
drawingVisual.RenderOpen)
{
// Вызвать любой из методов DrawingContext для визуализации данных.
drawingContext.DrawRoundedRectangle(
Brushes.Yellow, new Pen(Brushes.Black, 5),
new Rect(5, 5, 450, 100), 20, 20);
drawingContext.DrawText(text, new Point(20, 20));
}
// Динамически создать битовое изображение,
// используя данные в объекте DrawingVisual.
RenderTargetBitmap bmp = new RenderTargetBitmap(
500, 100, 100, 90, PixelFormats.Pbgra32);
bmp.Render(drawingVisual);
// Установить источник для элемента управления Image.
myImage.Source = bmp;
}
В коде задействовано несколько новых классов WPF, которые будут кратко описаны ниже. Метод начинается с создания нового объекта FormattedText, который представляет текстовую часть конструируемого изображения в памяти. Как видите, конструктор позволяет указывать многочисленные атрибуты, в том числе размер шрифта, семейство шрифтов, цвет переднего плана и сам текст.
Затем через вызов метода RenderOpen на экземпляре DrawingVisual получается необходимый объект DrawingContext. Здесь в DrawingVisual визуализируется цветной прямоугольник со скругленными углами, за которым следует форматированный текст. В обоих случаях графические данные помещаются в DrawingVisual с применением жестко закодированных значений, что не слишком хорошо в производственном приложении, но вполне подходит для такого простого теста.
Несколько последних операторов отображают DrawingVisual на объект RenderTagetBitmap, который является членом пространства имен System.Windows.Media.Imaging. Этот класс принимает визуальный объект и трансформирует его в растровое изображение, находящееся в памяти. Затем устанавливается свойство Source элемента управления Image и получается вывод, показанный на рис. 26.14.
На заметку! Пространство имен System.Windows.Media.Imaging содержит дополнительные классы кодирования, которые позволяют сохранять находящийся в памяти объект RenderTargetBitmap в физический файл в разнообразных форматах. Детали ищите в описании JpegBitmapEncoder и связанных с ним классов.
Визуализация графических данных в специальном диспетчере компоновки
Хотя применение DrawingVisual для рисования на фоне элемента управления WPF представляет интерес, возможно чаще придется строить специальный диспетчер компоновки (Grid, StackPanel, Canvas и т.д.), который внутренне использует визуальный уровень для визуализации своего содержимого. После создания такого специального диспетчера компоновки его можно подключить к обычному элементу Window (а также Page или UserControl) и позволить части пользовательского интерфейса использовать высоко оптимизированный агент визуализации, в то время как для визуализации некритичных графических данных будут применяться фигуры и рисунки.
Если дополнительная функциональность, предлагаемая специализированным диспетчером компоновки, не требуется, то можно просто расширить класс FrameworkElement, который обладает необходимой инфраструктурой, позволяющей содержать также и визуальные элементы. В целях иллюстрации вставьте в проект новый класс по имени CustomVisualFrameworkElement.