Skip to content

Commit

Permalink
Merge pull request #1 from Lightczx/feat/winui3-themelistener
Browse files Browse the repository at this point in the history
  • Loading branch information
HO-COOH authored Sep 30, 2024
2 parents f7628c0 + 9ad6992 commit 70c489e
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 58 deletions.
2 changes: 1 addition & 1 deletion components/Helpers/src/MultiTarget.props
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
-->
<MultiTarget>uwp;wasdk;wpf;wasm;linuxgtk;macos;ios;android;</MultiTarget>
</PropertyGroup>
</Project>
</Project>
9 changes: 9 additions & 0 deletions components/Helpers/src/NativeMethods.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "https://aka.ms/CsWin32.schema.json",
"allowMarshaling": false,
"comInterop": {
"preserveSigMethods": [
"*"
]
}
}
101 changes: 44 additions & 57 deletions components/Helpers/src/ThemeListenerHelperWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,90 +3,77 @@
// See the LICENSE file in the project root for more information.

using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.UI.WindowsAndMessaging;

namespace CommunityToolkit.WinUI.HelpersRns;

#if WINAPPSDK

internal class ThemeListenerHelperWindow
{
public delegate void ThemeChangedHandler(ApplicationTheme theme);

public static ThemeListenerHelperWindow Instance = new();
private static string s_className = "ThemeListenerHelperWindow";
private IntPtr m_hwnd;

public event ThemeChangedHandler? ThemeChanged;
delegate Windows.Win32.Foundation.LRESULT WndProc(Windows.Win32.Foundation.HWND hWnd, uint msg, Windows.Win32.Foundation.WPARAM wParam, Windows.Win32.Foundation.LPARAM lParam);
private WndProc m_wnd_proc_delegate;
private void registerClass()

private static string s_className = "ThemeListenerHelperWindow";

private HWND m_hwnd;

private ThemeListenerHelperWindow()
{
unsafe
s_className = "ThemeListenerHelperWindow";
RegisterClass();
m_hwnd = CreateWindow();
}

private static unsafe void RegisterClass()
{
WNDCLASSEXW wcx = default;
wcx.cbSize = (uint)sizeof(WNDCLASSEXW);
fixed (char* pClassName = s_className)
{
var wcx = new Windows.Win32.UI.WindowsAndMessaging.WNDCLASSEXW();
wcx.cbSize = (uint)Marshal.SizeOf(wcx);
fixed (char* pClassName = s_className)
{
wcx.lpszClassName = new Windows.Win32.Foundation.PCWSTR(pClassName);
}
wcx.lpfnWndProc = wndProc;
if (PInvoke.RegisterClassEx(in wcx) == 0)
wcx.lpszClassName = pClassName;
wcx.lpfnWndProc = &WndProc;
if (PInvoke.RegisterClassEx(in wcx) is 0)
{
Debug.WriteLine(new Win32Exception(Marshal.GetLastWin32Error()).Message);
Marshal.ThrowExceptionForHR(Marshal.GetLastPInvokeError());
}
}

}

static Windows.Win32.Foundation.LRESULT wndProc(Windows.Win32.Foundation.HWND hWnd, uint msg, Windows.Win32.Foundation.WPARAM wParam, Windows.Win32.Foundation.LPARAM lParam)
private static unsafe HWND CreateWindow()
{
switch (msg)
HWND hwnd = PInvoke.CreateWindowEx(0, s_className, string.Empty, 0, 0, 0, 0, 0, default, null, null, null);
if (hwnd == HWND.Null)
{
case PInvoke.WM_SETTINGCHANGE:
var value = Registry.GetValue(
"""HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize""",
"AppsUseLightTheme",
true
);
if (value != null)
{
Instance.ThemeChanged?.Invoke((int)value == 1 ? ApplicationTheme.Light : ApplicationTheme.Dark);
}
break;
Marshal.ThrowExceptionForHR(Marshal.GetLastPInvokeError());
}
return PInvoke.DefWindowProc(hWnd, msg, wParam, lParam);
return hwnd;
}

unsafe private static IntPtr createWindow()
[UnmanagedCallersOnly(CallConvs = [typeof(CallConvStdcall)])]
private static LRESULT WndProc(HWND hWnd, uint msg, WPARAM wParam, LPARAM lParam)
{
var hwnd = PInvoke.CreateWindowEx(
0,
s_className,
"",
0,
0, 0, 0, 0,
new Windows.Win32.Foundation.HWND(),
null,
null,
null);
if (hwnd == IntPtr.Zero)
if (msg is PInvoke.WM_SETTINGCHANGE)
{
Debug.WriteLine(new Win32Exception(Marshal.GetLastWin32Error()).Message);
// REG_DWORD
object? value = Registry.GetValue(
@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize",
"AppsUseLightTheme",
true);

if (value is int dword)
{
Instance.ThemeChanged?.Invoke(dword is 1 ? ApplicationTheme.Light : ApplicationTheme.Dark);
}
}
return hwnd;
}
private ThemeListenerHelperWindow()
{
m_wnd_proc_delegate = wndProc;
s_className = "ThemeListenerHelperWindow";
registerClass();
m_hwnd = createWindow();

return PInvoke.DefWindowProc(hWnd, msg, wParam, lParam);
}
}
#endif

0 comments on commit 70c489e

Please sign in to comment.