合成画笔

屏幕上的 UWP 应用中可见的所有内容均可见,因为它是通过画笔绘制。 你可以通过画笔绘制用户界面 (UI) 对象,内容可以为简单纯色图像或绘图到复杂的效果链。 本主题介绍使用 CompositionBrush 绘制的概念。

请注意,使用 XAML UWP 应用时,你可以选择使用 XAML 画笔CompositionBrush 绘制 UIElement。 一般来说,如果你的方案支持 XAML 画笔,则建议你选择 XAML 画笔,这样更加容易。 例如,设置按钮颜色动画、使用图像更改文本或图形填充。 另一方面,如果你尝试的操作不支持 XAML 画笔,如使用动画蒙板或动画九网格拉伸或效果链绘制,则可以选择 CompositionBrush 以使用 XamlCompositionBrushBase 绘制 UIElement。

操作可视化层时,必须使用 CompositionBrush 绘制 SpriteVisual 区域。

先决条件

本概述假定你已熟悉基本合成应用程序的结构,如可视化层概述中所述。

使用 CompositionBrush 绘制

CompositionBrush通过输出“绘制”区域。 不同的画笔具有不同的输出类型。 某些画笔使用纯色绘制区域,其他的画笔可以使用渐变、图像、自定义绘图或效果绘制区域。 另外还有用于修改其他画笔行为的专用画笔。 例如,绘制区域时,可以使用不透明蒙板控制使用 CompositionBrush 绘制的区域,或者使用九网格控制应用到 CompositionBrush 的延伸。 CompositionBrush 可以是以下类型之一:

详细信息 在 中引入
CompositionColorBrush 使用纯色绘制区域 Windows 10,版本 1511 (SDK 10586)
CompositionSurfaceBrush 使用 ICompositionSurface 内容绘制区域 Windows 10,版本 1511 (SDK 10586)
CompositionEffectBrush 使用合成效果内容绘制区域 Windows 10,版本 1511 (SDK 10586)
CompositionMaskBrush 使用带不透明蒙板的 CompositionBrush 绘制视觉对象 Windows 10,版本 1607 (SDK 14393)
CompositionNineGridBrush 使用九网格拉伸的 CompositionBrush 绘制区域 Windows 10,版本 1607 (SDK 14393)
CompositionLinearGradientBrush 使用线性渐变绘制区域 Windows 10,版本 1709 (SDK 16299)
CompositionRadialGradientBrush 使用径向渐变绘制区域 Windows 10,版本 1903 (Insider Preview SDK)
CompositionBackdropBrush 通过对应用程序的背景像素或桌面上应用程序窗口正后方的像素采用来绘制区域。 用作其他 CompositionBrush(如 CompositionEffectBrush)的输入 Windows 10,版本 1607 (SDK 14393)

使用纯色绘制

CompositionColorBrush 使用纯色绘制区域。 可以通过多种方式指定 SolidColorBrush 颜色。 例如,可以指定其 alpha、红色、蓝色和绿色 (ARGB) 通道,或者使用颜色类中提供的其中一个预定义颜色。

下图和代码显示了一个较小的可视化树来创建一个矩形,该矩形用黑色画笔描边,并使用颜色值为 0x9ACD32 的纯色画笔进行绘制。

CompositionColorBrush

Compositor _compositor;
ContainerVisual _container;
SpriteVisual _colorVisual1, _colorVisual2;
CompositionColorBrush _blackBrush, _greenBrush;

_compositor = Window.Current.Compositor;
_container = _compositor.CreateContainerVisual();

_blackBrush = _compositor.CreateColorBrush(Colors.Black);
_colorVisual1= _compositor.CreateSpriteVisual();
_colorVisual1.Brush = _blackBrush;
_colorVisual1.Size = new Vector2(156, 156);
_colorVisual1.Offset = new Vector3(0, 0, 0);
_container.Children.InsertAtBottom(_colorVisual1);

_ greenBrush = _compositor.CreateColorBrush(Color.FromArgb(0xff, 0x9A, 0xCD, 0x32));
_colorVisual2 = _compositor.CreateSpriteVisual();
_colorVisual2.Brush = _greenBrush;
_colorVisual2.Size = new Vector2(150, 150);
_colorVisual2.Offset = new Vector3(3, 3, 0);
_container.Children.InsertAtBottom(_colorVisual2);

使用线性渐变绘制

CompositionLinearGradientBrush 使用线性渐变绘制区域。 线性渐变在线条(渐变轴)中混合了两种或多种颜色。 你可以使用 GradientStop 对象指定渐变的颜色及其位置。

下图和代码所示为使用红黄 2 种起止颜色的 LinearGradientBrush 绘制的 SpriteVisual。

CompositionLinearGradientBrush

Compositor _compositor;
SpriteVisual _gradientVisual;
CompositionLinearGradientBrush _redyellowBrush;

_compositor = Window.Current.Compositor;

_redyellowBrush = _compositor.CreateLinearGradientBrush();
_redyellowBrush.ColorStops.Add(_compositor.CreateColorGradientStop(0, Colors.Red));
_redyellowBrush.ColorStops.Add(_compositor.CreateColorGradientStop(1, Colors.Yellow));
_gradientVisual = _compositor.CreateSpriteVisual();
_gradientVisual.Brush = _redyellowBrush;
_gradientVisual.Size = new Vector2(156, 156);

使用径向渐变绘制

CompositionRadialGradientBrush 使用径向渐变绘制区域。 径向渐变将两种或多种颜色与从椭圆中心开始到椭圆半径结束的渐变混合在一起。 GradientStop 对象用于定义颜色及其在渐变中的位置。

下面的插图和代码显示了使用带有 2 个 GradientStops 的 RadialGradientBrush 绘制的 SpriteVisual。

CompositionRadialGradientBrush

Compositor _compositor;
SpriteVisual _gradientVisual;
CompositionRadialGradientBrush RGBrush;

_compositor = Window.Current.Compositor;

RGBrush = _compositor.CreateRadialGradientBrush();
RGBrush.ColorStops.Add(_compositor.CreateColorGradientStop(0, Colors.Aquamarine));
RGBrush.ColorStops.Add(_compositor.CreateColorGradientStop(1, Colors.DeepPink));
_gradientVisual = _compositor.CreateSpriteVisual();
_gradientVisual.Brush = RGBrush;
_gradientVisual.Size = new Vector2(200, 200);

使用图像绘制

CompositionSurfaceBrush 使用 ICompositionSurface 上渲染的像素绘制区域。 例如,CompositionSurfaceBrush 可用于使用 LoadedImageSurface API 通过 ICompositionSurface 上渲染的图像绘制区域。

下图和代码所示为使用 LoadedImageSurface 通过 ICompositionSurface 上渲染的 licorice 位图绘制的 SpriteVisual。 CompositionSurfaceBrush 的属性可用于拉伸和对齐可视边界内的位图。

CompositionSurfaceBrush

Compositor _compositor;
SpriteVisual _imageVisual;
CompositionSurfaceBrush _imageBrush;

_compositor = Window.Current.Compositor;

_imageBrush = _compositor.CreateSurfaceBrush();

// The loadedSurface has a size of 0x0 till the image has been been downloaded, decoded and loaded to the surface. We can assign the surface to the CompositionSurfaceBrush and it will show up once the image is loaded to the surface.
LoadedImageSurface _loadedSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Assets/licorice.jpg"));
_imageBrush.Surface = _loadedSurface;

_imageVisual = _compositor.CreateSpriteVisual();
_imageVisual.Brush = _imageBrush;
_imageVisual.Size = new Vector2(156, 156);

使用自定义绘图绘制

CompositionSurfaceBrush 也可用于使用 Win2D(或 D2D)渲染的 ICompositionSurface 中的像素绘制区域。

下图和代码所示为通过 Win2D 使用 ICompositionSurface 上渲染的文本运行绘制的 SpriteVisual。 请注意,若要使用 Win2D,你需要在项目中包括 Win2D NuGet 程序包。

Compositor _compositor;
CanvasDevice _device;
CompositionGraphicsDevice _compositionGraphicsDevice;
SpriteVisual _drawingVisual;
CompositionSurfaceBrush _drawingBrush;

_device = CanvasDevice.GetSharedDevice();
_compositionGraphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(_compositor, _device);

_drawingBrush = _compositor.CreateSurfaceBrush();
CompositionDrawingSurface _drawingSurface = _compositionGraphicsDevice.CreateDrawingSurface(new Size(256, 256), DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);

using (var ds = CanvasComposition.CreateDrawingSession(_drawingSurface))
{
     ds.Clear(Colors.Transparent);
     var rect = new Rect(new Point(2, 2), (_drawingSurface.Size.ToVector2() - new Vector2(4, 4)).ToSize());
     ds.FillRoundedRectangle(rect, 15, 15, Colors.LightBlue);
     ds.DrawRoundedRectangle(rect, 15, 15, Colors.Gray, 2);
     ds.DrawText("This is a composition drawing surface", rect, Colors.Black, new CanvasTextFormat()
     {
          FontFamily = "Comic Sans MS",
          FontSize = 32,
          WordWrapping = CanvasWordWrapping.WholeWord,
          VerticalAlignment = CanvasVerticalAlignment.Center,
          HorizontalAlignment = CanvasHorizontalAlignment.Center
     }
);

_drawingBrush.Surface = _drawingSurface;

_drawingVisual = _compositor.CreateSpriteVisual();
_drawingVisual.Brush = _drawingBrush;
_drawingVisual.Size = new Vector2(156, 156);

同样,CompositionSurfaceBrush 也可用于使用 Win2D 互操作通过 SwapChain 绘制 SpriteVisual。 本示例提供如何使用 Win2D 绘制具有交换链的 SpriteVisual。

使用视频绘制

CompositionSurfaceBrush也可用于使用通过 MediaPlayer 类加载的视频渲染的 ICompositionSurface 中的像素绘制区域。

下图和代码所示为使用加载到 ICompositionSurface 的视频绘制的 SpriteVisual。

Compositor _compositor;
SpriteVisual _videoVisual;
CompositionSurfaceBrush _videoBrush;

// MediaPlayer set up with a create from URI

_mediaPlayer = new MediaPlayer();

// Get a source from a URI. This could also be from a file via a picker or a stream
var source = MediaSource.CreateFromUri(new Uri("https://go.microsoft.com/fwlink/?LinkID=809007&clcid=0x409"));
var item = new MediaPlaybackItem(source);
_mediaPlayer.Source = item;
_mediaPlayer.IsLoopingEnabled = true;

// Get the surface from MediaPlayer and put it on a brush
_videoSurface = _mediaPlayer.GetSurface(_compositor);
_videoBrush = _compositor.CreateSurfaceBrush(_videoSurface.CompositionSurface);

_videoVisual = _compositor.CreateSpriteVisual();
_videoVisual.Brush = _videoBrush;
_videoVisual.Size = new Vector2(156, 156);

使用过滤效果绘制

CompositionEffectBrush 使用 CompositionEffect 输出绘制区域。 可视化层中的效果可以制作应用到源内容集合的可进行动画设置的过滤效果,如颜色、渐变、图像、视频、交换链、UI 区域或视觉对象树。 源内容通常使用其他 CompositionBrush 指定。

下图和代码所示为使用已应用去饱和度过滤效果的猫图像绘制的 SpriteVisual。

CompositionEffectBrush

Compositor _compositor;
SpriteVisual _effectVisual;
CompositionEffectBrush _effectBrush;

_compositor = Window.Current.Compositor;

var graphicsEffect = new SaturationEffect {
                              Saturation = 0.0f,
                              Source = new CompositionEffectSourceParameter("mySource")
                         };

var effectFactory = _compositor.CreateEffectFactory(graphicsEffect);
_effectBrush = effectFactory.CreateBrush();

CompositionSurfaceBrush surfaceBrush =_compositor.CreateSurfaceBrush();
LoadedImageSurface loadedSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Assets/cat.jpg"));
SurfaceBrush.surface = loadedSurface;

_effectBrush.SetSourceParameter("mySource", surfaceBrush);

_effectVisual = _compositor.CreateSpriteVisual();
_effectVisual.Brush = _effectBrush;
_effectVisual.Size = new Vector2(156, 156);

有关使用 CompositionBrush 创建效果的详细信息,请参阅可视化层中的效果

使用已应用不透明蒙板的 CompositionBrush 绘制

CompositionMaskBrush 使用已应用不透明度蒙板的 CompositionBrush 绘制区域。 不透明度蒙板源可以为 CompositionColorBrush、CompositionLinearGradientBrush、CompositionSurfaceBrush、CompositionEffectBrush 或 CompositionNineGridBrush 类型的任何 CompositionBrush。 不透明度蒙板必须指定为 CompositionSurfaceBrush。

下图和代码所示为使用 CompositionMaskBrush 绘制的 SpriteVisual。 蒙板源为 CompositionLinearGradientBrush,蒙上后的效果如同使用圆圈图像的圆圈作为蒙板。

CompositionMaskBrush

Compositor _compositor;
SpriteVisual _maskVisual;
CompositionMaskBrush _maskBrush;

_compositor = Window.Current.Compositor;

_maskBrush = _compositor.CreateMaskBrush();

CompositionLinearGradientBrush _sourceGradient = _compositor.CreateLinearGradientBrush();
_sourceGradient.ColorStops.Add(_compositor.CreateColorGradientStop(0,Colors.Red));
_sourceGradient.ColorStops.Add(_compositor.CreateColorGradientStop(1,Colors.Yellow));
_maskBrush.Source = _sourceGradient;

LoadedImageSurface loadedSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Assets/circle.png"), new Size(156.0, 156.0));
_maskBrush.Mask = _compositor.CreateSurfaceBrush(loadedSurface);

_maskVisual = _compositor.CreateSpriteVisual();
_maskVisual.Brush = _maskBrush;
_maskVisual.Size = new Vector2(156, 156);

使用九网格拉伸的 CompositionBrush 绘制

CompositionNineGridBrush 使用通过九网格形式拉伸的 CompositionBrush 绘制区域。 九网格形式支持将 CompositionBrush 的边缘和角拉伸成与其中心不同的形状。 九网格拉伸源可以是 CompositionColorBrush、CompositionSurfaceBrush 或 CompositionEffectBrush 类型的任何 CompositionBrush。

以下代码所示为使用 CompositionNineGridBrush 绘制的 SpriteVisual。 蒙板源为使用九网格拉伸的 CompositionSurfaceBrush。

Compositor _compositor;
SpriteVisual _nineGridVisual;
CompositionNineGridBrush _nineGridBrush;

_compositor = Window.Current.Compositor;

_ninegridBrush = _compositor.CreateNineGridBrush();

// nineGridImage.png is 50x50 pixels; nine-grid insets, as measured relative to the actual size of the image, are: left = 1, top = 5, right = 10, bottom = 20 (in pixels)

LoadedImageSurface _imageSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Assets/nineGridImage.png"));
_nineGridBrush.Source = _compositor.CreateSurfaceBrush(_imageSurface);

// set Nine-Grid Insets

_ninegridBrush.SetInsets(1, 5, 10, 20);

// set appropriate Stretch on SurfaceBrush for Center of Nine-Grid

sourceBrush.Stretch = CompositionStretch.Fill;

_nineGridVisual = _compositor.CreateSpriteVisual();
_nineGridVisual.Brush = _ninegridBrush;
_nineGridVisual.Size = new Vector2(100, 75);

使用背景像素绘制

CompositionBackdropBrush 使用区域后的内容绘制区域。 CompositionBackdropBrush 不可单独使用,但可用作其他 CompositionBrush(如 EffectBrush)的输入。 例如,通过将 CompositionBackdropBrush 用作模糊效果的输入,你可以实现霜冻玻璃效果。

以下代码所示为一个较小的可视化树,用于创建一个使用 CompositionSurfaceBrush 的图像并在该图像上覆盖霜冻的玻璃。 覆盖的霜冻玻璃通过在图像上放入具有 EffectBrush 填充效果的 SpriteVisual 创建。 EffectBrush 使用 CompositionBackdropBrush 作为模糊效果的输入。

Compositor _compositor;
SpriteVisual _containerVisual;
SpriteVisual _imageVisual;
SpriteVisual _backdropVisual;

_compositor = Window.Current.Compositor;

// Create container visual to host the visual tree
_containerVisual = _compositor.CreateContainerVisual();

// Create _imageVisual and add it to the bottom of the container visual.
// Paint the visual with an image.

CompositionSurfaceBrush _licoriceBrush = _compositor.CreateSurfaceBrush();

LoadedImageSurface loadedSurface = 
    LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Assets/licorice.jpg"));
_licoriceBrush.Surface = loadedSurface;

_imageVisual = _compositor.CreateSpriteVisual();
_imageVisual.Brush = _licoriceBrush;
_imageVisual.Size = new Vector2(156, 156);
_imageVisual.Offset = new Vector3(0, 0, 0);
_containerVisual.Children.InsertAtBottom(_imageVisual)

// Create a SpriteVisual and add it to the top of the containerVisual.
// Paint the visual with an EffectBrush that applies blur to the content
// underneath the Visual to create a frosted glass effect.

GaussianBlurEffect blurEffect = new GaussianBlurEffect(){
                                    Name = "Blur",
                                    BlurAmount = 1.0f,
                                    BorderMode = EffectBorderMode.Hard,
                                    Source = new CompositionEffectSourceParameter("source");
                                    };

CompositionEffectFactory blurEffectFactory = _compositor.CreateEffectFactory(blurEffect);
CompositionEffectBrush _backdropBrush = blurEffectFactory.CreateBrush();

// Create a BackdropBrush and bind it to the EffectSourceParameter source

_backdropBrush.SetSourceParameter("source", _compositor.CreateBackdropBrush());
_backdropVisual = _compositor.CreateSpriteVisual();
_backdropVisual.Brush = _licoriceBrush;
_backdropVisual.Size = new Vector2(78, 78);
_backdropVisual.Offset = new Vector3(39, 39, 0);
_containerVisual.Children.InsertAtTop(_backdropVisual);

组合 CompositionBrush

许多 CompositionBrushes 使用其他 CompositionBrushes 作为输入。 例如,使用 SetSourceParameter 方法可以将其他 CompositionBrush 设为 CompositionEffectBrush 的输入。 下表列出了受支持的 CompositionBrush 组合。 请注意,使用不受支持的组合将会引发异常。

Brush EffectBrush.SetSourceParameter() MaskBrush.Mask MaskBrush.Source NineGridBrush.Source
CompositionColorBrush YES YES YES YES
CompositionLinear
GradientBrush
YES YES YES
CompositionSurfaceBrush YES YES YES YES
CompositionEffectBrush YES
CompositionMaskBrush
CompositionNineGridBrush YES YES YES
CompositionBackdropBrush YES

使用 XAML 画笔与 CompositionBrush

下表提供了方案列表以及在应用程序中绘制 UIElement 或 SpriteVisual 时是规定使用 XAML 画笔还是合成画笔。

注意

如果建议为 XAML UIElement 使用 CompositionBrush,则假定 CompositionBrush 是使用 XamlCompositionBrushBase 打包。

场景 XAML UIElement 合成 SpriteVisual
使用纯色绘制区域 SolidColorBrush CompositionColorBrush
使用动画颜色绘制区域 SolidColorBrush CompositionColorBrush
使用静态渐变绘制区域 LinearGradientBrush CompositionLinearGradientBrush
使用动画渐变起止颜色绘制区域 CompositionLinearGradientBrush CompositionLinearGradientBrush
使用图像绘制区域 ImageBrush CompositionSurfaceBrush
使用网页绘制区域 WebViewBrush 空值
使用九网格拉伸的图像绘制区域 图像控制 CompositionNineGridBrush
使用动画九网格拉伸绘制区域 CompositionNineGridBrush CompositionNineGridBrush
使用交换链绘制区域 SwapChainPanel 带交换链互操作的 CompositionSurfaceBrush
使用视频绘制区域 MediaElement 带媒体互操作的 CompositionSurfaceBrush
使用自定义 2D 绘图绘制区域 Win2D 中的 CanvasControl 带 Win2D 互操作的 CompositionSurfaceBrush
使用非动画蒙板绘制区域 使用 XAML 形状定义蒙板 CompositionMaskBrush
使用动画蒙板绘制区域 CompositionMaskBrush CompositionMaskBrush
使用动画过滤效果绘制区域 CompositionEffectBrush CompositionEffectBrush
使用应用于背景像素的效果绘制区域 CompositionBackdropBrush CompositionBackdropBrush

带有 BeginDraw 和 EndDraw 的合成本机 DirectX 和 Direct2D 互操作性

与 XamlCompositionBrushBase 进行的 XAML 画笔互操作