Add HotKeyListener

This commit is contained in:
Daniel Clark
2025-03-04 17:00:00 +00:00
parent dad7c54f0d
commit cee6557fb4
19 changed files with 424 additions and 297 deletions
+35 -79
View File
@@ -22,48 +22,27 @@ public class Cache<TValue>(IComparer<TValue> comparer) :
public void Clear() =>
items.Clear();
public bool Contains(TValue item)
{
int index = items.IndexOf(item);
if (index >= 0)
{
return true;
}
return false;
}
public bool Contains(TValue item) =>
items.IndexOf(item) >= 0;
public IEnumerator<TValue> GetEnumerator() =>
items.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => items.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() =>
items.GetEnumerator();
public int IndexOf(TValue item) =>
items.IndexOf(item);
public bool Remove(TValue item)
public bool Remove(TValue item) =>
items.Remove(item);
public bool TryGetValue(TValue key,
out TValue? item)
{
int index = items.IndexOf(item);
if (index >= 0)
{
items.RemoveAt(index);
return true;
}
return false;
}
public bool TryGetValue(TValue key, out TValue? item)
{
int index = items.IndexOf(key);
if (index >= 0)
{
item = items[index];
return true;
}
item = default;
return false;
var index = items.IndexOf(key);
item = index >= 0 ? items[index] : default;
return index >= 0;
}
private int FindInsertIndex(TValue item)
@@ -94,20 +73,20 @@ public class Cache<TValue>(IComparer<TValue> comparer) :
}
}
public class Cache<TKey, TValue>(IComparer<TKey> comparer) :
public class Cache<TKey, TValue>(IComparer<TKey>? comparer = null) :
ICache<TKey, TValue>
where TKey :
notnull
where TValue :
notnull
where TKey : notnull
where TValue : notnull
{
private readonly IComparer<TKey> comparer = comparer ?? Comparer<TKey>.Default;
private readonly List<KeyValuePair<TKey, TValue?>> items = [];
public TValue? this[TKey key]
{
get
{
int index = items.BinarySearch(new KeyValuePair<TKey, TValue?>(key, default),
int index = items.BinarySearch(
new KeyValuePair<TKey, TValue?>(key, default),
new KeyValuePairComparer<TKey, TValue?>(comparer));
if (index >= 0)
@@ -119,7 +98,8 @@ public class Cache<TKey, TValue>(IComparer<TKey> comparer) :
}
set
{
int index = items.BinarySearch(new KeyValuePair<TKey, TValue?>(key, default),
int index = items.BinarySearch(
new KeyValuePair<TKey, TValue?>(key, default),
new KeyValuePairComparer<TKey, TValue?>(comparer));
if (index >= 0)
@@ -135,7 +115,8 @@ public class Cache<TKey, TValue>(IComparer<TKey> comparer) :
public void Add(TKey key, TValue value)
{
int index = items.BinarySearch(new KeyValuePair<TKey, TValue?>(key, default),
int index = items.BinarySearch(
new KeyValuePair<TKey, TValue?>(key, default),
new KeyValuePairComparer<TKey, TValue?>(comparer));
if (index < 0)
@@ -148,53 +129,28 @@ public class Cache<TKey, TValue>(IComparer<TKey> comparer) :
public void Clear() => items.Clear();
public bool Contains(TKey key)
{
int index = items.FindIndex(kvp => comparer.Compare(kvp.Key, key) == 0);
if (index >= 0)
{
items.RemoveAt(index);
return true;
}
return false;
}
public bool Contains(TKey key) =>
items.FindIndex(kvp => comparer.Compare(kvp.Key, key) == 0) >= 0;
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() =>
items.GetEnumerator();
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() =>
items.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() =>
GetEnumerator();
public int IndexOf(TKey key) =>
public int IndexOf(TKey key) =>
items.FindIndex(kvp => comparer.Compare(kvp.Key, key) == 0);
public bool Remove(TKey key)
{
int index = items.FindIndex(kvp => comparer.Compare(kvp.Key, key) == 0);
if (index >= 0)
{
items.RemoveAt(index);
return true;
}
return false;
}
public bool Remove(TKey key) =>
items.RemoveAll(kvp => comparer.Compare(kvp.Key, key) == 0) > 0;
public bool TryGetValue(TKey key, out TValue? value)
{
int index = items.BinarySearch(new KeyValuePair<TKey, TValue?>(key, default(TValue)),
new KeyValuePairComparer<TKey, TValue?>(comparer));
public bool TryGetValue(TKey key, out TValue? value) =>
(items.BinarySearch(new KeyValuePair<TKey, TValue?>(key, default),
new KeyValuePairComparer<TKey, TValue?>(comparer)) is int index && index >= 0)
? (value = items[index].Value, true).Item2
: (value = default, false).Item2;
if (index >= 0)
{
value = items[index].Value;
return true;
}
value = default;
return false;
}
private class KeyValuePairComparer<TK, TV>(IComparer<TK> comparer) :
private class KeyValuePairComparer<TK, TV>(IComparer<TK> comparer) :
IComparer<KeyValuePair<TK, TV>>
{
private readonly IComparer<TK> comparer = comparer ?? Comparer<TK>.Default;
-1
View File
@@ -1,7 +1,6 @@
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
namespace Toolkit.Foundation;
+9
View File
@@ -0,0 +1,9 @@
namespace Toolkit.Foundation;
public enum ModifierKey : uint
{
Alt = 0x00000001,
Ctrl = 0x00000002,
Shift = 0x00000004,
Win = 0x00000008,
}
+177 -171
View File
@@ -1,175 +1,181 @@
namespace Toolkit.Foundation;
public enum VirtualKey
public enum VirtualKey : uint
{
None = 0,
LeftButton = 1,
RightButton = 2,
Cancel = 3,
MiddleButton = 4,
XButton1 = 5,
XButton2 = 6,
Back = 8,
Tab = 9,
Clear = 12,
Enter = 13,
Shift = 16,
Control = 17,
Menu = 18,
Pause = 19,
CapitalLock = 20,
Kana = 21,
Hangul = 21,
Junja = 23,
Final = 24,
Hanja = 25,
Kanji = 25,
Escape = 27,
Convert = 28,
NonConvert = 29,
Accept = 30,
ModeChange = 31,
Space = 32,
PageUp = 33,
PageDown = 34,
End = 35,
Home = 36,
Left = 37,
Up = 38,
Right = 39,
Down = 40,
Select = 41,
Print = 42,
Execute = 43,
Snapshot = 44,
Insert = 45,
Delete = 46,
Help = 47,
Number0 = 48,
Number1 = 49,
Number2 = 50,
Number3 = 51,
Number4 = 52,
Number5 = 53,
Number6 = 54,
Number7 = 55,
Number8 = 56,
Number9 = 57,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
LeftWindows = 91,
RightWindows = 92,
Application = 93,
Sleep = 95,
NumberPad0 = 96,
NumberPad1 = 97,
NumberPad2 = 98,
NumberPad3 = 99,
NumberPad4 = 100,
NumberPad5 = 101,
NumberPad6 = 102,
NumberPad7 = 103,
NumberPad8 = 104,
NumberPad9 = 105,
Multiply = 106,
Add = 107,
Separator = 108,
Subtract = 109,
Decimal = 110,
Divide = 111,
F1 = 112,
F2 = 113,
F3 = 114,
F4 = 115,
F5 = 116,
F6 = 117,
F7 = 118,
F8 = 119,
F9 = 120,
F10 = 121,
F11 = 122,
F12 = 123,
F13 = 124,
F14 = 125,
F15 = 126,
F16 = 127,
F17 = 128,
F18 = 129,
F19 = 130,
F20 = 131,
F21 = 132,
F22 = 133,
F23 = 134,
F24 = 135,
NavigationView = 136,
NavigationMenu = 137,
NavigationUp = 138,
NavigationDown = 139,
NavigationLeft = 140,
NavigationRight = 141,
NavigationAccept = 142,
NavigationCancel = 143,
NumberKeyLock = 144,
Scroll = 145,
LeftShift = 160,
RightShift = 161,
LeftControl = 162,
RightControl = 163,
LeftMenu = 164,
RightMenu = 165,
GoBack = 166,
GoForward = 167,
Refresh = 168,
Stop = 169,
Search = 170,
Favorites = 171,
GoHome = 172,
GamepadA = 195,
GamepadB = 196,
GamepadX = 197,
GamepadY = 198,
GamepadRightShoulder = 199,
GamepadLeftShoulder = 200,
GamepadLeftTrigger = 201,
GamepadRightTrigger = 202,
GamepadDPadUp = 203,
GamepadDPadDown = 204,
GamepadDPadLeft = 205,
GamepadDPadRight = 206,
GamepadMenu = 207,
GamepadView = 208,
GamepadLeftThumbstickButton = 209,
GamepadRightThumbstickButton = 210,
GamepadLeftThumbstickUp = 211,
GamepadLeftThumbstickDown = 212,
GamepadLeftThumbstickRight = 213,
GamepadLeftThumbstickLeft = 214,
GamepadRightThumbstickUp = 215,
GamepadRightThumbstickDown = 216,
GamepadRightThumbstickRight = 217,
GamepadRightThumbstickLeft = 218
None = 0x0000,
Back = 0x0008,
Tab = 0x0009,
Clear = 0x000C,
Enter = 0x000D,
Shift = 0x0010,
Control = 0x0011,
Menu = 0x0012,
Pause = 0x0013,
CapitalLock = 0x0014,
Kana = 0x0015,
Hangul = 0x0015,
Junja = 0x0017,
Final = 0x0018,
Hanja = 0x0019,
Kanji = 0x0019,
Escape = 0x001B,
Convert = 0x001C,
NonConvert = 0x001D,
Accept = 0x001E,
ModeChange = 0x001F,
Space = 0x0020,
PageUp = 0x0021,
PageDown = 0x0022,
End = 0x0023,
Home = 0x0024,
Left = 0x0025,
Up = 0x0026,
Right = 0x0027,
Down = 0x0028,
Select = 0x0029,
Print = 0x002A,
Execute = 0x002B,
Snapshot = 0x002C,
Insert = 0x002D,
Delete = 0x002E,
Help = 0x002F,
Number0 = 0x0030,
Number1 = 0x0031,
Number2 = 0x0032,
Number3 = 0x0033,
Number4 = 0x0034,
Number5 = 0x0035,
Number6 = 0x0036,
Number7 = 0x0037,
Number8 = 0x0038,
Number9 = 0x0039,
A = 0x0041,
B = 0x0042,
C = 0x0043,
D = 0x0044,
E = 0x0045,
F = 0x0046,
G = 0x0047,
H = 0x0048,
I = 0x0049,
J = 0x004A,
K = 0x004B,
L = 0x004C,
M = 0x004D,
N = 0x004E,
O = 0x004F,
P = 0x0050,
Q = 0x0051,
R = 0x0052,
S = 0x0053,
T = 0x0054,
U = 0x0055,
V = 0x0056,
W = 0x0057,
X = 0x0058,
Y = 0x0059,
Z = 0x005A,
LeftWindows = 0x005B,
RightWindows = 0x005C,
Application = 0x005D,
Sleep = 0x005F,
NumberPad0 = 0x0060,
NumberPad1 = 0x0061,
NumberPad2 = 0x0062,
NumberPad3 = 0x0063,
NumberPad4 = 0x0064,
NumberPad5 = 0x0065,
NumberPad6 = 0x0066,
NumberPad7 = 0x0067,
NumberPad8 = 0x0068,
NumberPad9 = 0x0069,
Multiply = 0x006A,
Add = 0x006B,
Separator = 0x006C,
Subtract = 0x006D,
Decimal = 0x006E,
Divide = 0x006F,
F1 = 0x0070,
F2 = 0x0071,
F3 = 0x0072,
F4 = 0x0073,
F5 = 0x0074,
F6 = 0x0075,
F7 = 0x0076,
F8 = 0x0077,
F9 = 0x0078,
F10 = 0x0079,
F11 = 0x007A,
F12 = 0x007B,
F13 = 0x007C,
F14 = 0x007D,
F15 = 0x007E,
F16 = 0x007F,
F17 = 0x0080,
F18 = 0x0081,
F19 = 0x0082,
F20 = 0x0083,
F21 = 0x0084,
F22 = 0x0085,
F23 = 0x0086,
F24 = 0x0087,
NavigationView = 0x0088,
NavigationMenu = 0x0089,
NavigationUp = 0x008A,
NavigationDown = 0x008B,
NavigationLeft = 0x008C,
NavigationRight = 0x008D,
NavigationAccept = 0x008E,
NavigationCancel = 0x008F,
NumberKeyLock = 0x0090,
Scroll = 0x0091,
LeftShift = 0x00A0,
RightShift = 0x00A1,
LeftControl = 0x00A2,
RightControl = 0x00A3,
LeftMenu = 0x00A4,
RightMenu = 0x00A5,
GoBack = 0x00A6,
GoForward = 0x00A7,
Refresh = 0x00A8,
Stop = 0x00A9,
Search = 0x00AA,
Favorites = 0x00AB,
GoHome = 0x00AC,
GamepadA = 0x00C3,
GamepadB = 0x00C4,
GamepadX = 0x00C5,
GamepadY = 0x00C6,
GamepadRightShoulder = 0x00C7,
GamepadLeftShoulder = 0x00C8,
GamepadLeftTrigger = 0x00C9,
GamepadRightTrigger = 0x00CA,
GamepadDPadUp = 0x00CB,
GamepadDPadDown = 0x00CC,
GamepadDPadLeft = 0x00CD,
GamepadDPadRight = 0x00CE,
GamepadMenu = 0x00CF,
GamepadView = 0x00D0,
GamepadLeftThumbstickButton = 0x00D1,
GamepadRightThumbstickButton = 0x00D2,
GamepadLeftThumbstickUp = 0x00D3,
GamepadLeftThumbstickDown = 0x00D4,
GamepadLeftThumbstickRight = 0x00D5,
GamepadLeftThumbstickLeft = 0x00D6,
GamepadRightThumbstickUp = 0x00D7,
GamepadRightThumbstickDown = 0x00D8,
GamepadRightThumbstickRight = 0x00D9,
GamepadRightThumbstickLeft = 0x00DA,
}
+8
View File
@@ -0,0 +1,8 @@
using Rect = Windows.Foundation.Rect;
namespace Toolkit.UI.WinUI;
public static class RectExtensions
{
public static Rect ToWindowsRect(this Windows.Rect rect) => new(rect.X, rect.Y, rect.Width, rect.Height);
}
+42 -23
View File
@@ -8,9 +8,10 @@ using System.Drawing;
using Windows.Win32.UI.Shell;
using Windows.Win32.UI.WindowsAndMessaging;
using Toolkit.Windows;
using Rect = Windows.Foundation.Rect;
using WinUIEx;
using Windows.Graphics;
using Rect = Windows.Foundation.Rect;
using System;
namespace Toolkit.UI.WinUI;
@@ -18,6 +19,14 @@ public static partial class WindowExtensions
{
private static SUBCLASSPROC? SubClassDelegate;
public static uint GetDpi(this Window window)
{
nint handle = WindowNative.GetWindowHandle(window);
if (handle == 0) return 0;
return PInvoke.GetDpiForWindow(new HWND(handle));
}
public static void Hide(this Window window)
{
nint handle = WindowNative.GetWindowHandle(window);
@@ -26,7 +35,7 @@ public static partial class WindowExtensions
WindowHelper.HideWindow(new HWND(handle));
}
public static void IsShownInSwitchers(this Window window,
public static void SetIsShownInSwitchers(this Window window,
bool value)
{
if (window.AppWindow is AppWindow appWindow)
@@ -35,17 +44,6 @@ public static partial class WindowExtensions
}
}
public static void SetSize(this Window window,
int width,
int height)
{
nint handle = WindowNative.GetWindowHandle(window);
if (handle == 0) return;
float value = PInvoke.GetDpiForWindow(new HWND(handle)) / 96f;
window.AppWindow.Resize(new SizeInt32((int)(width * (double)value), (int)(height * (double)value)));
}
public static void MoveAndResize(this Window window,
Rect rect)
{
@@ -87,19 +85,32 @@ public static partial class WindowExtensions
nint handle = WindowNative.GetWindowHandle(window);
if (handle == 0) return;
WindowHelper.SetForegroundWindow(new HWND(handle));
PInvoke.SetForegroundWindow(new HWND(handle));
}
public static void SetTopMost(this Window window,
bool value)
public static void SetIsMaximizable(this Window window, bool value) =>
window.UpdateOverlappedPresenter(presenter => presenter.IsMaximizable = value);
public static void SetIsMinimizable(this Window window, bool value) =>
window.UpdateOverlappedPresenter(presenter => presenter.IsMinimizable = value);
public static void SetIsResizable(this Window window, bool value) =>
window.UpdateOverlappedPresenter(presenter => presenter.IsResizable = value);
public static void SetSize(this Window window,
int width,
int height)
{
if (window.AppWindow is AppWindow appWindow &&
appWindow.Presenter is OverlappedPresenter presenter)
{
presenter.IsAlwaysOnTop = value;
}
nint handle = WindowNative.GetWindowHandle(window);
if (handle == 0) return;
float value = PInvoke.GetDpiForWindow(new HWND(handle)) / 96f;
window.AppWindow.Resize(new SizeInt32((int)(width * (double)value), (int)(height * (double)value)));
}
public static void SetIsTopMost(this Window window, bool value) =>
window.UpdateOverlappedPresenter(presenter => presenter.IsAlwaysOnTop = value);
public static void SetTransparency(this Window window,
bool value)
{
@@ -136,7 +147,6 @@ public static partial class WindowExtensions
WINDOW_EX_STYLE exStyle = (WINDOW_EX_STYLE)PInvoke.GetWindowLong(hWnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE);
_ = PInvoke.SetWindowLong(hWnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, (int)(exStyle & ~WINDOW_EX_STYLE.WS_EX_LAYERED));
}
private static unsafe void EnableTransparency(HWND hWnd)
{
SubClassDelegate = new SUBCLASSPROC(WindowSubClass);
@@ -147,12 +157,21 @@ public static partial class WindowExtensions
(int)(exStyle | WINDOW_EX_STYLE.WS_EX_LAYERED));
COLORREF blackColor = new COLORREF((uint)ToWin32(Color.Black));
_ = PInvoke.SetLayeredWindowAttributes(hWnd, blackColor, 0, LAYERED_WINDOW_ATTRIBUTES_FLAGS.LWA_COLORKEY |
_ = PInvoke.SetLayeredWindowAttributes(hWnd, blackColor, 0, LAYERED_WINDOW_ATTRIBUTES_FLAGS.LWA_COLORKEY |
LAYERED_WINDOW_ATTRIBUTES_FLAGS.LWA_ALPHA);
}
private static int ToWin32(Color c) => c.B << 16 | c.G << 8 | c.R;
private static void UpdateOverlappedPresenter(this Window window,
Action<OverlappedPresenter> action)
{
if (window.AppWindow.Presenter is OverlappedPresenter presenter)
{
action(presenter);
}
}
private static unsafe LRESULT WindowSubClass(HWND hWnd,
uint uMsg, WPARAM wParam, LPARAM lParam, nuint uIdSubclass, nuint dwRefData)
{
+5
View File
@@ -0,0 +1,5 @@
using Toolkit.Foundation;
namespace Toolkit.Windows;
public record HotKeyDescriptor(ModifierKey Modifiers, VirtualKey VirtualKey);
+49
View File
@@ -0,0 +1,49 @@
using CommunityToolkit.Mvvm.Messaging;
using Toolkit.Foundation;
namespace Toolkit.Windows;
public class HotKeyListener(ICache<int, HotKeyDescriptor> cache,
IMessenger messenger) :
IHotKeyListener,
IRecipient<WndProcEventArgs>
{
private bool isDisposed;
~HotKeyListener()
{
Dispose(false);
}
public void Initialize()
{
messenger.RegisterAll(this);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!isDisposed)
{
isDisposed = true;
}
}
public void Receive(WndProcEventArgs message)
{
const int WM_HOTKEY = 0x0312;
if (message.Message == WM_HOTKEY)
{
int key = (int)message.WParam;
if (cache.Contains(key))
{
messenger.Send(new HotKeyPressedEventArgs(key));
}
}
}
}
+57
View File
@@ -0,0 +1,57 @@
using Toolkit.Foundation;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.UI.Input.KeyboardAndMouse;
namespace Toolkit.Windows;
public class HotKeyManager(IWndProc wndProc,
ICache<int, HotKeyDescriptor> cache) :
IHotKeyManager
{
public void Add(int key, HotKeyDescriptor descriptor)
{
HOT_KEY_MODIFIERS modifiers = 0;
if ((descriptor.Modifiers & ModifierKey.Alt) == ModifierKey.Alt)
modifiers |= HOT_KEY_MODIFIERS.MOD_ALT;
if ((descriptor.Modifiers & ModifierKey.Ctrl) == ModifierKey.Ctrl)
modifiers |= HOT_KEY_MODIFIERS.MOD_CONTROL;
if ((descriptor.Modifiers & ModifierKey.Shift) == ModifierKey.Shift)
modifiers |= HOT_KEY_MODIFIERS.MOD_SHIFT;
if ((descriptor.Modifiers & ModifierKey.Win) == ModifierKey.Win)
modifiers |= HOT_KEY_MODIFIERS.MOD_WIN;
uint vk = (uint)descriptor.VirtualKey;
if (PInvoke.RegisterHotKey(new HWND(wndProc.Handle), key, modifiers, vk))
{
cache.Add(key, descriptor);
}
}
public bool Contains(int key) =>
cache.Contains(key);
public void Remove(int key)
{
PInvoke.UnregisterHotKey(new HWND(wndProc.Handle), key);
cache.Remove(key);
}
public void Dispose()
{
HWND hwnd = new(wndProc.Handle);
foreach (KeyValuePair<int, HotKeyDescriptor> item in cache)
{
PInvoke.UnregisterHotKey(hwnd, item.Key);
}
cache.Clear();
GC.SuppressFinalize(this);
}
~HotKeyManager()
{
Dispose();
}
}
@@ -0,0 +1,3 @@
namespace Toolkit.Windows;
public record HotKeyPressedEventArgs(int Key);
@@ -2,6 +2,6 @@
namespace Toolkit.Windows;
public interface ITaskbarButtonMonitor :
public interface IHotKeyListener :
IInitialization,
IDisposable;
+11
View File
@@ -0,0 +1,11 @@
namespace Toolkit.Windows;
public interface IHotKeyManager :
IDisposable
{
void Add(int key, HotKeyDescriptor descriptor);
bool Contains(int key);
void Remove(int key);
}
@@ -2,6 +2,6 @@
namespace Toolkit.Windows;
public interface IPointer :
public interface IPointerListener :
IInitialization,
IDisposable;
@@ -0,0 +1,7 @@
using Toolkit.Foundation;
namespace Toolkit.Windows;
public interface ITaskbarButtonListener :
IInitialization,
IDisposable;
+3 -1
View File
@@ -48,4 +48,6 @@ TranslateMessage
DispatchMessage
PostQuitMessage
DestroyWindow
GetModuleHandle
GetModuleHandle
RegisterHotKey
UnregisterHotKey
+1 -1
View File
@@ -62,7 +62,7 @@ public class NotifyIcon(IWndProc wndProc,
GC.SuppressFinalize(this);
}
public unsafe PointerLocation GetPointerPosition()
public static unsafe PointerLocation GetPointerPosition()
{
Point point = new();
_ = PInvoke.GetCursorPos(&point);
@@ -1,14 +1,13 @@
using CommunityToolkit.Mvvm.Messaging;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.UI.WindowsAndMessaging;
namespace Toolkit.Windows;
public class Pointer(IMessenger messenger) :
IPointer
public class PointerListener(IMessenger messenger) :
IPointerListener
{
private bool isDisposed;
private bool isPointerDrag;
@@ -16,7 +15,7 @@ public class Pointer(IMessenger messenger) :
private HOOKPROC? mouseEventDelegate;
private UnhookWindowsHookExSafeHandle? mouseHandle;
~Pointer()
~PointerListener()
{
Dispose(false);
}
@@ -27,25 +26,22 @@ public class Pointer(IMessenger messenger) :
GC.SuppressFinalize(this);
}
public unsafe void Initialize() =>
InitializeHook();
public unsafe void Initialize()
{
mouseEventDelegate = new HOOKPROC(MouseProc);
mouseHandle = PInvoke.SetWindowsHookEx(WINDOWS_HOOK_ID.WH_MOUSE_LL, mouseEventDelegate,
PInvoke.GetModuleHandle("user32.dll"), 0);
}
protected virtual void Dispose(bool disposing)
{
if (!isDisposed)
{
RemoveHook();
Remove();
isDisposed = true;
}
}
private unsafe void InitializeHook()
{
mouseEventDelegate = new HOOKPROC(MouseProc);
mouseHandle = PInvoke.SetWindowsHookEx(WINDOWS_HOOK_ID.WH_MOUSE_LL, mouseEventDelegate,
PInvoke.GetModuleHandle("user32.dll"), 0);
}
private LRESULT MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0)
@@ -82,7 +78,7 @@ public class Pointer(IMessenger messenger) :
return PInvoke.CallNextHookEx(mouseHandle, nCode, wParam, lParam);
}
private unsafe void RemoveHook()
private unsafe void Remove()
{
if (mouseHandle is not null && mouseHandle.DangerousGetHandle() != nint.Zero)
{
+1 -1
View File
@@ -42,7 +42,7 @@ public class TaskbarButton :
public void Receive(PointerReleasedEventArgs args)
{
if (!isDrag && isWithinBounds)
if (args.Button is PointerButton.Left && !isDrag && isWithinBounds)
{
messenger.Send(new TaskbarButtonInvokedEventArgs(this));
}
@@ -4,8 +4,8 @@ using UIAutomationClient;
namespace Toolkit.Windows;
public class TaskbarButtonMonitor :
ITaskbarButtonMonitor
public class TaskbarButtonListener :
ITaskbarButtonListener
{
private readonly IDispatcherTimer dispatcherTimer;
private readonly IDispatcherTimerFactory dispatcherTimerFactory;
@@ -19,7 +19,7 @@ public class TaskbarButtonMonitor :
private IUIAutomationElement? taskListElement;
private IntPtr taskListHandle;
public TaskbarButtonMonitor(ITaskbarList taskbarList,
public TaskbarButtonListener(ITaskbarList taskbarList,
IMessenger messenger,
IDispatcherTimerFactory dispatcherTimerFactory,
IServiceFactory serviceFactory,