Capture keyboard shortcuts and go

What do I need to do:

I need to capture all keystrokes for shortcuts, such as Ctrl + S from a specific application. Any key combination, even if it is not a shortcut to this application.

Then my midway application that captures these keys should check this key combination and check if another of our applications can work on this key, and if it can send a command to it.

What I still have:

Since we wrote other applications, we can easily send processed keys that are not a problem. I can get the handle of the application window. I need to capture keyboard shortcuts. This is the application that I know, it is built in C ++. I am looking to find a way to capture the equivalent of the following event in Winforms:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 

Now everything works as expected on the front of the key. I just do not have enough key capture on this descriptor. I really do not want to resort to connecting the entire keyboard and determining whether the key stroke is running in my applications or not, and I need to cancel the key or continue the process. I would also prefer to receive only key combinations of events. I would prefer not to receive all the letters that the guy clicks when he enters a text box or something else. I am really looking for anything starting with Ctrl , ALT , SHIFT or any combination of them

An example of what I want to do:

uncontrolled application: Notepad.exe my application midway: ShortcutHandler.exe my target applications: A.exe, B.exe

ShortcutHandler.exe will listen to Notepad.Exe shortcuts and then redirect them to A.exe and B.exe

Situation:

 1 - in Notepad.exe press CTRL+H for replace 2 - ShortcutHandler.exe detect CTRL+H pressed on Notepad.exe 3 - ShortcutHandler.exe Analyse CTRL+H and knows it need to do some task 4 - ShortcutHandler.exe call Save on A.exe in reaction to CTRL+H in Notepad.exe 5 - ShortcutHandler.exe call Print report in B.exe in reaction to CTRL+H in Notepad.exe 
+6
source share
1 answer

Some time ago I was supposed to do something like you, so I found this article: Simple C # Keyboard Hook , and with that I was able to do what I needed.

But this is complex code, and as you said, you do not want everything to be clicked. For my program, I created the KeyboardHook class, which simplifies working with the code obtained in the previous article.

So, there is a code snippet of what you can do with the KeyboardHook class:

 // Put this on the begin of your form (like the constructor on FormLoad). var hook = new KeyboardHook(); hook.KeyDown += (sender, e) => { // e.Control is a bool property if true Control is press. // e.Shift is a bool property if true Shift is press. // e.Key has a key that was press. // This if ignores anything that don't begin with Control or Shift. if(!e.Control && !e.Shift) return; // your code below: if(e.Control && e.Key == Keys.H) { // do your code here. // like: Analyse CTRL+H and knows it need to do some task. } }; hook.Start(); // Until here goes in the begin of your form. // Put this on the end of your form (like in the Dispose or FormClose). hook.Release(); hook.Dispose(); 

PS: If you put this in the ShortcutHandler application, the application will still receive the keys.

And below is the KeyboardHook code:

 using System.Runtime.InteropServices; using System.Windows.Forms; public class KeyboardHook : IDisposable { #region Fields private bool _lControlKeyIsDown; private bool _rControlKeyIsDown; private bool _lShiftKeyIsDown; private bool _rShiftKeyIsDown; #endregion #region Properties private bool ControlIsDown { get { return _lControlKeyIsDown || _rControlKeyIsDown; } } private bool ShiftIsDown { get { return _lShiftKeyIsDown || _rShiftKeyIsDown; } } #endregion #region Constructors public KeyboardHook() { _proc = HookCallback; } #endregion #region Events public event HookKeyDownHandler KeyDown; #endregion #region Methods public void Start() { _hookID = SetHook(_proc); } private static IntPtr SetHook(LowLevelKeyboardProc proc) { using (var curProcess = Process.GetCurrentProcess()) using (var curModule = curProcess.MainModule) { return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0); } } private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0) { var vkCode = Marshal.ReadInt32(lParam); var key = (Keys)vkCode; if (wParam == (IntPtr)WM_KEYDOWN) { switch (key) { case Keys.LControlKey: _lControlKeyIsDown = true; break; case Keys.RControlKey: _rControlKeyIsDown = true; break; case Keys.LShiftKey: _lShiftKeyIsDown = true; break; case Keys.RShiftKey: _rShiftKeyIsDown = true; break; default: if (KeyDown != null) { var args = new HookKeyDownEventArgs((Keys)vkCode, ShiftIsDown, ControlIsDown); KeyDown(this, args); } break; } } if (wParam == (IntPtr)WM_KEYUP) { switch (key) { case Keys.LControlKey: _lControlKeyIsDown = false; break; case Keys.RControlKey: _rControlKeyIsDown = false; break; case Keys.LShiftKey: _lShiftKeyIsDown = false; break; case Keys.RShiftKey: _rShiftKeyIsDown = false; break; } } } return CallNextHookEx(_hookID, nCode, wParam, lParam); } public void Release() { UnhookWindowsHookEx(_hookID); } public void Dispose() { Release(); } #endregion #region Interoperability private const int WH_KEYBOARD_LL = 13; private const int WM_KEYDOWN = 0x0100; private const int WM_KEYUP = 0x0101; private readonly LowLevelKeyboardProc _proc; private IntPtr _hookID = IntPtr.Zero; private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr GetModuleHandle(string lpModuleName); #endregion } public class HookKeyDownEventArgs : EventArgs { #region Fields private readonly Keys _key; private readonly bool _shift; private readonly bool _control; #endregion #region Properties public Keys Key { get { return _key; } } public bool Shift { get { return _shift; } } public bool Control { get { return _control; } } #endregion #region Constructors public HookKeyDownEventArgs(Keys key, bool shift, bool control) { _key = key; _shift = shift; _control = control; } #endregion } public delegate void HookKeyDownHandler(object sender, HookKeyDownEventArgs e); 
+3
source

All Articles