Add some WinUI work
This commit is contained in:
@@ -2,6 +2,6 @@
|
||||
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public interface IPointerMonitor :
|
||||
public interface IPointer :
|
||||
IInitialization,
|
||||
IDisposable;
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
@@ -16,7 +16,10 @@ public record Rect
|
||||
}
|
||||
|
||||
public int X { get; }
|
||||
|
||||
public int Y { get; }
|
||||
|
||||
public int Width { get; }
|
||||
|
||||
public int Height { get; }
|
||||
}
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user