-
-
Save LanceMcCarthy/4954ab92ca44c19eb4316d9d683efd50 to your computer and use it in GitHub Desktop.
// ************************************************************************ // | |
// This implementation is inspired from the official WinUI3 backdrops examples | |
// https://github.com/microsoft/WinUI-Gallery/blob/winui3/XamlControlsGallery/ControlPagesSampleCode/SystemBackdrops/SystemBackdropsSample2.txt | |
// *********************************************************************** // | |
using Microsoft.Maui.LifecycleEvents; | |
#if WINDOWS10_0_17763_0_OR_GREATER | |
// The namespace of where the WindowsHelpers class resides | |
// In older versions of .NET MAUI, this was | |
//using YOUR_APP.Platforms.Windows | |
// In newer versions of .NET MAUI, it is now | |
using YOUR_APP.WinUI; | |
#endif | |
namespace YOUR_APP.Maui | |
{ | |
public static class MauiProgram | |
{ | |
public static MauiApp CreateMauiApp() | |
{ | |
var builder = MauiApp.CreateBuilder(); | |
builder | |
.UseMauiApp<App>() | |
.ConfigureFonts(fonts => | |
{ | |
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); | |
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); | |
}); | |
// **** THIS SECTION IS WHAT IS RELEVANT FOR YOU ************ // | |
builder.ConfigureLifecycleEvents(events => | |
{ | |
#if WINDOWS10_0_17763_0_OR_GREATER | |
events.AddWindows(wndLifeCycleBuilder => | |
{ | |
wndLifeCycleBuilder.OnWindowCreated(window => | |
{ | |
window.TryMicaOrAcrylic(); // requires 'using YOUR_APP.WinUI;' | |
}); | |
}); | |
#endif | |
}); | |
// ************* END OF RELEVANT SECTION *********** // | |
return builder.Build(); | |
} | |
} | |
} |
// **************************************************** // | |
// Place this class file in your Platforms/Windows folder | |
// **************************************************** // | |
using Microsoft.UI.Composition; | |
using Microsoft.UI.Composition.SystemBackdrops; | |
using Microsoft.UI.Xaml; | |
using WinRT; | |
namespace YOUR_APP.Platforms.Windows | |
{ | |
public static class WindowHelpers | |
{ | |
public static void TryMicaOrAcrylic(this Microsoft.UI.Xaml.Window window) | |
{ | |
var dispatcherQueueHelper = new WindowsSystemDispatcherQueueHelper(); // in Platforms.Windows folder | |
dispatcherQueueHelper.EnsureWindowsSystemDispatcherQueueController(); | |
// Hooking up the policy object | |
var configurationSource = new SystemBackdropConfiguration(); | |
configurationSource.IsInputActive = true; | |
switch (((FrameworkElement)window.Content).ActualTheme) | |
{ | |
case ElementTheme.Dark: | |
configurationSource.Theme = SystemBackdropTheme.Dark; | |
break; | |
case ElementTheme.Light: | |
configurationSource.Theme = SystemBackdropTheme.Light; | |
break; | |
case ElementTheme.Default: | |
configurationSource.Theme = SystemBackdropTheme.Default; | |
break; | |
} | |
// Let's try Mica first | |
if (MicaController.IsSupported()) | |
{ | |
var micaController = new MicaController(); | |
micaController.AddSystemBackdropTarget(window.As<ICompositionSupportsSystemBackdrop>()); | |
micaController.SetSystemBackdropConfiguration(configurationSource); | |
window.Activated += (object sender, WindowActivatedEventArgs args) => | |
{ | |
if (args.WindowActivationState is WindowActivationState.CodeActivated or WindowActivationState.PointerActivated) | |
{ | |
// Handle situation where a window is activated and placed on top of other active windows. | |
if (micaController == null) | |
{ | |
micaController = new MicaController(); | |
micaController.AddSystemBackdropTarget(window.As<ICompositionSupportsSystemBackdrop>()); // Requires 'using WinRT;' | |
micaController.SetSystemBackdropConfiguration(configurationSource); | |
} | |
if (configurationSource != null) | |
configurationSource.IsInputActive = args.WindowActivationState != WindowActivationState.Deactivated; | |
} | |
}; | |
window.Closed += (object sender, WindowEventArgs args) => | |
{ | |
if (micaController != null) | |
{ | |
micaController.Dispose(); | |
micaController = null; | |
} | |
configurationSource = null; | |
}; | |
} | |
// If no Mica, maybe we can use Acrylic instead | |
else if (DesktopAcrylicController.IsSupported()) | |
{ | |
var acrylicController = new DesktopAcrylicController(); | |
acrylicController.AddSystemBackdropTarget(window.As<ICompositionSupportsSystemBackdrop>()); | |
acrylicController.SetSystemBackdropConfiguration(configurationSource); | |
window.Activated += (object sender, WindowActivatedEventArgs args) => | |
{ | |
if (args.WindowActivationState is WindowActivationState.CodeActivated or WindowActivationState.PointerActivated) | |
{ | |
// Handle situation where a window is activated and placed on top of other active windows. | |
if (acrylicController == null) | |
{ | |
acrylicController = new DesktopAcrylicController(); | |
acrylicController.AddSystemBackdropTarget(window.As<ICompositionSupportsSystemBackdrop>()); // Requires 'using WinRT;' | |
acrylicController.SetSystemBackdropConfiguration(configurationSource); | |
} | |
} | |
if (configurationSource != null) | |
configurationSource.IsInputActive = args.WindowActivationState != WindowActivationState.Deactivated; | |
}; | |
window.Closed += (object sender, WindowEventArgs args) => | |
{ | |
if (acrylicController != null) | |
{ | |
acrylicController.Dispose(); | |
acrylicController = null; | |
} | |
configurationSource = null; | |
}; | |
} | |
} | |
} | |
} |
// **************************************************** // | |
// Place this class file in your Platforms/Windows folder | |
// **************************************************** // | |
using System.Runtime.InteropServices; | |
using Windows.System; // Required for DllImport attribute and DispatcherQueue | |
namespace YOUR_APP.Maui.Platforms.Windows; | |
public 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 (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); | |
} | |
} | |
} |
Yeah, I wasn't talking about the shell, but as you pointed out, the background of the flyout header and content.
Setting those to have a background of transparent has no effect. Matter of fact, the screen shot I attached already has those properties set to transparent. I believe the internals of how those components are rendered (much like the label on a check box in Windows) is overriding the explicit background property. When inspecting the rendered UI, there are many pieces that are added by the platform, and which I cannot seem to be able to target with regular styling.
I will see if the MAUI team has any guidance for me.
NEW APPROACH
Hi folks, we no longer need a bunch of custom code. Microsoft now has an easy API to set the backdrop right on the Window class itself:
window.SystemBackdrop = new MicaBackdrop { Kind = MicaKind.BaseAlt };
Here's what it looks like in MauiProgram.cs
using Microsoft.Maui.LifecycleEvents;
#if WINDOWS10_0_17763_0_OR_GREATER
using Hacked.Maui.Platforms.Windows;
using Microsoft.UI.Composition.SystemBackdrops;
using Microsoft.UI.Xaml.Media;
#endif
namespace MyMauiApp;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
builder.ConfigureLifecycleEvents(events =>
{
#if WINDOWS10_0_17763_0_OR_GREATER
events.AddWindows(wndLifeCycleBuilder =>
{
wndLifeCycleBuilder.OnWindowCreated(window =>
{
window.SystemBackdrop = new MicaBackdrop { Kind = MicaKind.BaseAlt };
});
});
#endif
}
return builder.Build();
}
Here is the result at runtime (note MicaKind.BaseAlt is more tinted than default Mica):
That's good! I'm trying now...
I haven't been able to test it in most situations, so I'd be happy to hear how it goes.
Here are the docs => https://learn.microsoft.com/en-us/windows/apps/design/style/mica#use-mica-with-the-windows-app-sdk
It seems cannot put wasdk api on maui...
Oh sorry, I'm forgot to update the nuget package, now works fine.
Hi @kolkonos I'm sorry, I didn't see this until now.
What you want to do is not technically possible. That is because WinUI 2 and 3 does not support 100% transparent background Windows. You can get semi-transparent real-time blur (what is called Acrylic).
Update
I just realized you might be talking about the Shell page's background so that you can get the acrylic all the way through. I believe you can achieve that with Styles targeting ContentPage, Shell and possibly NavigationPage, then setting the BackgroundColor to Transparent. Though, I would ask the MAUI team for assistance with that if you're still stuck, you can get help here => https://learn.microsoft.com/en-us/answers/tags/247/dotnet-maui