.NET MAUI Shell桌面应用:亚克力窗口标题栏自定义与内容延伸
.NET MAUI Shell应用:实现内容延伸至标题栏(配合亚克力效果)
我正在开发面向Windows 10/11和macOS平台的.NET MAUI Shell应用,想要实现两个核心效果:窗口启用亚克力(Acrylic)效果,同时让应用内容延伸至标题栏区域。目前已经完成了亚克力窗口的实现,但找不到让内容延伸到标题栏的方法。
效果对比
目标效果

当前已实现效果

请问如何实现应用内容向标题栏区域延伸?
当前实现代码
MauiProgram.cs
public static class MauiProgram { public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .UseMauiCommunityToolkit() .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); fonts.AddFont("Segoe Fluent Icons.ttf", "SegoeFluentIcons"); }) .ConfigureLifecycleEvents(events => { #if WINDOWS10_0_17763_0_OR_GREATER events.AddWindows(wndLifeCycleBuilder => { wndLifeCycleBuilder.OnWindowCreated(window => { window.TryMicaOrAcrylic(); // Platforms/Windows/WindowsHelpers.cs }); }); #endif }); builder.Services.AddSingleton<PhoenixPipe>(); builder.Services.AddTransient<OverviewPage>(); builder.Services.AddTransient<OverviewViewModel>(); builder.Services.AddTransient<BlocksPage>(); builder.Services.AddTransient<BlocksViewModel>(); builder.Services.AddTransient<NewBlockPage>(); builder.Services.AddTransient<NewBlockViewModel>(); Routing.RegisterRoute("block_new", typeof(NewBlockPage)); Routing.RegisterRoute("block_edit", typeof(BlockEditPage)); #if DEBUG builder.Logging.AddDebug(); #endif return builder.Build(); } }
Platforms/Windows/WindowsHelpers.cs(用于创建亚克力窗口)
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; }; } } }
Platforms/Windows/WindowsSystemDispatcherQueueHelper.cs
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); } } }
内容的提问来源于stack exchange,提问作者Jeremy Ashcraft
相关产品推荐
相关产品推荐

