Condividi tramite


Pennelli di composizione

Tutto ciò che è visibile sullo schermo in un'app WinUI è visibile perché è stato disegnato da un pennello. I pennelli consentono di disegnare oggetti dell'interfaccia utente con contenuti che vanno da semplici colori a tinta unita a immagini, disegni e catene di effetti complesse. Questo argomento presenta i concetti relativi alla pittura con CompositionBrush.

Quando si usa un'app XAML WinUI, è possibile scegliere di disegnare un oggetto UIElement con un pennello XAML o compositionBrush. In genere, è più facile scegliere un pennello XAML se lo scenario è già supportato da uno. Ad esempio, animare il colore di un pulsante o modificare il riempimento di testo o una forma con un'immagine. Se hai bisogno di qualcosa che non è supportato da un pennello XAML, ad esempio una maschera animata, un tratto di nove griglie animato o una catena di effetti, puoi usare compositionBrush per disegnare un oggetto UIElement tramite XamlCompositionBrushBase.

Quando si lavora con il Visual layer, è necessario usare un CompositionBrush per riempire l'area di un SpriteVisual.

Prerequisiti

Questa panoramica presuppone che tu abbia familiarità con la struttura di un'applicazione Composition di base, come descritto nella panoramica del livello visivo.

Dipingi con un CompositionBrush

Un oggetto CompositionBrush "colora" un'area con il suo output. I pennelli diversi hanno tipi diversi di output. Alcuni pennelli disegnano un'area con un colore a tinta unita, altre con sfumatura, immagine, disegno personalizzato o 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 dipinta da un oggetto CompositionBrush, oppure una griglia a nove riquadri può essere utilizzata per controllare l'estensione applicata a un oggetto CompositionBrush quando si colora un'area. CompositionBrush può essere di uno dei tipi seguenti:

Classe dettagli
CompositionColorBrush Disegna un'area con un colore a tinta unita
CompositionSurfaceBrush Disegna un'area con il contenuto di un ICompositionSurface
CompositionEffectBrush Disegna un'area con il contenuto di un effetto di composizione
CompositionMaskBrush Disegna un elemento visivo con un CompositionBrush con una maschera di opacità
CompositionNineGridBrush Disegna un'area con un oggetto CompositionBrush usando un'estensione NineGrid
CompositionLinearGradientBrush Disegna un'area con una sfumatura lineare
CompositionRadialGradientBrush Disegna un'area con una sfumatura radiale
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

Dipingere 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 = ElementCompositionPreview.GetElementVisual(this).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 CompositionLinearGradientBrush pittura 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 utilizzati per specificare i colori del gradiente e le loro posizioni.

La figura e il codice seguenti illustrano un oggetto SpriteVisual disegnato con un LinearGradientBrush con 2 stop, uno rosso e uno giallo.

CompositionLinearGradientBrush

Compositor _compositor;
SpriteVisual _gradientVisual;
CompositionLinearGradientBrush _redyellowBrush;

_compositor = ElementCompositionPreview.GetElementVisual(this).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 illustrano un oggetto SpriteVisual pitturato con un RadialGradientBrush con 2 GradientStops.

CompositionRadialGradientBrush

Compositor _compositor;
SpriteVisual _gradientVisual;
CompositionRadialGradientBrush RGBrush;

_compositor = ElementCompositionPreview.GetElementVisual(this).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

CompositionSurfaceBrush dipinge un'area con pixel renderizzati su un ICompositionSurface. Ad esempio, un oggetto CompositionSurfaceBrush può essere usato per disegnare un'area con un'immagine sottoposta a rendering in un oggetto ICompositionSurface usando l'API LoadedImageSurface .

La figura e il codice seguenti mostrano uno SpriteVisual, dipinto con una bitmap di una liquirizia, renderizzata su un 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 = ElementCompositionPreview.GetElementVisual(this).Compositor;

_imageBrush = _compositor.CreateSurfaceBrush();

// The loadedSurface has a size of 0x0 till the image has 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);

Dipingi 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 uno SpriteVisual dipinto con un testo eseguito su una ICompositionSurface utilizzando Win2D. Per usare Win2D con WinUI, installare il pacchetto NuGet Microsoft.Graphics.Win2D nel progetto.

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

_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
_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 per disegnare un SpriteVisual con una SwapChain tramite l'interoperabilità di Win2D. Questo esempio fornisce un esempio di come usare Win2D per disegnare un oggetto SpriteVisual con una swap chain.

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 dipinto con un video caricato su un oggetto ICompositionSurface.

Compositor _compositor;
SpriteVisual _videoVisual;
CompositionSurfaceBrush _videoBrush;

_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;

// MediaPlayer setup with a source URI.
_mediaPlayer = new MediaPlayer();

// Get a source from a URI. This could also come from a file 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);

Dipingi con un effetto filtro

Un oggetto 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 = ElementCompositionPreview.GetElementVisual(this).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 CompositionBrush con maschera di opacità applicata

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 un cerchio come maschera.

CompositionMaskBrush

Compositor _compositor;
SpriteVisual _maskVisual;
CompositionMaskBrush _maskBrush;

_compositor = ElementCompositionPreview.GetElementVisual(this).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 oggetto CompositionNineGridBrush disegna un'area con un oggetto 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. La sorgente dell'estensione a nove griglie può essere 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 a nove.

Compositor _compositor;
SpriteVisual _nineGridVisual;
CompositionNineGridBrush _nineGridBrush;

_compositor = ElementCompositionPreview.GetElementVisual(this).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"));
CompositionSurfaceBrush sourceBrush = _compositor.CreateSurfaceBrush(_imageSurface);
_nineGridBrush.Source = sourceBrush;

// Set nine-grid insets.
_nineGridBrush.SetInsets(1, 5, 10, 20);

// Set the appropriate stretch on the SurfaceBrush for the center of the nine-grid.
sourceBrush.Stretch = CompositionStretch.Fill;

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

Disegnare usando pixel di sfondo

CompositionBackdropBrush disegna un'area con il contenuto che si trova dietro di essa. 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 ghiacciato.

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

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

_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;

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

// Create _imageVisual and add it to the bottom of the container visual.
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 container visual.
// Paint the visual with an EffectBrush that applies blur to the content underneath it.
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 = _backdropBrush;
_backdropVisual.Size = new Vector2(78, 78);
_backdropVisual.Offset = new Vector3(39, 39, 0);
_containerVisual.Children.InsertAtTop(_backdropVisual);

Combinazione di CompositionBrush

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

Pennello EffectBrush.SetSourceParameter() MaskBrush.Mask MaskBrush.Source NineGridBrush.Source
CompositionColorBrush
CompositionLinear
GradientBrush
NO
CompositionSurfaceBrush
CompositionEffectBrush NO NO NO
PennelloMascheraComposizione 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.

Annotazioni

Se per un elemento UIElement XAML viene suggerito un CompositionBrush, si presuppone che il CompositionBrush sia impacchettato usando XamlCompositionBrushBase.

Scenario XAML UIElement Composizione SpriteVisual
Pitturare un'area con tinta unita SolidColorBrush CompositionColorBrush
Disegnare un'area con colore animato SolidColorBrush CompositionColorBrush
Dipingere un'area con una sfumatura statica LinearGradientBrush CompositionLinearGradientBrush
Disegnare un'area con stop di gradiente animati CompositionLinearGradientBrush CompositionLinearGradientBrush
Disegnare un'area con un'immagine Imagebrush CompositionSurfaceBrush
Colorare un'area utilizzando una pagina Web WebView2 N/A
Disegnare un'area con un'immagine usando l'estensione NineGrid Controllo immagine CompositionNineGridBrush
Disegnare un'area con il NineGrid stretch animato CompositionNineGridBrush CompositionNineGridBrush
Disegnare un'area con un swapchain SwapChainPanel Interoperabilità CompositionSurfaceBrush con interoperabilità di swapchain
Disegnare un'area con un video MediaPlayerElement CompositionSurfaceBrush con interoperabilità multimediale
Disegnare un'area con disegno 2D personalizzato CanvasControl da Win2D Interoperabilità CompositionSurfaceBrush con Win2D
Disegnare un'area con maschera non animata Usare forme XAML per definire una maschera CompositionMaskBrush
Disegnare un'area con una maschera 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

Composizione nativa di DirectX e interoperabilità Direct2D con BeginDraw e EndDraw

Interoperabilità del pennello XAML con XamlCompositionBrushBase