Add some WinUI work

This commit is contained in:
Dan Clark
2024-11-17 21:25:27 +00:00
parent b5bf17821c
commit 796ef41e3f
25 changed files with 426 additions and 159 deletions
@@ -2,6 +2,6 @@
namespace Toolkit.Windows;
public interface IPointerMonitor :
public interface IPointer :
IInitialization,
IDisposable;
+46 -36
View File
@@ -1,41 +1,51 @@
SetWindowsHookEx
GetModuleHandle
CallNextHookEx
GetPhysicalCursorPos
FindWindowEx
FindWindow
GetWindowRect
DestroyWindow
DefWindowProcW
CallNextHookEx
CreateSolidBrush
CreateWindowExW
RegisterClassW
GetSystemMetrics
MonitorFromWindow
RegisterWindowMessage
GetDpiForWindow
SetWindowPos
SHCreateShellItemArrayFromDataObject
Shell_NotifyIcon
GetSystemMetricsForDpi
GetSystemMetrics
DWM_WINDOW_CORNER_PREFERENCE
DefSubclassProc
DefWindowProcW
DeleteObject
DestroyWindow
DwmSetWindowAttribute
FillRect
FindWindow
FindWindowEx
GetClientRect
GetCurrentProcess
SetProcessInformation
PROCESS_POWER_THROTTLING_STATE
GetDpiForWindow
GetPhysicalCursorPos
GetSystemMetrics
GetSystemMetricsForDpi
GetWindowLong
GetWindowRect
MonitorFromWindow
PROCESS_POWER_THROTTLING_CURRENT_VERSION
PROCESS_POWER_THROTTLING_EXECUTION_SPEED
SetPriorityClass
WINDOW_STYLE
DefSubclassProc
SetLayeredWindowAttributes
WM_ERASEBKGND
SetWindowSubclass
GetClientRect
CreateSolidBrush
DwmSetWindowAttribute
DWM_WINDOW_CORNER_PREFERENCE
FillRect
SetLayeredWindowAttributes
DeleteObject
PROCESS_POWER_THROTTLING_STATE
RegisterClassW
RegisterWindowMessage
RemoveWindowSubclass
GetWindowLong
SetWindowLong
SHCreateShellItemArrayFromDataObject
SetLayeredWindowAttributes
SetPriorityClass
SetProcessInformation
SetWindowLong
SetWindowPos
SetWindowSubclass
SetWindowsHookEx
Shell_NotifyIcon
WINDOW_STYLE
WM_ERASEBKGND
SetForegroundWindow
ShowWindow
GetCursorPos
UnregisterClass
CreateWindowEx
RegisterClass
DefWindowProc
GetMessage
TranslateMessage
DispatchMessage
PostQuitMessage
DestroyWindow
GetModuleHandle
+17 -10
View File
@@ -1,11 +1,12 @@
using CommunityToolkit.Mvvm.Messaging;
using System.Drawing;
using System.Runtime.InteropServices;
using Toolkit.Foundation;
using Windows.Win32;
namespace Toolkit.Windows;
public partial class NotifyIcon(IWndProc wndProc,
public class NotifyIcon(IWndProc wndProc,
IMessenger messenger) :
INotifyIcon,
IRecipient<WndProcEventArgs>
@@ -17,11 +18,6 @@ public partial class NotifyIcon(IWndProc wndProc,
private bool isDisposed;
private NotifyIconData notifyIconData;
~NotifyIcon()
{
Dispose(false);
}
private enum NotifyIconBalloonType
{
None = 0x00,
@@ -66,6 +62,14 @@ public partial class NotifyIcon(IWndProc wndProc,
GC.SuppressFinalize(this);
}
public unsafe PointerLocation GetPointerPosition()
{
Point point = new();
_ = PInvoke.GetCursorPos(&point);
return new PointerLocation(point.X, point.Y);
}
public void Initialize()
{
messenger.RegisterAll(this);
@@ -79,15 +83,18 @@ public partial class NotifyIcon(IWndProc wndProc,
switch (message.LParam)
{
case (uint)WndProcMessages.WM_LBUTTONUP:
messenger.Send(new NotifyIconInvokedEventArgs(PointerButton.Left));
messenger.Send(new NotifyIconInvokedEventArgs(PointerButton.Left,
GetPointerPosition()));
break;
case (uint)WndProcMessages.WM_MBUTTONUP:
messenger.Send(new NotifyIconInvokedEventArgs(PointerButton.Middle));
messenger.Send(new NotifyIconInvokedEventArgs(PointerButton.Middle,
GetPointerPosition()));
break;
case (uint)WndProcMessages.WM_RBUTTONUP:
messenger.Send(new NotifyIconInvokedEventArgs(PointerButton.Right));
messenger.Send(new NotifyIconInvokedEventArgs(PointerButton.Right,
GetPointerPosition()));
break;
}
}
@@ -1,3 +1,4 @@
namespace Toolkit.Windows;
public record NotifyIconInvokedEventArgs(PointerButton PointerButton);
public record NotifyIconInvokedEventArgs(PointerButton Button,
PointerLocation Location);
+5
View File
@@ -59,4 +59,9 @@ public static partial class PInvoke
public static void GetAppBarPosition(ref AppBarData appBarData) =>
SHAppBarMessage(AppBarMessage.GetTaskbarPos, ref appBarData);
internal static bool SetWindowSubclass(HWND value1, Func<HWND, uint, WPARAM, LPARAM, nuint, nuint, LRESULT> value2, int v1, nuint v2)
{
throw new NotImplementedException();
}
}
@@ -7,8 +7,8 @@ using Windows.Win32.UI.WindowsAndMessaging;
namespace Toolkit.Windows;
public class PointerMonitor(IMessenger messenger) :
IPointerMonitor
public class Pointer(IMessenger messenger) :
IPointer
{
private bool isDisposed;
private bool isPointerDrag;
@@ -16,7 +16,7 @@ public class PointerMonitor(IMessenger messenger) :
private HOOKPROC? mouseEventDelegate;
private UnhookWindowsHookExSafeHandle? mouseHandle;
~PointerMonitor()
~Pointer()
{
Dispose(false);
}
@@ -126,9 +126,9 @@ public class PointerMonitor(IMessenger messenger) :
}
}
private unsafe bool TryGetPointer(out Point point)
private unsafe bool TryGetPointer(out System.Drawing.Point point)
{
fixed (Point* lpPointLocal = &point)
fixed (System.Drawing.Point* lpPointLocal = &point)
{
return PInvoke.GetPhysicalCursorPos(lpPointLocal);
}
@@ -136,7 +136,7 @@ public class PointerMonitor(IMessenger messenger) :
private bool TryGetPointerLocation([MaybeNullWhen(false)] out PointerLocation location)
{
if (TryGetPointer(out Point point))
if (TryGetPointer(out System.Drawing.Point point))
{
location = new PointerLocation(point.X, point.Y);
return true;
+3
View File
@@ -16,7 +16,10 @@ public record Rect
}
public int X { get; }
public int Y { get; }
public int Width { get; }
public int Height { get; }
}
+2 -2
View File
@@ -40,7 +40,7 @@ public class Taskbar(IMessenger messenger,
return state;
}
public IntPtr GetHandle() => WindowHelper.Find("Shell_TrayWnd");
public IntPtr GetHandle() => WindowHelper.FindWindow("Shell_TrayWnd");
public void Receive(WndProcEventArgs args)
{
@@ -63,7 +63,7 @@ public class Taskbar(IMessenger messenger,
public void Receive(PointerMovedEventArgs args)
{
nint taskbarHandle = GetHandle();
if (WindowHelper.TryGetBounds(taskbarHandle, out Rect? rect))
if (WindowHelper.TryGetWindowBounds(taskbarHandle, out Rect? rect))
{
if (args.Location.IsWithinBounds(rect))
{
+2 -2
View File
@@ -49,7 +49,7 @@ public class TaskbarButtonMonitor :
taskListHandle = taskbarList.GetHandle();
taskListElement = clientUIAutomation.ElementFromHandle(taskListHandle);
if (WindowHelper.TryGetBounds(taskListHandle, out Rect? rect))
if (WindowHelper.TryGetWindowBounds(taskListHandle, out Rect? rect))
{
taskbarRectCache = rect;
}
@@ -60,7 +60,7 @@ public class TaskbarButtonMonitor :
private bool CheckDirtyTaskbarRegion()
{
if (WindowHelper.TryGetBounds(taskListHandle, out Rect? rect))
if (WindowHelper.TryGetWindowBounds(taskListHandle, out Rect? rect))
{
if (taskbarRectCache?.Width != rect.Width ||
taskbarRectCache?.Height != rect.Height)
+3 -3
View File
@@ -5,8 +5,8 @@ public class TaskbarList(ITaskbar taskbar) :
{
public IntPtr GetHandle()
{
nint rebarHandle = WindowHelper.Find("ReBarWindow32", taskbar.GetHandle());
nint taskHandle = WindowHelper.Find("MSTaskSwWClass", rebarHandle);
return WindowHelper.Find("MSTaskListWClass", taskHandle);
nint rebarHandle = WindowHelper.FindWindow("ReBarWindow32", taskbar.GetHandle());
nint taskHandle = WindowHelper.FindWindow("MSTaskSwWClass", rebarHandle);
return WindowHelper.FindWindow("MSTaskListWClass", taskHandle);
}
}
+28 -19
View File
@@ -7,35 +7,44 @@ namespace Toolkit.Windows;
public class WindowHelper
{
public static IntPtr GetHandle(string windowName) => PInvoke.FindWindow(windowName, null);
public static IntPtr FindWindow(string name) =>
PInvoke.FindWindow(name, null);
public static uint GetDpi(IntPtr handle) => PInvoke.GetDpiForWindow((HWND)handle);
public static IntPtr FindWindow(string name, IntPtr handle) =>
PInvoke.FindWindowEx(new HWND(handle), new HWND(), name, null);
public static void BringToForeground(HWND handle)
{
if (TryGetBoundsUnsafe(handle, out RECT bounds))
{
PInvoke.SetWindowPos(handle, new HWND(), bounds.left, bounds.top, bounds.right -
bounds.left, bounds.bottom - bounds.top, SET_WINDOW_POS_FLAGS.SWP_SHOWWINDOW | SET_WINDOW_POS_FLAGS.SWP_NOACTIVATE);
}
}
public static uint GetDpi(IntPtr handle) =>
PInvoke.GetDpiForWindow((HWND)handle);
public static IntPtr Find(string windowName) =>
PInvoke.FindWindow(windowName, null);
public static IntPtr GetWindowHandle(string name) =>
PInvoke.FindWindow(name, null);
public static IntPtr Find(string windowName, IntPtr parentHandle) =>
PInvoke.FindWindowEx(new HWND(parentHandle), new HWND(), windowName, null);
public static bool HideWindow(IntPtr hWnd) =>
PInvoke.ShowWindow(new HWND(hWnd), SHOW_WINDOW_CMD.SW_HIDE);
public static void MoveAndResize(HWND handle, int x, int y, int width, int height) =>
public static void MoveAndResizeWindow(HWND handle, int x, int y, int width, int height) =>
PInvoke.SetWindowPos(handle, new HWND(), x, y, width, height, 0);
public static bool TryGetBounds(IntPtr handle,
public static bool SetForegroundWindow(HWND handle)
{
if (TryGetWindowBoundsUnsafe(handle, out RECT bounds))
{
return PInvoke.SetWindowPos(handle, new HWND(), bounds.left, bounds.top, bounds.right -
bounds.left, bounds.bottom - bounds.top, SET_WINDOW_POS_FLAGS.SWP_SHOWWINDOW | SET_WINDOW_POS_FLAGS.SWP_NOACTIVATE) == 1;
}
return false;
}
public static bool ShowWindow(IntPtr hWnd) =>
PInvoke.ShowWindow(new HWND(hWnd), SHOW_WINDOW_CMD.SW_SHOW);
public static bool TryGetWindowBounds(IntPtr handle,
[MaybeNullWhen(false)] out Rect rect)
{
if (TryGetBoundsUnsafe(handle, out RECT unsafeRect))
if (TryGetWindowBoundsUnsafe(handle, out RECT unsafeRect))
{
rect = new Rect(unsafeRect.left, unsafeRect.top, unsafeRect.right - unsafeRect.left, unsafeRect.bottom - unsafeRect.top);
return true;
}
@@ -43,7 +52,7 @@ public class WindowHelper
return false;
}
private static unsafe bool TryGetBoundsUnsafe(IntPtr handle, out RECT rect)
private static unsafe bool TryGetWindowBoundsUnsafe(IntPtr handle, out RECT rect)
{
fixed (RECT* lpRectLocal = &rect)
{
+42 -37
View File
@@ -1,7 +1,7 @@
using CommunityToolkit.Mvvm.Messaging;
using Toolkit.Foundation;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.Graphics.Gdi;
using Windows.Win32.UI.WindowsAndMessaging;
namespace Toolkit.Windows;
@@ -10,56 +10,61 @@ public class WndProc(IMessenger messenger) :
IWndProc
{
private WNDPROC? handler;
private bool isDisposed;
~WndProc()
{
Dispose(false);
}
public IntPtr Handle { get; private set; }
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void Initialize() => InitializeWndProc();
protected virtual void Dispose(bool disposing)
{
if (isDisposed)
{
return;
}
isDisposed = true;
PInvoke.DestroyWindow((HWND)Handle);
}
private LRESULT HandleWndProc(HWND hWnd, uint msg,
WPARAM wParam, LPARAM lParam)
{
messenger.Send(new WndProcEventArgs(msg,
(uint)wParam.Value,
(uint)lParam.Value));
return PInvoke.DefWindowProc(hWnd, msg, wParam, lParam);
}
private unsafe void InitializeWndProc()
{
string windowName = Guid.NewGuid().ToString();
handler = Wndproc;
string windowId = $"WndProc_Handler_{Guid.NewGuid()}";
handler = HandleWndProc;
WNDCLASSW wndProcWindow;
wndProcWindow.style = 0;
wndProcWindow.lpfnWndProc = handler;
wndProcWindow.cbClsExtra = 0;
wndProcWindow.cbWndExtra = 0;
wndProcWindow.hInstance = new HINSTANCE();
wndProcWindow.hIcon = new HICON();
wndProcWindow.hCursor = new HCURSOR();
wndProcWindow.hbrBackground = new HBRUSH();
fixed (char* menuName = "")
fixed (char* className = windowId)
{
wndProcWindow.lpszMenuName = new PCWSTR(menuName);
WNDCLASSW wndCLass = new()
{
lpfnWndProc = handler,
lpszClassName = className,
};
_ = PInvoke.RegisterClass(wndCLass);
}
fixed (char* className = windowName)
{
wndProcWindow.lpszClassName = new PCWSTR(className);
}
PInvoke.RegisterClass(wndProcWindow);
Handle = PInvoke.CreateWindowEx(0, wndProcWindow.lpszClassName,
new PCWSTR(), 0, 0, 0, 0, 0, new HWND(),
new HMENU(),
new HINSTANCE());
}
private LRESULT Wndproc(HWND param0, uint param1, WPARAM param2, LPARAM param3)
{
messenger.Send(new WndProcEventArgs(param1, (uint)param2.Value, (uint)param3.Value));
return PInvoke.DefWindowProc(param0, param1, param2, param3);
}
public void Initialize()
{
InitializeWndProc();
Handle = PInvoke.CreateWindowEx(0, windowId, windowId, 0, 0, 0, 0, 0,
new HWND(IntPtr.Zero), null, null, null);
}
}