Reputation: 47
I am just learning how to create applications on WinUI 3. and I ran into a problem: the top panel does not match the colors with the application itself if it is in a dark theme. Despite the fact that everything is fine in the light theme (you can see it in the picture)
Here is the code
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System;
using System.Collections.Generic;
using Microsoft.UI;
using Microsoft.UI.Windowing;
using WinRT.Interop;
using Microsoft.UI.Composition.SystemBackdrops;
using System.Runtime.InteropServices;
using WinRT; // required to support Window.As<ICompositionSupportsSystemBackdrop>()
using System.Text;
namespace PasswordGenerator
{
public sealed partial class MainWindow : Window
{
WindowsSystemDispatcherQueueHelper m_wsdqHelper;
MicaController m_backdropController;
SystemBackdropConfiguration m_configurationSource;
private IntPtr hWnd = IntPtr.Zero;
private AppWindow appWindow = null;
private OverlappedPresenter presenter = null;
private AppWindow m_AppWindow;
public MainWindow()
{
this.InitializeComponent();
m_AppWindow = GetAppWindowForCurrentWindow();
m_AppWindow.Title = "Password Generator";
m_AppWindow.SetIcon("Assets\\key.ico");
IntPtr hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
var windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
var appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
appWindow.Resize(new Windows.Graphics.SizeInt32 { Width = 550, Height = 350 });
presenter = appWindow.Presenter as OverlappedPresenter;
presenter.IsResizable = false;
TrySetSystemBackdrop();
}
private AppWindow GetAppWindowForCurrentWindow()
{
IntPtr hWnd = WindowNative.GetWindowHandle(this);
WindowId wndId = Win32Interop.GetWindowIdFromWindow(hWnd);
return AppWindow.GetFromWindowId(wndId);
}
bool TrySetSystemBackdrop()
{
if (Microsoft.UI.Composition.SystemBackdrops.MicaController.IsSupported())
{
m_wsdqHelper = new WindowsSystemDispatcherQueueHelper();
m_wsdqHelper.EnsureWindowsSystemDispatcherQueueController();
m_configurationSource = new SystemBackdropConfiguration();
this.Activated += Window_Activated;
this.Closed += Window_Closed;
((FrameworkElement)this.Content).ActualThemeChanged += Window_ThemeChanged;
m_configurationSource.IsInputActive = true;
SetConfigurationSourceTheme();
m_backdropController = new Microsoft.UI.Composition.SystemBackdrops.MicaController();
m_backdropController.AddSystemBackdropTarget(this.As<Microsoft.UI.Composition.ICompositionSupportsSystemBackdrop>());
m_backdropController.SetSystemBackdropConfiguration(m_configurationSource);
return true;
}
return false;
}
private void Window_Activated(object sender, WindowActivatedEventArgs args)
{
m_configurationSource.IsInputActive = args.WindowActivationState != WindowActivationState.Deactivated;
}
private void Window_Closed(object sender, WindowEventArgs args)
{
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)
{
return;
}
if (m_dispatcherQueueController == null)
{
DispatcherQueueOptions options;
options.dwSize = Marshal.SizeOf(typeof(DispatcherQueueOptions));
options.threadType = 2;
options.apartmentType = 2;
CreateDispatcherQueueController(options, ref m_dispatcherQueueController);
}
}
}
}
I will be glad to help.
I would also be willing to hear criticism about my code if it really can be improved
Upvotes: 1
Views: 370
Reputation: 13666
You can see here how to customize the title bar.
This is a simple example using the WinUI 3 way.
MainWindow.xaml
<Window
x:Class="WinUI3TitleBars.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid
Background="HotPink"
RowDefinitions="32,*">
<Grid
x:Name="AppTitleBar"
Grid.Row="0">
<Image
Width="16"
Height="16"
Margin="5,0,0,0"
HorizontalAlignment="Left"
Source="Assets/MicrosoftLogo.png" />
<TextBlock
Margin="28,0,0,0"
VerticalAlignment="Center"
Text="App Title Bar" />
</Grid>
<Grid Grid.Row="1">
<TextBlock Text="Your contents go here." />
</Grid>
</Grid>
</Window>
MainWindow.xaml.cs
using Microsoft.UI.Xaml;
namespace WinUI3TitleBars;
public sealed partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
this.SetTitleBar(this.AppTitleBar);
this.ExtendsContentIntoTitleBar = true;
}
}
And to avoid the brighter background of the title bar, add these SolidColorBrush
definitions.
App.xaml
<Application
x:Class="WinUI3TitleBars.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WinUI3TitleBars">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<!-- Other app resources here -->
<SolidColorBrush x:Key="WindowCaptionBackground">Transparent</SolidColorBrush>
<SolidColorBrush x:Key="WindowCaptionBackgroundDisabled">Transparent</SolidColorBrush>
</ResourceDictionary>
</Application.Resources>
</Application>
Upvotes: 1