Skip to content

Latest commit

 

History

History
516 lines (415 loc) · 20.6 KB

system-backdrop-controller.md

File metadata and controls

516 lines (415 loc) · 20.6 KB
titledescriptionms.topicms.datekeywordsms.localizationprioritydev_langs
Using a SystemBackdropController with WinUI 3 XAML
Sample code for applying Mica in a WinUI 3 application.
article
07/15/2024
windows, windows app development, Windows App SDK, Mica
medium
csharp
cppwinrt

Apply Mica or Acrylic materials in desktop apps for Windows 11

Materials in Windows 11 are visual effects applied to UX surfaces that resemble real life artifacts. Occluding materials, like Mica and Acrylic, are used as base layers beneath interactive UI controls.

Mica is an opaque material that incorporates the user's theme and desktop wallpaper to create a highly personalized appearance. Mica is designed for performance as it only captures the background wallpaper once to create its visualization, so we recommend it for the foundation layer of your app, especially in the title bar area.

Acrylic is a semi-transparent material that replicates the effect of frosted glass. It's used only for transient, light-dismiss surfaces such as flyouts and context menus.

This article describes how to apply Mica or Acrylic as the base layer of your Windows App SDK/WinUI 3 XAML app.

Note

How to use a backdrop material

[!div class="checklist"]

[!div class="nextstepaction"] Open the WinUI 3 Gallery app and see the System Backdrops in action

[!INCLUDE winui-3-gallery]

To apply Mica or Acrylic material to your app, you set the SystemBackdrop property to a XAML SystemBackdrop (typically, one of the built-in backdrops, MicaBackdrop or DesktopAcrylicBackdrop).

These elements have a SystemBackdrop property:

These examples show how to set the system backdrop in XAML and in code.

Mica

Mica is typically used as the backdrop for an app Window.

<Window ... > <Window.SystemBackdrop> <MicaBackdropKind="BaseAlt"/> </Window.SystemBackdrop> </Window>
publicMainWindow(){this.InitializeComponent();SystemBackdrop=newMicaBackdrop(){Kind=MicaKind.BaseAlt};}

Acrylic

Acrylic is typically used as the backdrop for transient UI, like a flyout.

<Flyout ... > <Flyout.SystemBackdrop> <DesktopAcrylicBackdrop/> </Flyout.SystemBackdrop> </Flyout>
Flyoutflyout=newFlyout(){SystemBackdrop=newDesktopAcrylicBackdrop()};

How to use a system backdrop controller

Note

Starting with Windows App SDK 1.3, you can apply material by setting the Window.SystemBackdrop property to a XAML SystemBackdrop as described in the previous section. This is the recommended way to apply a material.

The remainder of this article shows how to use the Composition MicaController and DesktopAcrylicController APIs.

To use a backdrop material in your app, you can use one of the controllers that implements the ISystemBackdropController interface (MicaController or DesktopAcrylicController). These classes manage both the rendering of the system backdrop material as well as the handling of system policy for the material.

To use Mica as your backdrop material, create a MicaController object. To use Acrylic, create a DesktopAcrylicController object. The set up and supporting code is the same for each type of system backdrop material.

This code shows how to create a MicaController.

MicaControllerm_backdropController;boolTrySetSystemBackdrop(){if(MicaController.IsSupported()){ ...m_backdropController=newMicaController(); ...}}
// namespace MUCSB = Microsoft::UI::Composition::SystemBackdrops; winrt::MUCSB::MicaController m_backdropController{ nullptr }; void SetBackground() { if (winrt::MUCSB::MicaController::IsSupported()) { ... m_backdropController = winrt::MUCSB::MicaController(); ... } } 

To use the Mica Alt variant of Mica, create a MicaController object and set the Kind property to MicaKind.BaseAlt.

MicaControllerm_backdropController;boolTrySetSystemBackdrop(){if(MicaController.IsSupported()){ ...m_backdropController=newMicaController(){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); ... } } 

This code shows how to create a DesktopAcrylicController.

DesktopAcrylicControllerm_backdropController;boolTrySetSystemBackdrop(){if(DesktopAcrylicController.IsSupported()){ ...m_backdropController=newDesktopAcrylicController(); ...}}
// namespace MUCSB = Microsoft::UI::Composition::SystemBackdrops; winrt::MUCSB::DesktopAcrylicController m_backdropController{ nullptr }; void SetBackground() { if (winrt::MUCSB::DesktopAcrylicController::IsSupported()) { ... m_backdropController = winrt::MUCSB::DesktopAcrylicController(); ... } } 

The controller reacts to the system Light and Dark themes by default. To override this behavior, you can set the following properties on the controller:

Note

After customizing any of the controller’s four properties, it no longer applies default Light or Dark values when the associated SystemBackdropConfiguration.Theme changes. You need to manually update those properties to match the new theme.

In order to use the backdrop material in your app, the following items are required:

Example: Use Mica in a Windows AppSDK/WinUI 3 app

This example shows how to set up the Mica backdrop material in a XAML app.

Tip

Also, see these example projects on GitHub:

C#: SampleSystemBackdropsWindow in the WinUI3 Gallery.

C++/WinRT: Windows App SDK Mica sample.

usingMicrosoft.UI.Composition.SystemBackdrops;usingMicrosoft.UI.Xaml;usingSystem.Runtime.InteropServices;// For DllImportusingWinRT;// required to support Window.As<ICompositionSupportsSystemBackdrop>()publicsealedpartialclassMainWindow:Window{WindowsSystemDispatcherQueueHelperm_wsdqHelper;// See below for implementation.MicaControllerm_backdropController;SystemBackdropConfigurationm_configurationSource;publicMainWindow(){this.InitializeComponent();TrySetSystemBackdrop();}boolTrySetSystemBackdrop(){if(Microsoft.UI.Composition.SystemBackdrops.MicaController.IsSupported()){m_wsdqHelper=newWindowsSystemDispatcherQueueHelper();m_wsdqHelper.EnsureWindowsSystemDispatcherQueueController();// Create the policy object.m_configurationSource=newSystemBackdropConfiguration();this.Activated+=Window_Activated;this.Closed+=Window_Closed;((FrameworkElement)this.Content).ActualThemeChanged+=Window_ThemeChanged;// Initial configuration state.m_configurationSource.IsInputActive=true;SetConfigurationSourceTheme();m_backdropController=newMicrosoft.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);returntrue;// succeeded}returnfalse;// Mica is not supported on this system}privatevoidWindow_Activated(objectsender,WindowActivatedEventArgsargs){m_configurationSource.IsInputActive=args.WindowActivationState!=WindowActivationState.Deactivated;}privatevoidWindow_Closed(objectsender,WindowEventArgsargs){// 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;}privatevoidWindow_ThemeChanged(FrameworkElementsender,objectargs){if(m_configurationSource!=null){SetConfigurationSourceTheme();}}privatevoidSetConfigurationSourceTheme(){switch(((FrameworkElement)this.Content).ActualTheme){caseElementTheme.Dark:m_configurationSource.Theme=Microsoft.UI.Composition.SystemBackdrops.SystemBackdropTheme.Dark;break;caseElementTheme.Light:m_configurationSource.Theme=Microsoft.UI.Composition.SystemBackdrops.SystemBackdropTheme.Light;break;caseElementTheme.Default:m_configurationSource.Theme=Microsoft.UI.Composition.SystemBackdrops.SystemBackdropTheme.Default;break;}}}classWindowsSystemDispatcherQueueHelper{[StructLayout(LayoutKind.Sequential)]structDispatcherQueueOptions{internalintdwSize;internalintthreadType;internalintapartmentType;}[DllImport("CoreMessaging.dll")]privatestaticexternintCreateDispatcherQueueController([In]DispatcherQueueOptionsoptions,[In,Out,MarshalAs(UnmanagedType.IUnknown)]refobjectdispatcherQueueController);objectm_dispatcherQueueController=null;publicvoidEnsureWindowsSystemDispatcherQueueController(){if(Windows.System.DispatcherQueue.GetForCurrentThread()!=null){// one already exists, so we'll just use it.return;}if(m_dispatcherQueueController==null){DispatcherQueueOptionsoptions;options.dwSize=Marshal.SizeOf(typeof(DispatcherQueueOptions));options.threadType=2;// DQTYPE_THREAD_CURRENToptions.apartmentType=2;// DQTAT_COM_STACreateDispatcherQueueController(options,refm_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; } } ... }; ... 

Related articles

close