-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHotKey.cs
110 lines (93 loc) · 3.37 KB
/
HotKey.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using WpfApplicationHotKey.WinApi;
namespace STTGoPlayer
{
//credits: https://www.outcoldman.com/en/archive/2010/09/11/register-hotkey-in-system-for-wpf-application/
internal class HotKeyWinApi
{
public const int WmHotKey = 0x0312;
[DllImport("user32.dll", SetLastError = true)]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, ModifierKeys fsModifiers, Keys vk);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
}
public sealed class HotKey : IDisposable
{
public event Action<HotKey> HotKeyPressed;
private readonly int _id;
private bool _isKeyRegistered;
readonly IntPtr _handle;
public HotKey(ModifierKeys modifierKeys, Keys key, Window window)
: this(modifierKeys, key, new WindowInteropHelper(window))
{
Contract.Requires(window != null);
}
public HotKey(ModifierKeys modifierKeys, Keys key, WindowInteropHelper window)
: this(modifierKeys, key, window.Handle)
{
Contract.Requires(window != null);
}
public HotKey(ModifierKeys modifierKeys, Keys key, IntPtr windowHandle)
{
Contract.Requires(modifierKeys != ModifierKeys.None || key != Keys.None);
Contract.Requires(windowHandle != IntPtr.Zero);
Key = key;
KeyModifier = modifierKeys;
_id = GetHashCode();
_handle = windowHandle;
RegisterHotKey();
ComponentDispatcher.ThreadPreprocessMessage += ThreadPreprocessMessageMethod;
}
~HotKey()
{
Dispose();
}
public Keys Key { get; private set; }
public ModifierKeys KeyModifier { get; private set; }
public void RegisterHotKey()
{
if (Key == Keys.None)
return;
if (_isKeyRegistered)
UnregisterHotKey();
_isKeyRegistered = HotKeyWinApi.RegisterHotKey(_handle, _id, KeyModifier, Key);
if (!_isKeyRegistered)
throw new ApplicationException("Hotkey already in use");
}
public void UnregisterHotKey()
{
_isKeyRegistered = !HotKeyWinApi.UnregisterHotKey(_handle, _id);
}
public void Dispose()
{
ComponentDispatcher.ThreadPreprocessMessage -= ThreadPreprocessMessageMethod;
UnregisterHotKey();
}
private void ThreadPreprocessMessageMethod(ref MSG msg, ref bool handled)
{
if (!handled)
{
if (msg.message == HotKeyWinApi.WmHotKey
&& (int)(msg.wParam) == _id)
{
OnHotKeyPressed();
handled = true;
}
}
}
private void OnHotKeyPressed()
{
if (HotKeyPressed != null)
HotKeyPressed(this);
}
}
}