Skip to content

Commit 87d9831

Browse files
Fix some media keys not working
1 parent 991a0fb commit 87d9831

File tree

1 file changed

+110
-4
lines changed

1 file changed

+110
-4
lines changed

RadialActions/Data/ActionUtil.cs

Lines changed: 110 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,35 +29,141 @@ public static class ActionUtil
2929

3030
#endregion
3131

32+
private const int WM_APPCOMMAND = 0x0319;
33+
private const int APPCOMMAND_MEDIA_NEXTTRACK = 11;
34+
private const int APPCOMMAND_MEDIA_PREVIOUSTRACK = 12;
35+
private const int APPCOMMAND_MEDIA_STOP = 13;
36+
private const int APPCOMMAND_MEDIA_PLAY_PAUSE = 14;
37+
38+
private const uint INPUT_KEYBOARD = 1;
39+
private const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
3240
private const uint KEYEVENTF_KEYUP = 0x0002;
3341

3442
[DllImport("user32.dll", SetLastError = true)]
3543
private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, IntPtr dwExtraInfo);
3644

45+
[DllImport("user32.dll", SetLastError = true)]
46+
private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
47+
48+
[DllImport("user32.dll")]
49+
private static extern IntPtr GetForegroundWindow();
50+
51+
[DllImport("user32.dll")]
52+
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
53+
54+
[StructLayout(LayoutKind.Sequential)]
55+
private struct INPUT
56+
{
57+
public uint type;
58+
public InputUnion U;
59+
}
60+
61+
[StructLayout(LayoutKind.Explicit)]
62+
private struct InputUnion
63+
{
64+
[FieldOffset(0)]
65+
public KEYBDINPUT ki;
66+
}
67+
68+
[StructLayout(LayoutKind.Sequential)]
69+
private struct KEYBDINPUT
70+
{
71+
public ushort wVk;
72+
public ushort wScan;
73+
public uint dwFlags;
74+
public uint time;
75+
public IntPtr dwExtraInfo;
76+
}
77+
3778
/// <summary>
3879
/// Simulates a key press and release.
3980
/// </summary>
4081
/// <param name="vk">The virtual key code to simulate.</param>
4182
public static void SimulateKey(byte vk)
4283
{
43-
keybd_event(vk, 0, 0, IntPtr.Zero);
44-
keybd_event(vk, 0, KEYEVENTF_KEYUP, IntPtr.Zero);
84+
if (TrySendMediaAppCommand(vk))
85+
return;
86+
87+
SendKey(vk, isKeyUp: false);
88+
SendKey(vk, isKeyUp: true);
4589
}
4690

4791
/// <summary>
4892
/// Simulates pressing a key down.
4993
/// </summary>
5094
private static void KeyDown(byte vk)
5195
{
52-
keybd_event(vk, 0, 0, IntPtr.Zero);
96+
SendKey(vk, isKeyUp: false);
5397
}
5498

5599
/// <summary>
56100
/// Simulates releasing a key.
57101
/// </summary>
58102
private static void KeyUp(byte vk)
59103
{
60-
keybd_event(vk, 0, KEYEVENTF_KEYUP, IntPtr.Zero);
104+
SendKey(vk, isKeyUp: true);
105+
}
106+
107+
private static void SendKey(byte vk, bool isKeyUp)
108+
{
109+
var flags = isKeyUp ? KEYEVENTF_KEYUP : 0u;
110+
if (IsExtendedKey(vk))
111+
flags |= KEYEVENTF_EXTENDEDKEY;
112+
113+
var input = new INPUT
114+
{
115+
type = INPUT_KEYBOARD,
116+
U = new InputUnion
117+
{
118+
ki = new KEYBDINPUT
119+
{
120+
wVk = vk,
121+
wScan = 0,
122+
dwFlags = flags,
123+
time = 0,
124+
dwExtraInfo = IntPtr.Zero
125+
}
126+
}
127+
};
128+
129+
if (SendInput(1, new[] { input }, Marshal.SizeOf<INPUT>()) == 0)
130+
{
131+
keybd_event(vk, 0, flags, IntPtr.Zero);
132+
}
133+
}
134+
135+
private static bool IsExtendedKey(byte vk)
136+
{
137+
return vk is VK_MEDIA_PLAY_PAUSE
138+
or VK_MEDIA_NEXT_TRACK
139+
or VK_MEDIA_PREV_TRACK
140+
or VK_MEDIA_STOP
141+
or VK_VOLUME_MUTE
142+
or VK_VOLUME_DOWN
143+
or VK_VOLUME_UP;
144+
}
145+
146+
private static bool TrySendMediaAppCommand(byte vk)
147+
{
148+
var appCommand = vk switch
149+
{
150+
VK_MEDIA_PLAY_PAUSE => APPCOMMAND_MEDIA_PLAY_PAUSE,
151+
VK_MEDIA_NEXT_TRACK => APPCOMMAND_MEDIA_NEXTTRACK,
152+
VK_MEDIA_PREV_TRACK => APPCOMMAND_MEDIA_PREVIOUSTRACK,
153+
VK_MEDIA_STOP => APPCOMMAND_MEDIA_STOP,
154+
_ => -1
155+
};
156+
157+
if (appCommand < 0)
158+
return false;
159+
160+
var hwnd = GetForegroundWindow();
161+
if (hwnd == IntPtr.Zero)
162+
return false;
163+
164+
var lParam = (IntPtr)(appCommand << 16);
165+
SendMessage(hwnd, WM_APPCOMMAND, hwnd, lParam);
166+
return true;
61167
}
62168

63169
/// <summary>

0 commit comments

Comments
 (0)