unison/Handlers/HotkeyHandler.cs

293 lines
9.5 KiB
C#

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
namespace unison
{
public class HotkeyHandler
{
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
private const int HOTKEY_ID = 9000;
public enum MOD : int
{
None = 0x0000,
Alt = 0x0001,
Control = 0x0002,
Shift = 0x0004,
//Win = 0x0008
};
// reference => https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
public enum VK : int
{
None = 0x00,
Back = 0x08,
Tab = 0x09,
Clear = 0x0c,
Return = 0x0d,
Menu = 0x12,
Pause = 0x13,
Capital = 0x14,
Kana = 0x15,
Hangul = 0x15,
Junja = 0x17,
Final = 0x18,
Hanja = 0x19,
Kanji = 0x19,
Escape = 0x1b,
Convert = 0x1c,
NonConvert = 0x1d,
Accept = 0x1e,
ModeChange = 0x1f,
Space = 0x20,
Prior = 0x21,
Next = 0x22,
End = 0x23,
Home = 0x24,
Left = 0x25,
Up = 0x26,
Right = 0x27,
Down = 0x28,
Select = 0x29,
Print = 0x2a,
Execute = 0x2b,
Snapshot = 0x2c,
Insert = 0x2d,
Delete = 0x2e,
Help = 0x2f,
NumRow0 = 0x30,
NumRow1 = 0x31,
NumRow2 = 0x32,
NumRow3 = 0x33,
NumRow4 = 0x34,
NumRow5 = 0x35,
NumRow6 = 0x36,
NumRow7 = 0x37,
NumRow8 = 0x38,
NumRow9 = 0x39,
A = 0x41,
B = 0x42,
C = 0x43,
D = 0x44,
E = 0x45,
F = 0x46,
G = 0x47,
H = 0x48,
I = 0x49,
J = 0x4a,
K = 0x4b,
L = 0x4c,
M = 0x4d,
N = 0x4e,
O = 0x4f,
P = 0x50,
Q = 0x51,
R = 0x52,
S = 0x53,
T = 0x54,
U = 0x55,
V = 0x56,
W = 0x57,
X = 0x58,
Y = 0x59,
Z = 0x5a,
Apps = 0x5d,
Sleep = 0x5f,
NumPad0 = 0x60,
NumPad1 = 0x61,
NumPad2 = 0x62,
NumPad3 = 0x63,
NumPad4 = 0x64,
NumPad5 = 0x65,
NumPad6 = 0x66,
NumPad7 = 0x67,
NumPad8 = 0x68,
NumPad9 = 0x69,
Multiply = 0x6a,
Add = 0x6b,
Separator = 0x6c,
Subtract = 0x6d,
Decimal = 0x6e,
Divide = 0x6f,
F1 = 0x70,
F2 = 0x71,
F3 = 0x72,
F4 = 0x73,
F5 = 0x74,
F6 = 0x75,
F7 = 0x76,
F8 = 0x77,
F9 = 0x78,
F10 = 0x79,
F11 = 0x7a,
F12 = 0x7b,
F13 = 0x7c,
F14 = 0x7d,
F15 = 0x7e,
F16 = 0x7f,
F17 = 0x80,
F18 = 0x81,
F19 = 0x82,
F20 = 0x83,
F21 = 0x84,
F22 = 0x85,
F23 = 0x86,
F24 = 0x87,
NumLock = 0x90,
Scroll = 0x91,
LMenu = 0xa4,
RMenu = 0xa5,
BrowserBack = 0xa6,
BrowserForward = 0xa7,
BrowserRefresh = 0xa8,
BrowserStop = 0xa9,
BrowserSearch = 0xaa,
BrowserFavorites = 0xab,
BrowserHome = 0xac,
VolumeMute = 0xad,
VolumeDown = 0xae,
VolumeUp = 0xaf,
MediaNextTrack = 0xb0,
MediaPreviousTrack = 0xb1,
MediaStop = 0xb2,
MediaPlayPause = 0xb3,
LaunchMail = 0xb4,
LaunchMediaSelect = 0xb5,
LaunchApp1 = 0xb6,
LaunchApp2 = 0xb7,
};
public struct HotkeyPair
{
public MOD mod;
public VK vk;
public HotkeyPair(MOD _mod, VK _vk) { mod = _mod; vk = _vk; }
public uint GetMOD() { return (uint)mod; }
public uint GetVK() { return (uint)vk; }
public void SetMOD(MOD modmod) { mod = modmod; }
public void SetVK(VK vkvk) { vk = vkvk; }
}
private MainWindow _appWindow;
private readonly MPDHandler _mpd;
private IntPtr _windowHandle;
private HwndSource _source;
public HotkeyPair _NextTrack;
public HotkeyPair _PreviousTrack;
public HotkeyPair _PlayPause;
public HotkeyPair _VolumeUp;
public HotkeyPair _VolumeDown;
public HotkeyPair _VolumeMute;
public HotkeyPair _ShowWindow;
public HotkeyPair[] _Shortcuts;
public HotkeyHandler()
{
_mpd = (MPDHandler)Application.Current.Properties["mpd"];
Initialize();
}
public void Initialize()
{
_NextTrack = new HotkeyPair((MOD)Properties.Settings.Default.nextTrack_mod, (VK)Properties.Settings.Default.nextTrack_vk);
_PreviousTrack = new HotkeyPair((MOD)Properties.Settings.Default.previousTrack_mod, (VK)Properties.Settings.Default.previousTrack_vk);
_PlayPause = new HotkeyPair((MOD)Properties.Settings.Default.playPause_mod, (VK)Properties.Settings.Default.playPause_vk);
_VolumeUp = new HotkeyPair((MOD)Properties.Settings.Default.volumeUp_mod, (VK)Properties.Settings.Default.volumeUp_vk);
_VolumeDown = new HotkeyPair((MOD)Properties.Settings.Default.volumeDown_mod, (VK)Properties.Settings.Default.volumeDown_vk);
_VolumeMute = new HotkeyPair((MOD)Properties.Settings.Default.volumeMute_mod, (VK)Properties.Settings.Default.volumeMute_vk);
_ShowWindow = new HotkeyPair((MOD)Properties.Settings.Default.showWindow_mod, (VK)Properties.Settings.Default.showWindow_vk);
_Shortcuts = new HotkeyPair[] { _NextTrack, _PreviousTrack, _PlayPause, _VolumeUp, _VolumeDown, _VolumeMute, _ShowWindow };
}
public void Activate(Window win)
{
if (_source == null)
{
_windowHandle = new WindowInteropHelper(win).Handle;
_source = HwndSource.FromHwnd(_windowHandle);
AddHotkeys();
}
}
public void AddHotkeys()
{
_source.AddHook(HwndHook);
RegisterHotKey(_windowHandle, HOTKEY_ID, _NextTrack.GetMOD(), _NextTrack.GetVK());
RegisterHotKey(_windowHandle, HOTKEY_ID, _PreviousTrack.GetMOD(), _PreviousTrack.GetVK());
RegisterHotKey(_windowHandle, HOTKEY_ID, _PlayPause.GetMOD(), _PlayPause.GetVK());
RegisterHotKey(_windowHandle, HOTKEY_ID, _VolumeUp.GetMOD(), _VolumeUp.GetVK());
RegisterHotKey(_windowHandle, HOTKEY_ID, _VolumeDown.GetMOD(), _VolumeDown.GetVK());
RegisterHotKey(_windowHandle, HOTKEY_ID, _VolumeMute.GetMOD(), _VolumeMute.GetVK());
RegisterHotKey(_windowHandle, HOTKEY_ID, _ShowWindow.GetMOD(), _ShowWindow.GetVK());
}
public void RemoveHotkeys()
{
_source.RemoveHook(HwndHook);
UnregisterHotKey(_windowHandle, HOTKEY_ID);
}
private IntPtr HwndHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
const int WM_HOTKEY = 0x0312;
if (msg == WM_HOTKEY && wParam.ToInt32() == HOTKEY_ID)
{
uint vkey = ((uint)lParam >> 16) & 0xFFFF;
if (vkey == _NextTrack.GetVK())
_mpd.Next();
else if (vkey == _PreviousTrack.GetVK())
_mpd.Prev();
else if (vkey == _PlayPause.GetVK())
_mpd.PlayPause();
else if (vkey == _VolumeUp.GetVK())
_mpd.VolumeUp();
else if (vkey == _VolumeDown.GetVK())
_mpd.VolumeDown();
else if (vkey == _VolumeMute.GetVK())
_mpd.VolumeMute();
else if (vkey == _ShowWindow.GetVK())
{
if (_appWindow == null)
_appWindow = (MainWindow)Application.Current.MainWindow;
if (_appWindow.WindowState == WindowState.Minimized)
{
_appWindow.Show();
_appWindow.Activate();
_appWindow.WindowState = WindowState.Normal;
}
else
{
if (_appWindow.IsActive)
{
_appWindow.Hide();
_appWindow.WindowState = WindowState.Minimized;
}
else // not minimized but not in front
{
_appWindow.Show();
_appWindow.Activate();
_appWindow.WindowState = WindowState.Normal;
}
}
}
handled = true;
}
return IntPtr.Zero;
}
}
}