fixed issue with DPI not updating

This commit is contained in:
Daniel Clark
2021-03-01 16:02:58 +00:00
parent dd92d25d23
commit 0a6b227fc6
6 changed files with 48 additions and 19 deletions
@@ -7,6 +7,7 @@
<StartupObject>NotificationFlyoutSample.Host.Program</StartupObject> <StartupObject>NotificationFlyoutSample.Host.Program</StartupObject>
<AssetTargetFallback>uap10.0.19041</AssetTargetFallback> <AssetTargetFallback>uap10.0.19041</AssetTargetFallback>
<Platforms>x64</Platforms> <Platforms>x64</Platforms>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -51,7 +51,7 @@
</TransitionCollection> </TransitionCollection>
</Border.Transitions> </Border.Transitions>
<Grid> <Grid>
<ScrollViewer <ScrollViewer
x:Name="ScrollViewer" x:Name="ScrollViewer"
@@ -9,6 +9,10 @@ using System.Windows.Media.Imaging;
using TheXamlGuy.NotificationFlyout.Common.Extensions; using TheXamlGuy.NotificationFlyout.Common.Extensions;
using Microsoft.Windows.Sdk; using Microsoft.Windows.Sdk;
using TheXamlGuy.NotificationFlyout.Shared.UI; using TheXamlGuy.NotificationFlyout.Shared.UI;
using System.Windows.Media;
using System.Threading.Tasks;
using Microsoft.Win32;
using System.Windows.Threading;
namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
{ {
@@ -24,6 +28,7 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
private readonly NotificationIconHelper _notificationIconHelper; private readonly NotificationIconHelper _notificationIconHelper;
private readonly SystemPersonalisationHelper _systemPersonalisationHelper; private readonly SystemPersonalisationHelper _systemPersonalisationHelper;
private readonly TaskbarHelper _taskbarHelper; private readonly TaskbarHelper _taskbarHelper;
private bool _isDpiChanging;
private TransparentXamlHost<ContentControl> _notificationFlyoutXamlHost; private TransparentXamlHost<ContentControl> _notificationFlyoutXamlHost;
public NotificationFlyoutApplication() public NotificationFlyoutApplication()
@@ -58,12 +63,15 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
public void CloseFlyout() => CloseFlyout(false); public void CloseFlyout() => CloseFlyout(false);
public void Exit() => _notificationFlyoutXamlHost.Close(); public void Exit() => _notificationFlyoutXamlHost.Close();
public void OpenAsWindow<TUIElement>() where TUIElement : Windows.UI.Xaml.UIElement public void OpenAsWindow<TUIElement>() where TUIElement : Windows.UI.Xaml.UIElement
{ {
var window = new XamlHost<TUIElement>(); var window = new XamlHost<TUIElement>();
window.Hidden();
window.Show(); window.Show();
} }
public void OpenFlyout() public void OpenFlyout()
{ {
if (Flyout == null) return; if (Flyout == null) return;
@@ -104,6 +112,29 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
private void OnNotificationFlyoutXamlHostDeactivated(object sender, EventArgs args) => CloseFlyout(true); private void OnNotificationFlyoutXamlHostDeactivated(object sender, EventArgs args) => CloseFlyout(true);
private async void OnNotificationFlyoutXamlHostDpiChanged(object sender, DpiChangedEventArgs args)
{
if (_isDpiChanging)
return;
_isDpiChanging = true;
UpdateIcons();
_notificationFlyoutXamlHost.Visibility = Visibility.Visible;
await Dispatcher.BeginInvoke(new Action(() =>
{
VisualTreeHelper.SetRootDpi(_notificationFlyoutXamlHost, args.OldDpi);
VisualTreeHelper.SetRootDpi(_notificationFlyoutXamlHost, args.NewDpi);
}), DispatcherPriority.ContextIdle, null);
await Dispatcher.BeginInvoke(new Action(() =>
{
_notificationFlyoutXamlHost.Visibility = Visibility.Hidden;
_isDpiChanging = false;
}), DispatcherPriority.ContextIdle, null);
}
private void OnTaskbarChanged(object sender, EventArgs args) => UpdateFlyoutPlacement(); private void OnTaskbarChanged(object sender, EventArgs args) => UpdateFlyoutPlacement();
private void OnThemeChanged(object sender, SystemPersonalisationChangedEventArgs args) private void OnThemeChanged(object sender, SystemPersonalisationChangedEventArgs args)
@@ -115,6 +146,7 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
private void PrepareFlyout() private void PrepareFlyout()
{ {
if (Flyout == null) return; if (Flyout == null) return;
Flyout.IconSourcePropertyChanged += OnFlyoutIconSourcePropertyChanged; Flyout.IconSourcePropertyChanged += OnFlyoutIconSourcePropertyChanged;
Flyout.PlacementPropertyChanged += OnFlyoutPlacementPropertyChanged; Flyout.PlacementPropertyChanged += OnFlyoutPlacementPropertyChanged;
Flyout.InteractedWith += OnFlyoutInteractedWith; Flyout.InteractedWith += OnFlyoutInteractedWith;
@@ -131,6 +163,8 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
private void PrepareFlyoutHost() private void PrepareFlyoutHost()
{ {
_notificationFlyoutXamlHost = new TransparentXamlHost<ContentControl>(); _notificationFlyoutXamlHost = new TransparentXamlHost<ContentControl>();
_notificationFlyoutXamlHost.DpiChanged += OnNotificationFlyoutXamlHostDpiChanged;
_notificationFlyoutXamlHost.Closed += OnNotificationFlyoutXamlHostClosed; _notificationFlyoutXamlHost.Closed += OnNotificationFlyoutXamlHostClosed;
_notificationFlyoutXamlHost.Deactivated += OnNotificationFlyoutXamlHostDeactivated; _notificationFlyoutXamlHost.Deactivated += OnNotificationFlyoutXamlHostDeactivated;
@@ -140,7 +174,6 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
_notificationFlyoutXamlHost.Show(); _notificationFlyoutXamlHost.Show();
} }
private void ShowContextMenu() private void ShowContextMenu()
{ {
var dpiX = _notificationFlyoutXamlHost.DpiX(); var dpiX = _notificationFlyoutXamlHost.DpiX();
@@ -1,18 +1,17 @@
using Microsoft.Toolkit.Wpf.UI.XamlHost; using Microsoft.Toolkit.Wpf.UI.XamlHost;
using System;
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using System;
using TheXamlGuy.NotificationFlyout.Wpf.UI.Extensions;
namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
{ {
internal class TransparentXamlHost<TXamlContent> : XamlHost<TXamlContent> where TXamlContent : Windows.UI.Xaml.UIElement internal class TransparentXamlHost<TXamlContent> : XamlHost<TXamlContent> where TXamlContent : Windows.UI.Xaml.UIElement
{ {
internal const double WindowSize = 0; internal const double WindowSize = 10;
public TransparentXamlHost() => PrepareDefaultWindow(); public TransparentXamlHost() => PrepareDefaultWindow();
protected override void OnContentRendered(EventArgs args) => Visibility = Visibility.Hidden; protected override void OnContentRendered(EventArgs args) => Hide();
protected override WindowsXamlHost OnPreparingXamlHost(WindowsXamlHost xamlHost) protected override WindowsXamlHost OnPreparingXamlHost(WindowsXamlHost xamlHost)
{ {
@@ -21,6 +20,7 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
return base.OnPreparingXamlHost(xamlHost); return base.OnPreparingXamlHost(xamlHost);
} }
private void PrepareDefaultWindow() private void PrepareDefaultWindow()
{ {
ShowInTaskbar = false; ShowInTaskbar = false;
@@ -6,13 +6,11 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
{ {
internal class XamlHost<TXamlContent> : Window where TXamlContent : Windows.UI.Xaml.UIElement internal class XamlHost<TXamlContent> : Window where TXamlContent : Windows.UI.Xaml.UIElement
{ {
protected new bool IsLoaded;
private WindowsXamlHost _xamlHost; private WindowsXamlHost _xamlHost;
public XamlHost() public XamlHost()
{ {
PrepareWindowsXamlHost(); PrepareWindowsXamlHost();
ContentRendered += OnContentRendered;
} }
internal TXamlContent GetHostContent() internal TXamlContent GetHostContent()
@@ -21,11 +19,6 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
return _xamlHost.GetUwpInternalObject() as TXamlContent; return _xamlHost.GetUwpInternalObject() as TXamlContent;
} }
protected virtual void OnContentLoaded()
{
}
protected virtual WindowsXamlHost OnPreparingXamlHost(WindowsXamlHost xamlHost) protected virtual WindowsXamlHost OnPreparingXamlHost(WindowsXamlHost xamlHost)
{ {
xamlHost.InitialTypeName = typeof(TXamlContent).FullName; xamlHost.InitialTypeName = typeof(TXamlContent).FullName;
@@ -35,12 +28,6 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
return xamlHost; return xamlHost;
} }
private void OnContentRendered(object sender, EventArgs args)
{
IsLoaded = true;
OnContentLoaded();
}
private void PrepareWindowsXamlHost() private void PrepareWindowsXamlHost()
{ {
_xamlHost = new WindowsXamlHost(); _xamlHost = new WindowsXamlHost();
@@ -7,6 +7,8 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Extensions
{ {
public static class WindowExtensions public static class WindowExtensions
{ {
private const int GWL_EX_STYLE = -20;
[Flags] [Flags]
private enum WindowFlag : uint private enum WindowFlag : uint
{ {
@@ -26,6 +28,12 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Extensions
return helper.Handle; return helper.Handle;
} }
public static void Hidden(this Window window)
{
var handle = window.GetHandle();
PInvoke.SetWindowLong((HWND)handle, GWL_EX_STYLE, (PInvoke.GetWindowLong((HWND)handle, GWL_EX_STYLE) | (int)WindowFlag.WS_EX_TOOLWINDOW) & ~(int)WindowFlag.WS_EX_APPWINDOW);
}
public static void SetTopAll(this Window window) public static void SetTopAll(this Window window)
{ {
PInvoke.SetWindowPos((HWND)window.GetHandle(), (HWND)new IntPtr(-1), 0, 0, 0, 0, (uint)WindowFlag.SWP_NOMOVE | (uint)WindowFlag.SWP_NOSIZE | (uint)WindowFlag.WS_EX_NOACTIVATE); PInvoke.SetWindowPos((HWND)window.GetHandle(), (HWND)new IntPtr(-1), 0, 0, 0, 0, (uint)WindowFlag.SWP_NOMOVE | (uint)WindowFlag.SWP_NOSIZE | (uint)WindowFlag.WS_EX_NOACTIVATE);