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>
<AssetTargetFallback>uap10.0.19041</AssetTargetFallback>
<Platforms>x64</Platforms>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
@@ -51,7 +51,7 @@
</TransitionCollection>
</Border.Transitions>
<Grid>
<ScrollViewer
x:Name="ScrollViewer"
@@ -9,6 +9,10 @@ using System.Windows.Media.Imaging;
using TheXamlGuy.NotificationFlyout.Common.Extensions;
using Microsoft.Windows.Sdk;
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
{
@@ -24,6 +28,7 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
private readonly NotificationIconHelper _notificationIconHelper;
private readonly SystemPersonalisationHelper _systemPersonalisationHelper;
private readonly TaskbarHelper _taskbarHelper;
private bool _isDpiChanging;
private TransparentXamlHost<ContentControl> _notificationFlyoutXamlHost;
public NotificationFlyoutApplication()
@@ -58,12 +63,15 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
public void CloseFlyout() => CloseFlyout(false);
public void Exit() => _notificationFlyoutXamlHost.Close();
public void OpenAsWindow<TUIElement>() where TUIElement : Windows.UI.Xaml.UIElement
{
var window = new XamlHost<TUIElement>();
window.Hidden();
window.Show();
}
public void OpenFlyout()
{
if (Flyout == null) return;
@@ -104,6 +112,29 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
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 OnThemeChanged(object sender, SystemPersonalisationChangedEventArgs args)
@@ -115,6 +146,7 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
private void PrepareFlyout()
{
if (Flyout == null) return;
Flyout.IconSourcePropertyChanged += OnFlyoutIconSourcePropertyChanged;
Flyout.PlacementPropertyChanged += OnFlyoutPlacementPropertyChanged;
Flyout.InteractedWith += OnFlyoutInteractedWith;
@@ -131,6 +163,8 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
private void PrepareFlyoutHost()
{
_notificationFlyoutXamlHost = new TransparentXamlHost<ContentControl>();
_notificationFlyoutXamlHost.DpiChanged += OnNotificationFlyoutXamlHostDpiChanged;
_notificationFlyoutXamlHost.Closed += OnNotificationFlyoutXamlHostClosed;
_notificationFlyoutXamlHost.Deactivated += OnNotificationFlyoutXamlHostDeactivated;
@@ -140,7 +174,6 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
_notificationFlyoutXamlHost.Show();
}
private void ShowContextMenu()
{
var dpiX = _notificationFlyoutXamlHost.DpiX();
@@ -1,18 +1,17 @@
using Microsoft.Toolkit.Wpf.UI.XamlHost;
using System;
using System.Windows;
using System.Windows.Media;
using System;
using TheXamlGuy.NotificationFlyout.Wpf.UI.Extensions;
namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
{
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();
protected override void OnContentRendered(EventArgs args) => Visibility = Visibility.Hidden;
protected override void OnContentRendered(EventArgs args) => Hide();
protected override WindowsXamlHost OnPreparingXamlHost(WindowsXamlHost xamlHost)
{
@@ -21,6 +20,7 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
return base.OnPreparingXamlHost(xamlHost);
}
private void PrepareDefaultWindow()
{
ShowInTaskbar = false;
@@ -6,13 +6,11 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
{
internal class XamlHost<TXamlContent> : Window where TXamlContent : Windows.UI.Xaml.UIElement
{
protected new bool IsLoaded;
private WindowsXamlHost _xamlHost;
public XamlHost()
{
PrepareWindowsXamlHost();
ContentRendered += OnContentRendered;
}
internal TXamlContent GetHostContent()
@@ -21,11 +19,6 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
return _xamlHost.GetUwpInternalObject() as TXamlContent;
}
protected virtual void OnContentLoaded()
{
}
protected virtual WindowsXamlHost OnPreparingXamlHost(WindowsXamlHost xamlHost)
{
xamlHost.InitialTypeName = typeof(TXamlContent).FullName;
@@ -35,12 +28,6 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Controls
return xamlHost;
}
private void OnContentRendered(object sender, EventArgs args)
{
IsLoaded = true;
OnContentLoaded();
}
private void PrepareWindowsXamlHost()
{
_xamlHost = new WindowsXamlHost();
@@ -7,6 +7,8 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Extensions
{
public static class WindowExtensions
{
private const int GWL_EX_STYLE = -20;
[Flags]
private enum WindowFlag : uint
{
@@ -26,6 +28,12 @@ namespace TheXamlGuy.NotificationFlyout.Wpf.UI.Extensions
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)
{
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);