Instant Rimshot
Posted: Last updated:It's been a while since I've written anything here, I've been working on my master project like crazy, have a 6 month old baby and so haven't had much time for programming pet projects. Tonight I spent a half hour making perhaps the most useless application I'll ever make. It's based on the single-serving website http://instantrimshot.com which only has one huge red button, if you press it a rimshot sound is played. I thought it might be fun to have that available as a keyboard shortcut in windows, and then I started wondering how it could be done in C#.
The only way to get a global keyboard working in .NET is by calling into the Win32 API. To register a global hotkey there is the aptly named function RegisterHotKey. That requires you to have a window handle however, and I wanted to make the application as simple as possible, so I used a lower level API call, SetWindowsHookEx which lets you get notified of all keyboard activity on the system. I then check what keys are pressed and when the combination Ctrl+Shift+I is pressed the sound is played. There is only one way to exit the app, and that is by pressing the keyboard combination Ctrl+Shift+Alt+I, that cleans up the hook before exiting. So, the code is shown below, you can download the source or just download the program itself. Enjoy!
using System;
using System.IO;
using System.Media;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
class InstantRimshot {
const int WH_KEYBOARD_LL = 13;
const int WM_KEYDOWN = 0x100;
delegate int Hook(int code, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int code,
Hook func,
IntPtr hInstance,
int threadID);
[DllImport("user32.dll")]
static extern int UnhookWindowsHookEx(IntPtr hookHandle);
[DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr hhook,
int code,
IntPtr wParam,
IntPtr lParam);
static bool IsPressed(Keys check) {
return ((Control.ModifierKeys & check) == check);
}
static void Main() {
Stream sound = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("InstantRimshot.rimshot.wav");
SoundPlayer player = new SoundPlayer(sound);
player.Load();
IntPtr hookHandle = IntPtr.Zero;
hookHandle = SetWindowsHookEx(WH_KEYBOARD_LL,
delegate(int code, IntPtr wParam, IntPtr lParam) {
if (code >= 0 && wParam == (IntPtr) WM_KEYDOWN) {
Keys vkCode = (Keys)Marshal.ReadInt32(lParam);
if (Keys.I == vkCode
&& IsPressed(Keys.Control)
&& IsPressed(Keys.Shift)) {
if (IsPressed(Keys.Alt)) {
UnhookWindowsHookEx(hookHandle);
Application.Exit();
return CallNextHookEx(hookHandle, code,
wParam, lParam);
} else {
player.Play();
}
}
}
return CallNextHookEx(hookHandle, code, wParam, lParam);
}, IntPtr.Zero, 0);
Application.Run();
}
}