Add HotKeyListener
This commit is contained in:
+35
-79
@@ -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,7 +1,6 @@
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System;
|
||||
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public enum ModifierKey : uint
|
||||
{
|
||||
Alt = 0x00000001,
|
||||
Ctrl = 0x00000002,
|
||||
Shift = 0x00000004,
|
||||
Win = 0x00000008,
|
||||
}
|
||||
+177
-171
@@ -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,
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Toolkit.Windows;
|
||||
|
||||
public record HotKeyDescriptor(ModifierKey Modifiers, VirtualKey VirtualKey);
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -48,4 +48,6 @@ TranslateMessage
|
||||
DispatchMessage
|
||||
PostQuitMessage
|
||||
DestroyWindow
|
||||
GetModuleHandle
|
||||
GetModuleHandle
|
||||
RegisterHotKey
|
||||
UnregisterHotKey
|
||||
@@ -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)
|
||||
{
|
||||
@@ -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,
|
||||
Reference in New Issue
Block a user