diff --git a/NotificationFlyout.Shared.UI/Helpers/SystemPersonalisationHelper.cs b/NotificationFlyout.Shared.UI/Helpers/SystemPersonalisationHelper.cs
new file mode 100644
index 0000000..a683afe
--- /dev/null
+++ b/NotificationFlyout.Shared.UI/Helpers/SystemPersonalisationHelper.cs
@@ -0,0 +1,35 @@
+using System;
+using Windows.UI.ViewManagement;
+
+namespace NotificationFlyout.Shared.UI.Helpers
+{
+ public class SystemPersonalisationHelper
+ {
+ private readonly UISettings _settings = new UISettings();
+
+ private SystemPersonalisationHelper()
+ {
+ _settings.ColorValuesChanged += _settings_ColorValuesChanged;
+ }
+
+ private void _settings_ColorValuesChanged(UISettings sender, object args)
+ {
+ ThemeChanged?.Invoke(this, EventArgs.Empty);
+ }
+
+ public event EventHandler ThemeChanged;
+
+ public SystemTheme SystemTheme => GetSystemTheme();
+
+ public static SystemPersonalisationHelper Create()
+ {
+ return new SystemPersonalisationHelper();
+ }
+
+ private SystemTheme GetSystemTheme()
+ {
+ var uiTheme = _settings.GetColorValue(UIColorType.Background).ToString();
+ return uiTheme == "#FFFFFFFF" ? SystemTheme.Light : SystemTheme.Dark;
+ }
+ }
+}
diff --git a/NotificationFlyout.Shared.UI/Helpers/SystemTheme.cs b/NotificationFlyout.Shared.UI/Helpers/SystemTheme.cs
new file mode 100644
index 0000000..ee90015
--- /dev/null
+++ b/NotificationFlyout.Shared.UI/Helpers/SystemTheme.cs
@@ -0,0 +1,8 @@
+namespace NotificationFlyout.Shared.UI.Helpers
+{
+ public enum SystemTheme
+ {
+ Dark,
+ Light,
+ }
+}
diff --git a/NotificationFlyout.Shared.UI/NotificationFlyout.Shared.UI.csproj b/NotificationFlyout.Shared.UI/NotificationFlyout.Shared.UI.csproj
new file mode 100644
index 0000000..92145d4
--- /dev/null
+++ b/NotificationFlyout.Shared.UI/NotificationFlyout.Shared.UI.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
diff --git a/NotificationFlyout.Tray/Assets/Icon-Light.ico b/NotificationFlyout.Tray/Assets/Icon-Light.ico
new file mode 100644
index 0000000..5c7e7a8
Binary files /dev/null and b/NotificationFlyout.Tray/Assets/Icon-Light.ico differ
diff --git a/NotificationFlyout.Tray/NotificationFlyout.Sample.Wpf.csproj b/NotificationFlyout.Tray/NotificationFlyout.Sample.Wpf.csproj
index 16b2061..b7af113 100644
--- a/NotificationFlyout.Tray/NotificationFlyout.Sample.Wpf.csproj
+++ b/NotificationFlyout.Tray/NotificationFlyout.Sample.Wpf.csproj
@@ -12,6 +12,7 @@
+
@@ -27,6 +28,7 @@
+
diff --git a/NotificationFlyout.Tray/SampleNotificationFlyout.xaml b/NotificationFlyout.Tray/SampleNotificationFlyout.xaml
index 0b4c2e5..947fc42 100644
--- a/NotificationFlyout.Tray/SampleNotificationFlyout.xaml
+++ b/NotificationFlyout.Tray/SampleNotificationFlyout.xaml
@@ -4,6 +4,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sample="clr-namespace:NotificationFlyout.Sample;assembly=NotificationFlyout.Sample"
IconSource="/Assets/Icon.ico"
- LightIconSource="/Assets/Icon.ico">
+ LightIconSource="/Assets/Icon-Light.ico">
diff --git a/NotificationFlyout.Wpf.UI.Controls/NotificationFlyout/NotificationFlyout.cs b/NotificationFlyout.Wpf.UI.Controls/NotificationFlyout/NotificationFlyout.cs
index 1c08447..fe991bc 100644
--- a/NotificationFlyout.Wpf.UI.Controls/NotificationFlyout/NotificationFlyout.cs
+++ b/NotificationFlyout.Wpf.UI.Controls/NotificationFlyout/NotificationFlyout.cs
@@ -1,6 +1,4 @@
using NotificationFlyout.Uwp.UI.Controls;
-using NotificationFlyout.Wpf.UI.Extensions;
-using NotificationFlyout.Wpf.UI.Helpers;
using System.Windows;
using System.Windows.Markup;
using System.Windows.Media;
@@ -25,8 +23,6 @@ namespace NotificationFlyout.Wpf.UI.Controls
typeof(NotificationFlyoutPresenter), typeof(NotificationFlyout),
new PropertyMetadata(null, OnFlyoutPresenterPropertyChanged));
- private const string ShellTrayHandleName = "Shell_TrayWnd";
-
private readonly NotificationFlyoutXamlHost _xamlHost;
public NotificationFlyout()
@@ -82,21 +78,7 @@ namespace NotificationFlyout.Wpf.UI.Controls
private void OnIconPropertyChanged()
{
- SetIcon();
- }
-
- private void SetIcon()
- {
- var shellTrayHandle = WindowHelper.GetHandle(ShellTrayHandleName);
- if (shellTrayHandle == null) return;
-
- var dpi = WindowHelper.GetDpi(shellTrayHandle);
-
- var iconSource = SystemSettingsHelper.DefaultSystemTheme == SystemTheme.Dark ? IconSource : LightIconSource;
- if (iconSource == null) return;
-
- using var icon = iconSource.ConvertToIcon(dpi);
- _xamlHost.SetNotificationIcon(icon.Handle);
+ _xamlHost.SetIcons(IconSource, LightIconSource);
}
}
}
\ No newline at end of file
diff --git a/NotificationFlyout.Wpf.UI.Controls/NotificationFlyout/NotificationFlyoutXamlHost.cs b/NotificationFlyout.Wpf.UI.Controls/NotificationFlyout/NotificationFlyoutXamlHost.cs
index 6740adf..493d610 100644
--- a/NotificationFlyout.Wpf.UI.Controls/NotificationFlyout/NotificationFlyoutXamlHost.cs
+++ b/NotificationFlyout.Wpf.UI.Controls/NotificationFlyout/NotificationFlyoutXamlHost.cs
@@ -11,10 +11,16 @@ namespace NotificationFlyout.Wpf.UI.Controls
{
internal class NotificationFlyoutXamlHost : Window
{
- private const double MaximumOffset = 80;
+ private const string ShellTrayHandleName = "Shell_TrayWnd";
+ private const double WindowSize = 5;
+
+ private ImageSource _defaultIconSource;
+ private ImageSource _lightIconSource;
private NotificationIconHelper _notificationIconHelper;
+ private SystemPersonalisationHelper _systemPersonalisationHelper;
private TaskbarHelper _taskbarHelper;
private WindowsXamlHost _xamlHost;
+ private bool _isLoaded;
public NotificationFlyoutXamlHost()
{
@@ -42,9 +48,12 @@ namespace NotificationFlyout.Wpf.UI.Controls
}
}
- internal void SetNotificationIcon(IntPtr handle)
+ internal void SetIcons(ImageSource defaultIconSource, ImageSource lightIconSource)
{
- _notificationIconHelper.SetIcon(handle);
+ _defaultIconSource = defaultIconSource;
+ _lightIconSource = lightIconSource;
+
+ UpdateIcon();
}
internal void ShowFlyout()
@@ -83,7 +92,16 @@ namespace NotificationFlyout.Wpf.UI.Controls
PrepareNotificationIcon();
PrepareTaskbar();
+ _isLoaded = true;
+
UpdateWindow();
+ UpdateIcon();
+
+ }
+
+ private void OnSystemThemeChanged(object sender, EventArgs args)
+ {
+ UpdateIcon();
}
private void OnTaskbarChanged(object sender, EventArgs args)
@@ -99,14 +117,17 @@ namespace NotificationFlyout.Wpf.UI.Controls
ResizeMode = ResizeMode.NoResize;
AllowsTransparency = true;
Background = new SolidColorBrush(Colors.Transparent);
- Height = 5;
- Width = 5;
+ Height = WindowSize;
+ Width = WindowSize;
}
private void PrepareNotificationIcon()
{
_notificationIconHelper = NotificationIconHelper.Create(this);
_notificationIconHelper.IconInvoked += OnIconInvoked;
+
+ _systemPersonalisationHelper = SystemPersonalisationHelper.Create(this);
+ _systemPersonalisationHelper.ThemeChanged += OnSystemThemeChanged;
}
private void PrepareTaskbar()
@@ -128,8 +149,26 @@ namespace NotificationFlyout.Wpf.UI.Controls
Content = _xamlHost;
}
+ private void UpdateIcon()
+ {
+ if (!_isLoaded) return;
+
+ var shellTrayHandle = WindowHelper.GetHandle(ShellTrayHandleName);
+ if (shellTrayHandle == null) return;
+
+ var dpi = WindowHelper.GetDpi(shellTrayHandle);
+
+ var iconSource = _systemPersonalisationHelper.SystemTheme == SystemTheme.Dark ? _defaultIconSource : _lightIconSource;
+ if (iconSource == null) return;
+
+ using var icon = iconSource.ConvertToIcon(dpi);
+ _notificationIconHelper.SetIcon(icon.Handle);
+ }
+
private void UpdateWindow()
{
+ if (!_isLoaded) return;
+
var flyoutHost = GetFlyoutHost();
if (flyoutHost == null) return;
@@ -138,8 +177,8 @@ namespace NotificationFlyout.Wpf.UI.Controls
Left = taskbarState.Screen.WorkingArea.Left;
Top = taskbarState.Screen.WorkingArea.Top;
- var windowWidth = 5 * this.DpiX();
- var windowHeight = 5 * this.DpiY();
+ var windowWidth = WindowSize * this.DpiX();
+ var windowHeight = WindowSize * this.DpiY();
double top, left, height, width;
diff --git a/NotificationFlyout.Wpf.UI/Helpers/NotificationIconHelper.cs b/NotificationFlyout.Wpf.UI/Helpers/NotificationIconHelper.cs
index 0bce1fd..c5597f3 100644
--- a/NotificationFlyout.Wpf.UI/Helpers/NotificationIconHelper.cs
+++ b/NotificationFlyout.Wpf.UI/Helpers/NotificationIconHelper.cs
@@ -12,9 +12,6 @@ namespace NotificationFlyout.Wpf.UI.Helpers
private const int CallbackMessage = 0x400;
private const uint IconVersion = 0x4;
- private const int WM_LBUTTONUP = 0x0202;
- private const int WM_MBUTTONUP = 0x0208;
- private const int WM_RBUTTONUP = 0x0205;
private readonly object _lock = new();
private readonly IntPtr _windowHandle;
private bool _isDisposed;
@@ -134,36 +131,29 @@ namespace NotificationFlyout.Wpf.UI.Helpers
}
}
+ private void InvokeIconInvoked(MouseButton mouseButton)
+ {
+ IconInvoked?.Invoke(this, new NotificationIconInvokedEventArgs { MouseButton = mouseButton });
+ }
+
private void RemoveNotificationIcon() => WriteNotifyIconData(NotifyIconCommand.Delete, NotifyIconDataMember.Message);
+
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == CallbackMessage)
{
- var mouseButton = MouseButton.Left;
- var isInvoked = false;
-
switch ((uint)lParam)
{
- case WM_LBUTTONUP:
- isInvoked = true;
- mouseButton = MouseButton.Left;
+ case (uint)WndProcMessages.WM_LBUTTONUP:
+ InvokeIconInvoked(MouseButton.Left);
break;
-
- case WM_MBUTTONUP:
- isInvoked = true;
- mouseButton = MouseButton.Middle;
+ case (uint)WndProcMessages.WM_MBUTTONUP:
+ InvokeIconInvoked(MouseButton.Middle);
break;
-
- case WM_RBUTTONUP:
- isInvoked = true;
- mouseButton = MouseButton.Right;
+ case (uint)WndProcMessages.WM_RBUTTONUP:
+ InvokeIconInvoked(MouseButton.Right);
break;
}
-
- if (isInvoked)
- {
- IconInvoked?.Invoke(this, new NotificationIconInvokedEventArgs { MouseButton = mouseButton });
- }
}
return DefWindowProcW(hwnd, (uint)msg, wParam, (lParam));
diff --git a/NotificationFlyout.Wpf.UI/Helpers/RegistryHelper.cs b/NotificationFlyout.Wpf.UI/Helpers/RegistryHelper.cs
deleted file mode 100644
index d5ad730..0000000
--- a/NotificationFlyout.Wpf.UI/Helpers/RegistryHelper.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using Microsoft.Win32;
-
-namespace NotificationFlyout.Wpf.UI.Helpers
-{
- internal static class RegistryHelper
- {
- public static TValue GetDwordValue(string key, string valueName)
- {
- using var baseKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64);
- using var subKey = baseKey.OpenSubKey(key);
-
- return (TValue)subKey.GetValue(valueName, 0);
- }
- }
-}
diff --git a/NotificationFlyout.Wpf.UI/Helpers/SystemInformationHelper.cs b/NotificationFlyout.Wpf.UI/Helpers/SystemInformationHelper.cs
index e8adbde..cde40e5 100644
--- a/NotificationFlyout.Wpf.UI/Helpers/SystemInformationHelper.cs
+++ b/NotificationFlyout.Wpf.UI/Helpers/SystemInformationHelper.cs
@@ -8,13 +8,10 @@ namespace NotificationFlyout.Wpf.UI.Helpers
public static class SystemInformationHelper
{
private const int SM_CXSCREEN = 0;
-
private const int SM_CYSCREEN = 1;
-
private const int SPI_GETWORKAREA = 48;
public static Rect VirtualScreen => GetVirtualScreen();
-
public static Rect WorkingArea => GetWorkingArea();
public static int GetCurrentDpi()
diff --git a/NotificationFlyout.Wpf.UI/Helpers/SystemPersonalisationHelper.cs b/NotificationFlyout.Wpf.UI/Helpers/SystemPersonalisationHelper.cs
new file mode 100644
index 0000000..fa7cdb3
--- /dev/null
+++ b/NotificationFlyout.Wpf.UI/Helpers/SystemPersonalisationHelper.cs
@@ -0,0 +1,69 @@
+using NotificationFlyout.Wpf.UI.Extensions;
+using System;
+using System.Runtime.InteropServices;
+using System.Windows;
+using System.Windows.Interop;
+using Windows.UI.ViewManagement;
+
+namespace NotificationFlyout.Wpf.UI.Helpers
+{
+ public class SystemPersonalisationHelper
+ {
+ private readonly UISettings _settings = new();
+
+ private SystemTheme _currentTheme;
+
+
+ private SystemPersonalisationHelper(Window window)
+ {
+ var source = HwndSource.FromHwnd(window.GetHandle());
+ source.AddHook(new HwndSourceHook(WndProc));
+
+ _settings.ColorValuesChanged += OnColorValuesChanged;
+ _currentTheme = GetSystemTheme();
+ }
+
+ public event EventHandler ThemeChanged;
+
+ public SystemTheme SystemTheme => GetSystemTheme();
+
+ public static SystemPersonalisationHelper Create(Window window)
+ {
+ return new SystemPersonalisationHelper(window);
+ }
+
+ [DllImport("user32.dll", SetLastError = true)]
+ private static extern IntPtr DefWindowProcW(IntPtr handle, uint msg, IntPtr wParam, IntPtr lParam);
+
+ private SystemTheme GetSystemTheme()
+ {
+ var uiTheme = _settings.GetColorValue(UIColorType.Background).ToString();
+ return uiTheme == "#FFFFFFFF" ? SystemTheme.Light : SystemTheme.Dark;
+ }
+
+ private void OnColorValuesChanged(UISettings sender, object args)
+ {
+ RaiseThemeChangedEvent();
+ }
+
+ private void RaiseThemeChangedEvent()
+ {
+ var theme = GetSystemTheme();
+ if (theme != _currentTheme)
+ {
+ ThemeChanged?.Invoke(this, new ThemeChangedEventArgs(theme));
+ _currentTheme = theme;
+ }
+ }
+
+ private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
+ {
+ if (msg == (int)WndProcMessages.WM_SETTINGCHANGE)
+ {
+ RaiseThemeChangedEvent();
+ }
+
+ return DefWindowProcW(hwnd, (uint)msg, wParam, (lParam));
+ }
+ }
+}
diff --git a/NotificationFlyout.Wpf.UI/Helpers/SystemSettingsHelper.cs b/NotificationFlyout.Wpf.UI/Helpers/SystemSettingsHelper.cs
deleted file mode 100644
index b0d4d37..0000000
--- a/NotificationFlyout.Wpf.UI/Helpers/SystemSettingsHelper.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using NotificationFlyout.Wpf.UI.Extensions;
-using System;
-
-namespace NotificationFlyout.Wpf.UI.Helpers
-{
- public static class SystemSettingsHelper
- {
- public static SystemTheme DefaultSystemTheme => GetDefaultSystemTheme();
-
- private static SystemTheme GetDefaultSystemTheme()
- {
- return Environment.OSVersion.IsGreaterThan(OperatingSystemVersion.Windows10_1809) && DoesSystemUsesLightTheme() ? SystemTheme.Light : SystemTheme.Dark;
- }
-
- private static bool DoesSystemUsesLightTheme()
- {
- var personalizeKey = @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";
- return RegistryHelper.GetDwordValue(personalizeKey, "SystemUsesLightTheme") > 0;
- }
- }
-}
diff --git a/NotificationFlyout.Wpf.UI/Helpers/TaskbarHelper.cs b/NotificationFlyout.Wpf.UI/Helpers/TaskbarHelper.cs
index 6808b48..859bceb 100644
--- a/NotificationFlyout.Wpf.UI/Helpers/TaskbarHelper.cs
+++ b/NotificationFlyout.Wpf.UI/Helpers/TaskbarHelper.cs
@@ -10,12 +10,9 @@ namespace NotificationFlyout.Wpf.UI.Helpers
public class TaskbarHelper
{
private const string ShellTrayHandleName = "Shell_TrayWnd";
-
private const int SPI_SETWORKAREA = 0x002F;
- private const int WSETTINGCHANGE = 0x001A;
-
- private static readonly uint WTASKBARCREATED = PInvoke.RegisterWindowMessage("TaskbarCreated");
+ private readonly uint WM_TASKBARCREATED = PInvoke.RegisterWindowMessage("TaskbarCreated");
private TaskbarHelper(Window window)
{
@@ -99,7 +96,7 @@ namespace NotificationFlyout.Wpf.UI.Helpers
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
- if (msg == WTASKBARCREATED || msg == WSETTINGCHANGE && (int)wParam == SPI_SETWORKAREA)
+ if (msg == WM_TASKBARCREATED || msg == (int)WndProcMessages.WM_SETTINGCHANGE && (int)wParam == SPI_SETWORKAREA)
{
TaskbarChanged?.Invoke(this, EventArgs.Empty);
}
diff --git a/NotificationFlyout.Wpf.UI/Helpers/ThemeChangedEventArgs.cs b/NotificationFlyout.Wpf.UI/Helpers/ThemeChangedEventArgs.cs
new file mode 100644
index 0000000..6da9c84
--- /dev/null
+++ b/NotificationFlyout.Wpf.UI/Helpers/ThemeChangedEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace NotificationFlyout.Wpf.UI.Helpers
+{
+ public class ThemeChangedEventArgs : EventArgs
+ {
+ internal ThemeChangedEventArgs(SystemTheme theme)
+ {
+ Theme = theme;
+ }
+
+ public SystemTheme Theme { get; private set; }
+ }
+}
diff --git a/NotificationFlyout.Wpf.UI/Helpers/WndProcMessages.cs b/NotificationFlyout.Wpf.UI/Helpers/WndProcMessages.cs
new file mode 100644
index 0000000..e6a2cb2
--- /dev/null
+++ b/NotificationFlyout.Wpf.UI/Helpers/WndProcMessages.cs
@@ -0,0 +1,11 @@
+namespace NotificationFlyout.Wpf.UI.Helpers
+{
+ internal enum WndProcMessages
+ {
+ WM_LBUTTONUP = 0x0202,
+ WM_MBUTTONUP = 0x0208,
+ WM_RBUTTONUP = 0x0205,
+ WM_MOUSEMOVE = 0x0200,
+ WM_SETTINGCHANGE = 0x001A,
+ }
+}
\ No newline at end of file
diff --git a/NotificationFlyout.Wpf.UI/NotificationFlyout.Wpf.UI.csproj b/NotificationFlyout.Wpf.UI/NotificationFlyout.Wpf.UI.csproj
index 0da0fef..4909a30 100644
--- a/NotificationFlyout.Wpf.UI/NotificationFlyout.Wpf.UI.csproj
+++ b/NotificationFlyout.Wpf.UI/NotificationFlyout.Wpf.UI.csproj
@@ -11,6 +11,7 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
+