Delen via


Mica- of Acrylmaterialen toepassen in desktop-apps voor Windows 11

Materialen in Windows 11 zijn visuele effecten die worden toegepast op UX-oppervlakken die lijken op echte artefacten. Afsluitende materialen, zoals mica en acryl, worden gebruikt als basislagen onder interactieve gebruikersinterface-elementen.

Mica is een ondoorzichtig materiaal dat het thema en de bureaubladachtergrond van de gebruiker bevat om een zeer gepersonaliseerde uitstraling te creëren. Mica is ontworpen voor prestaties, omdat het achtergrondachtergrond slechts eenmaal vastlegt om de visualisatie te maken. Daarom raden we het aan voor de basislaag van uw app, met name in het titelbalkgebied.

Acryl is een semitransparant materiaal dat het effect van vorstglas repliceert. Het wordt alleen gebruikt voor tijdelijke, licht-sluiten oppervlakken zoals flyouts en contextmenu's.

In dit artikel wordt beschreven hoe u Mica of Acryl toepast als de basislaag van uw Windows App SDK/WinUI 3 XAML-app.

Notitie

Hoe een achtergrondmateriaal te gebruiken

De WinUI 3 Gallery app bevat interactieve voorbeelden van de meeste Besturingselementen, functies en functionaliteit van WinUI 3. Download de app uit de Microsoft Store of haal de broncode op GitHub-

Als u Mica of Acrylmateriaal wilt toepassen op uw app, stelt u de eigenschap SystemBackdrop in op een XAML-SystemBackdrop- (meestal een van de ingebouwde achtergronden, MicaBackdrop of DesktopAcrylicBackdrop).

Deze elementen hebben een eigenschap SystemBackdrop:

In deze voorbeelden ziet u hoe u de achtergrond van het systeem instelt in XAML en in code.

Mica

Mica wordt meestal gebruikt als achtergrond voor een app-venster.

<Window
    ... >

    <Window.SystemBackdrop>
        <MicaBackdrop Kind="BaseAlt"/>
    </Window.SystemBackdrop>

</Window>
public MainWindow()
{
    this.InitializeComponent();

    SystemBackdrop = new MicaBackdrop() 
                        { Kind = MicaKind.BaseAlt };
}

Acryl

Acryl wordt meestal gebruikt als achtergrond voor tijdelijke gebruikersinterface, zoals een flyout.

<Flyout
    ... >

    <Flyout.SystemBackdrop>
        <DesktopAcrylicBackdrop/>
    </Flyout.SystemBackdrop>
</Flyout>
Flyout flyout = new Flyout()
{
    SystemBackdrop = new DesktopAcrylicBackdrop()
};

Een systeemachtergrondcontroller gebruiken

Notitie

Vanaf Windows App SDK 1.3 kunt u materiaal toepassen door de eigenschap Window.SystemBackdrop in te stellen op een XAML-SystemBackdrop zoals beschreven in de vorige sectie. Dit is de aanbevolen manier om een materiaal toe te passen.

In de rest van dit artikel ziet u hoe u de Samenstelling MicaController en DesktopAcrylicController API's gebruikt.

Als u een achtergrondmateriaal in uw app wilt gebruiken, kunt u een van de controllers gebruiken waarmee de interface ISystemBackdropController (MicaController of DesktopAcrylicController) wordt geïmplementeerd. Deze klassen beheren zowel het weergeven van het systeemachtergrondmateriaal als de verwerking van systeembeleid voor het materiaal.

Als u Mica als achtergrondmateriaal wilt gebruiken, maakt u een MicaController object. Als u Acryl wilt gebruiken, maakt u een DesktopAcrylicController object. De instel- en ondersteunende code is hetzelfde voor elk type achtergrondmateriaal van het systeem.

Deze code laat zien hoe u een MicaControllermaakt.

MicaController m_backdropController;

bool TrySetSystemBackdrop()
{
    if (MicaController.IsSupported())
    {
        ...
        m_backdropController = new MicaController();
        ...
    }
}
// namespace MUCSB = Microsoft::UI::Composition::SystemBackdrops;

winrt::MUCSB::MicaController m_backdropController{ nullptr };

void SetBackground()
{
    if (winrt::MUCSB::MicaController::IsSupported())
    {
        ...
        m_backdropController = winrt::MUCSB::MicaController();
        ...
    }
}

Als u de Mica Alt-variant van Mica wilt gebruiken, maakt u een MicaController object en stelt u de eigenschap Kind in op MicaKind.BaseAlt-.

MicaController m_backdropController;

bool TrySetSystemBackdrop()
{
    if (MicaController.IsSupported())
    {
        ...
        m_backdropController = new MicaController()
        {
            Kind = MicaKind.BaseAlt
        };
        ...
    }
}
// namespace MUCSB = Microsoft::UI::Composition::SystemBackdrops;

winrt::MUCSB::MicaController m_backdropController{ nullptr };

void SetBackground()
{
    if (winrt::MUCSB::MicaController::IsSupported())
    {
        ...
        m_backdropController = winrt::MUCSB::MicaController();
        m_backdropController.Kind(winrt::MUCSB::MicaKind::BaseAlt);
        ...
    }
}

Deze code laat zien hoe u een DesktopAcrylicControllermaakt.

DesktopAcrylicController m_backdropController;

bool TrySetSystemBackdrop()
{
    if (DesktopAcrylicController.IsSupported())
    {
        ...
        m_backdropController = new DesktopAcrylicController();
        ...
    }
}
// namespace MUCSB = Microsoft::UI::Composition::SystemBackdrops;

winrt::MUCSB::DesktopAcrylicController m_backdropController{ nullptr };

void SetBackground()
{
    if (winrt::MUCSB::DesktopAcrylicController::IsSupported())
    {
        ...
        m_backdropController = winrt::MUCSB::DesktopAcrylicController();
        ...
    }
}

De controller reageert standaard op de licht- en donkere thema's van het systeem. Als u dit gedrag wilt overschrijven, kunt u de volgende eigenschappen instellen op de controller:

Notitie

Nadat u een van de vier eigenschappen van de controller hebt aangepast, worden de standaardwaarden licht of donker niet meer toegepast wanneer de bijbehorende SystemBackdropConfiguration.Theme wordt gewijzigd. U moet deze eigenschappen handmatig bijwerken zodat deze overeenkomen met het nieuwe thema.

Als u het achtergrondmateriaal in uw app wilt gebruiken, zijn de volgende items vereist:

  • System-ondersteuning

    Het systeem waarop de app wordt uitgevoerd, moet het achtergrondmateriaal ondersteunen. Roep de methode MicaController.IsSupported of DesktopAcrylicController.IsSupported aan om ervoor te zorgen dat het achtergrondmateriaal tijdens runtime wordt ondersteund.

  • een geldig doel

    U moet een doel opgeven waarmee de interface ICompositionSupportsSystemBackdrop wordt geïmplementeerd. In een XAML-app implementeert het XAML-Window deze interface en wordt deze gebruikt als achtergronddoel.

  • een SystemBackdropConfiguration-object

    De SystemBackdropConfiguration biedt de systeemachtergrondcontroller met app-specifieke beleidsinformatie om het achtergrondmateriaal van het systeem correct te configureren.

  • een DispatcherQueue-object.

    U hebt een beschikbare Windows.System.DispatcherQueue- nodig op de belangrijkste XAML-thread. Zie de klasse WindowsSystemDispatcherQueueHelper in de voorbeeldcode of in het WinUI 3 Gallery-voorbeeld.

Voorbeeld: Mica gebruiken in een Windows AppSDK/WinUI 3-app

In dit voorbeeld ziet u hoe u het Mica-achtergrondmateriaal instelt in een XAML-app.

Fooi

Bekijk ook deze voorbeeldprojecten op GitHub:

C#: SampleSystemBackdropsWindow in de WinUI3 Gallery.

C++/WinRT: Windows App SDK Mica-voorbeeld.

using Microsoft.UI.Composition.SystemBackdrops;
using Microsoft.UI.Xaml;
using System.Runtime.InteropServices; // For DllImport
using WinRT; // required to support Window.As<ICompositionSupportsSystemBackdrop>()

public sealed partial class MainWindow : Window
{
    WindowsSystemDispatcherQueueHelper m_wsdqHelper; // See below for implementation.
    MicaController m_backdropController;
    SystemBackdropConfiguration m_configurationSource;

    public MainWindow()
    {
        this.InitializeComponent();

        TrySetSystemBackdrop();
    }

    bool TrySetSystemBackdrop()
    {
        if (Microsoft.UI.Composition.SystemBackdrops.MicaController.IsSupported())
        {
            m_wsdqHelper = new WindowsSystemDispatcherQueueHelper();
            m_wsdqHelper.EnsureWindowsSystemDispatcherQueueController();

            // Create the policy object.
            m_configurationSource = new SystemBackdropConfiguration();
            this.Activated += Window_Activated;
            this.Closed += Window_Closed;
            ((FrameworkElement)this.Content).ActualThemeChanged += Window_ThemeChanged;

            // Initial configuration state.
            m_configurationSource.IsInputActive = true;
            SetConfigurationSourceTheme();

            m_backdropController = new Microsoft.UI.Composition.SystemBackdrops.MicaController();

            // Enable the system backdrop.
            // Note: Be sure to have "using WinRT;" to support the Window.As<...>() call.
            m_backdropController.AddSystemBackdropTarget(this.As<Microsoft.UI.Composition.ICompositionSupportsSystemBackdrop>());
            m_backdropController.SetSystemBackdropConfiguration(m_configurationSource);
            return true; // succeeded
        }

        return false; // Mica is not supported on this system
    }

    private void Window_Activated(object sender, WindowActivatedEventArgs args)
        {
            m_configurationSource.IsInputActive = args.WindowActivationState != WindowActivationState.Deactivated;
        }

    private void Window_Closed(object sender, WindowEventArgs args)
        {
            // Make sure any Mica/Acrylic controller is disposed
            // so it doesn't try to use this closed window.
            if (m_backdropController != null)
            {
                m_backdropController.Dispose();
                m_backdropController = null;
            }
            this.Activated -= Window_Activated;
            m_configurationSource = null;
        }

    private void Window_ThemeChanged(FrameworkElement sender, object args)
        {
            if (m_configurationSource != null)
            {
                SetConfigurationSourceTheme();
            }
        }

    private void SetConfigurationSourceTheme()
        {
            switch (((FrameworkElement)this.Content).ActualTheme)
            {
                case ElementTheme.Dark: m_configurationSource.Theme = Microsoft.UI.Composition.SystemBackdrops.SystemBackdropTheme.Dark; break;
                case ElementTheme.Light: m_configurationSource.Theme = Microsoft.UI.Composition.SystemBackdrops.SystemBackdropTheme.Light; break;
                case ElementTheme.Default: m_configurationSource.Theme = Microsoft.UI.Composition.SystemBackdrops.SystemBackdropTheme.Default; break;
            }
        }
}

class WindowsSystemDispatcherQueueHelper
{
    [StructLayout(LayoutKind.Sequential)]
    struct DispatcherQueueOptions
    {
        internal int dwSize;
        internal int threadType;
        internal int apartmentType;
    }

    [DllImport("CoreMessaging.dll")]
    private static extern int CreateDispatcherQueueController([In] DispatcherQueueOptions options, [In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object dispatcherQueueController);

    object m_dispatcherQueueController = null;
    public void EnsureWindowsSystemDispatcherQueueController()
    {
        if (Windows.System.DispatcherQueue.GetForCurrentThread() != null)
        {
            // one already exists, so we'll just use it.
            return;
        }

        if (m_dispatcherQueueController == null)
        {
            DispatcherQueueOptions options;
            options.dwSize = Marshal.SizeOf(typeof(DispatcherQueueOptions));
            options.threadType = 2;    // DQTYPE_THREAD_CURRENT
            options.apartmentType = 2; // DQTAT_COM_STA

            CreateDispatcherQueueController(options, ref m_dispatcherQueueController);
        }
    }
}
// pch.h
...
#include <winrt/Microsoft.UI.Composition.SystemBackdrops.h>
#include <winrt/Windows.System.h>
#include <dispatcherqueue.h>

// MainWindow.xaml.h
...
namespace winrt
{
    namespace MUC = Microsoft::UI::Composition;
    namespace MUCSB = Microsoft::UI::Composition::SystemBackdrops;
    namespace MUX = Microsoft::UI::Xaml;
    namespace WS = Windows::System;
}
...
struct MainWindow : MainWindowT<MainWindow>
{
    winrt::MUCSB::SystemBackdropConfiguration m_configuration{ nullptr };
    winrt::MUCSB::MicaController m_backdropController{ nullptr };
    winrt::MUX::Window::Activated_revoker m_activatedRevoker;
    winrt::MUX::Window::Closed_revoker m_closedRevoker;
    winrt::MUX::FrameworkElement::ActualThemeChanged_revoker m_themeChangedRevoker;
    winrt::MUX::FrameworkElement m_rootElement{ nullptr };
    winrt::WS::DispatcherQueueController m_dispatcherQueueController{ nullptr };

    MainWindow::MainWindow()
    {
        InitializeComponent();

        SetBackground();

        m_closedRevoker = this->Closed(winrt::auto_revoke, [&](auto&&, auto&&)
        {
            if (nullptr != m_backdropController)
            {
                m_backdropController.Close();
                m_backdropController = nullptr;
            }

            if (nullptr != m_dispatcherQueueController)
            {
                m_dispatcherQueueController.ShutdownQueueAsync();
                m_dispatcherQueueController = nullptr;
            }
        });
    }

    void SetBackground()
    {
        if (winrt::MUCSB::MicaController::IsSupported())
        {
            // We ensure that there is a Windows.System.DispatcherQueue on the current thread.
            // Always check if one already exists before attempting to create a new one.
            if (nullptr == winrt::WS::DispatcherQueue::GetForCurrentThread() &&
                nullptr == m_dispatcherQueueController)
            {
                m_dispatcherQueueController = CreateSystemDispatcherQueueController();
            }

            // Setup the SystemBackdropConfiguration object.
            SetupSystemBackdropConfiguration();

            // Setup Mica on the current Window.
            m_backdropController = winrt::MUCSB::MicaController();
            m_backdropController.SetSystemBackdropConfiguration(m_configuration);
            m_backdropController.AddSystemBackdropTarget(
                this->m_inner.as<winrt::MUC::ICompositionSupportsSystemBackdrop>());
        }
        else
        {
            // The backdrop material is not supported.
        }
    }

    winrt::WS::DispatcherQueueController CreateSystemDispatcherQueueController()
    {
        DispatcherQueueOptions options
        {
            sizeof(DispatcherQueueOptions),
            DQTYPE_THREAD_CURRENT,
            DQTAT_COM_NONE
        };

        ::ABI::Windows::System::IDispatcherQueueController* ptr{ nullptr };
        winrt::check_hresult(CreateDispatcherQueueController(options, &ptr));
        return { ptr, take_ownership_from_abi };
    }

    void SetupSystemBackdropConfiguration()
    {
        m_configuration = winrt::MUCSB::SystemBackdropConfiguration();

        // Activation state.
        m_activatedRevoker = this->Activated(winrt::auto_revoke,
            [&](auto&&, MUX::WindowActivatedEventArgs const& args)
            {
                m_configuration.IsInputActive(
                    winrt::MUX::WindowActivationState::Deactivated != args.WindowActivationState());
            });

        // Initial state.
        m_configuration.IsInputActive(true);

        // Application theme.
        m_rootElement = this->Content().try_as<winrt::MUX::FrameworkElement>();
        if (nullptr != m_rootElement)
        {
            m_themeChangedRevoker = m_rootElement.ActualThemeChanged(winrt::auto_revoke,
                [&](auto&&, auto&&)
                {
                    m_configuration.Theme(
                        ConvertToSystemBackdropTheme(m_rootElement.ActualTheme()));
                });

            // Initial state.
            m_configuration.Theme(
                ConvertToSystemBackdropTheme(m_rootElement.ActualTheme()));
        }
    }

    winrt::MUCSB::SystemBackdropTheme ConvertToSystemBackdropTheme(
        winrt::MUX::ElementTheme const& theme)
    {
        switch (theme)
        {
        case winrt::MUX::ElementTheme::Dark:
            return winrt::MUCSB::SystemBackdropTheme::Dark;
        case winrt::MUX::ElementTheme::Light:
            return winrt::MUCSB::SystemBackdropTheme::Light;
        default:
            return winrt::MUCSB::SystemBackdropTheme::Default;
        }
    }
    ...
};
...