Pennelli di composizione

Tutto ciò che è visibile sullo schermo da un'applicazione UWP è visibile perché è stato disegnato da un pennello. I pennelli consentono di disegnare oggetti dell'interfaccia utente con contenuto che va da colori semplici a tinta unita a immagini o disegni a catena di effetti complessi. Questo argomento presenta i concetti relativi alla pittura con CompositionBrush.

Si noti che, quando si usa l'app UWP XAML, è possibile scegliere di disegnare un oggetto UIElement con un pennello XAML o con un oggetto CompositionBrush. In genere, è più semplice e consigliabile scegliere un pennello XAML se lo scenario è supportato da un pennello XAML. Ad esempio, animando il colore di un pulsante oppure modificando il riempimento di un testo o una forma con un'immagine. D'altra parte, se si sta provando a fare qualcosa che non è supportato da un pennello XAML come disegnare con una maschera animata o un tratto di griglia a nove animato o una catena di effetti, è possibile usare un oggetto CompositionBrush per disegnare un oggetto UIElement tramite XamlCompositionBrushBase.

Quando si lavora con il livello Visual, è necessario usare un oggetto CompositionBrush per disegnare l'area di un oggetto SpriteVisual.

Prerequisiti

Questa panoramica presuppone di avere familiarità con la struttura di un'applicazione Composition di base, come descritto nella panoramica sul livello Visual.

Disegnare con un oggetto CompositionBrush

Un oggetto CompositionBrush "disegna" un'area con il relativo output. Tipi di pennelli diversi producono output diversi. Alcuni pennelli disegnano un'area con un colore a tinta unita, altre con una sfumatura, un'immagine, un disegno personalizzato o un effetto. Esistono anche pennelli specializzati che modificano il comportamento di altri pennelli. Ad esempio, la maschera di opacità può essere usata per controllare l'area disegnata da un oggetto CompositionBrush o una griglia a nove per controllare l'estensione applicata a un oggetto CompositionBrush quando si disegna un'area. CompositionBrush può essere di uno dei tipi seguenti:

Classe Dettagli Introdotto in
CompositionColorBrush Disegna un'area con un colore a tinta unita Windows 10 versione 1511 (SDK 10586)
CompositionSurfaceBrush Disegna un'area con il contenuto di un oggetto ICompositionSurface Windows 10 versione 1511 (SDK 10586)
CompositionEffectBrush Disegna un'area con il contenuto di un effetto di composizione Windows 10 versione 1511 (SDK 10586)
CompositionMaskBrush Disegna un oggetto visivo con un oggetto CompositionBrush con una maschera di opacità Windows 10 versione 1607 (SDK 14393)
CompositionNineGridBrush Disegna un'area con un oggetto CompositionBrush usando un'estensione NineGrid Windows 10 versione 1607 (SDK 14393)
CompositionLinearGradientBrush Disegna un'area con una sfumatura lineare Windows 10 versione 1709 (SDK 16299)
CompositionRadialGradientBrush Disegna un'area con una sfumatura radiale Windows 10 versione 1903 (Insider Preview SDK)
CompositionBackdropBrush Disegna un'area eseguendo il campionamento dei pixel di sfondo dall'applicazione o dai pixel direttamente dietro la finestra dell'applicazione sul desktop. Usato come input per un altro CompositionBrush come compositionEffectBrush Windows 10 versione 1607 (SDK 14393)

Disegnare con un colore a tinta unita

Un oggetto CompositionColorBrush disegna un'area con un colore a tinta unita. Esistono diversi modi per specificare il colore di un oggetto SolidColorBrush. Ad esempio, è possibile specificare i relativi canali alfa, rosso, blu e verde (ARGB) o usare uno dei colori predefiniti forniti dalla classe Colors.

La figura e il codice seguenti illustrano una piccola struttura ad albero visuale per creare un rettangolo tratto con un pennello di colore nero e disegnato con un pennello a tinta unita con il valore di colore 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);

Disegnare con una sfumatura lineare

Un oggetto CompositionLinearGradientBrush disegna un'area con una sfumatura lineare. Una sfumatura lineare fonde due o più colori su una linea, l'asse delle sfumature. Gli oggetti GradientStop vengono usati per specificare i colori nella sfumatura e le relative posizioni.

La figura e il codice seguenti illustrano un oggetto SpriteVisual disegnato con linearGradientBrush con 2 arresti usando un colore rosso e giallo.

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);

Disegnare con una sfumatura radiale

Un oggetto CompositionRadialGradientBrush disegna un'area con una sfumatura radiale. Una sfumatura radiale fonde due o più colori con la sfumatura a partire dal centro dell'ellisse e termina con il raggio dell'ellisse. Gli oggetti GradientStop vengono usati per definire i colori e la relativa posizione nella sfumatura.

La figura e il codice seguenti illustra un oggetto SpriteVisual disegnato con radialgradientBrush con 2 gradienti.

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);

Disegnare con un'immagine

Un oggetto CompositionSurfaceBrush disegna un'area con pixel di cui viene eseguito il rendering in un oggetto ICompositionSurface. Ad esempio, un oggetto CompositionSurfaceBrush può essere usato per disegnare un'area con un'immagine sottoposta a rendering su una superficie ICompositionSurface usando l'API LoadedImageSurface.

La figura e il codice seguenti illustrano un oggetto SpriteVisual disegnato con una bitmap di colore liquirizia di cui viene eseguito il rendering in un oggetto ICompositionSurface usando LoadedImageSurface. Le proprietà di CompositionSurfaceBrush possono essere usate per estendere e allineare la bitmap all'interno dei limiti dell'oggetto visivo.

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);

Disegnare con un disegno personalizzato

Un oggetto CompositionSurfaceBrush può essere usato anche per disegnare un'area con pixel da un oggetto ICompositionSurface sottoposto a rendering tramite Win2D (o D2D).

Il codice seguente mostra un oggetto SpriteVisual disegnato con una sequenza di testo di cui è stato eseguito il rendering in un oggetto ICompositionSurface usando Win2D. Si noti che per usare Win2D è necessario includere il pacchetto NuGet Win2D nel progetto.

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);

Analogamente, CompositionSurfaceBrush può essere usato anche per disegnare uno SpriteVisual con interoperabilità Win2D con SwapChain. Questo esempio spiega come usare Win2D per disegnare un oggetto SpriteVisual con una swapchain.

Disegnare con un video

Un CompositionSurfaceBrush può essere usato anche per disegnare un'area con pixel da un oggetto ICompositionSurface sottoposto a rendering usando un video caricato tramite la classe MediaPlayer.

Il codice seguente mostra un oggetto SpriteVisual disegnato con un video caricato in un oggetto ICompositionSurface.

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);

Disegnare con un effetto filtro

Un CompositionEffectBrush disegna un'area con output di CompositionEffect. Gli effetti nel livello visivo possono essere considerati come effetti di filtro animabili applicati a una raccolta di contenuti di origine, ad esempio colori, sfumature, immagini, video, swapchain, aree dell'interfaccia utente o alberi degli oggetti visivi. Il contenuto di origine viene in genere specificato usando un altro CompositionBrush.

La figura e il codice seguenti illustrano un oggetto SpriteVisual disegnato con un'immagine di un gatto con effetto filtro di desaturazione applicato.

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);

Per altre informazioni sulla creazione di un effetto tramite CompositionBrushes, vedere Effetti nel livello visivo

Disegnare con un oggetto CompositionBrush con una maschera di opacità applicata

Un CompositionMaskBrush disegna un'area con un CompositionBrush con una maschera di opacità applicata. L'origine della maschera di opacità può essere qualsiasi CompositionBrush di tipo CompositionColorBrush, CompositionLinearGradientBrush, CompositionSurfaceBrush, CompositionEffectBrush o CompositionNineGridBrush. La maschera di opacità deve essere specificata come CompositionSurfaceBrush.

La figura e il codice seguenti illustrano un oggetto SpriteVisual disegnato con CompositionMaskBrush. L'origine della maschera è un CompositionLinearGradientBrush che viene mascherato per apparire come un cerchio usando un'immagine di cerchio come maschera.

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);

Disegnare con un oggetto CompositionBrush usando l'estensione NineGrid

Un CompositionNineGridBrush disegna un'area con un CompositionBrush esteso usando la metafora a nove griglie. La metafora a nove griglie consente di estendere i bordi e gli angoli di un CompositionBrush in modo diverso rispetto al suo centro. L'origine dell'estensione a nove griglie può essere eseguita da qualsiasi CompositionBrush di tipo CompositionColorBrush, CompositionSurfaceBrush o CompositionEffectBrush.

Il codice seguente mostra un oggetto SpriteVisual disegnato con CompositionNineGridBrush. L'origine della maschera è un CompositionSurfaceBrush che viene esteso usando una griglia Nine.

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);

Disegnare con pixel di sfondo

Un CompositionBackdropBrush disegna un'area con il contenuto dietro l'area. Un CompositionBackdropBrush non viene mai usato autonomamente, ma viene invece usato come input per un altro CompositionBrush come EffectBrush. Ad esempio, usando CompositionBackdropBrush come input per un effetto sfocatura, è possibile ottenere un effetto vetro smerigliato.

Il codice seguente mostra una piccola struttura ad albero visuale per creare un'immagine usando CompositionSurfaceBrush e una sovrimpressione di vetro smerigliato sopra l'immagine. La sovrimpressione di vetro smerigliato viene creata posizionando uno SpriteVisual pieno di EffectBrush sopra l'immagine. EffectBrush usa CompositionBackdropBrush come input per l'effetto sfocatura.

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);

Combinazione di CompositionBrushes

Alcuni oggetti CompositionBrushes usano altri oggetti CompositionBrushes come input. Ad esempio, l'uso del metodo SetSourceParameter può essere usato per impostare un altro CompositionBrush come input su CompositionEffectBrush. La tabella seguente illustra le combinazioni supportate di CompositionBrushes. Si noti che l'uso di una combinazione non supportata genererà un'eccezione.

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

Uso di un pennello XAML e di CompositionBrush

La tabella seguente fornisce un elenco di scenari e indica se è previsto l'uso del pennello XAML o Composition quando si disegna un oggetto UIElement o SpriteVisual nell'applicazione.

Nota

Se per un oggetto UIElement XAML viene suggerito un oggetto CompositionBrush, si presuppone che CompositionBrush venga creato in un pacchetto usando XamlCompositionBrushBase.

Scenario XAML UIElement SpriteVisual di composizione
Disegnare un'area con un colore a tinta unita SolidColorBrush CompositionColorBrush
Disegnare un'area con un colore animato SolidColorBrush CompositionColorBrush
Disegnare un'area con una sfumatura statica LinearGradientBrush CompositionLinearGradientBrush
Disegnare un'area con interruzioni sfumature animate CompositionLinearGradientBrush CompositionLinearGradientBrush
Disegnare un'area con un'immagine ImageBrush CompositionSurfaceBrush
Disegnare un'area con una pagina Web WebViewBrush N/D
Disegnare un'area con un'immagine usando l'estensione NineGrid Controllo Image CompositionNineGridBrush
Disegnare un'area con estensione NineGrid animata CompositionNineGridBrush CompositionNineGridBrush
Disegnare un'area con una swapchain SwapChainPanel CompositionSurfaceBrush con interoperabilità swapchain
Disegnare un'area con un video MediaElement CompositionSurfaceBrush con interoperabilità multimediale
Disegnare un'area con un disegno 2D CanvasControl da Win2D CompositionSurfaceBrush con interoperabilità Win2D
Disegnare un'area con una maschera non animata Usare forme XAML per definire una maschera CompositionMaskBrush
Disegnare un'area con una maschera non animata CompositionMaskBrush CompositionMaskBrush
Disegnare un'area con un effetto filtro animato CompositionEffectBrush CompositionEffectBrush
Disegnare un'area con un effetto applicato ai pixel di sfondo CompositionBackdropBrush CompositionBackdropBrush

Interoperabilità DirectX e Direct2D nativa della composizione con BeginDraw e EndDraw

Interoperabilità del pennello XAML con XamlCompositionBrushBase