2015-08-28 123 views
6

我需要做什麼:捕獲鍵盤快捷鍵和轉發

我需要捕獲所有的快捷按鍵,如按Ctrl +小號特定的應用程序。任何關鍵組合,即使它不是該應用程序的快捷方式。

然後我的,捕捉這些鍵中途申請需要驗證這些組合鍵,並檢查是否另一個我們的應用程序的運行可到關鍵的迴應,如果可以將命令發送到它。

我有什麼至今:

因爲我們寫的其他應用程序,我們可以輕鬆地發送鍵被處理,這不是一個問題。我可以得到應用程序的窗口句柄。我需要捕獲快捷鍵。這個應用我知道它是用C++編譯的。我期待找到一種方法來捕獲下列事件的等效中的WinForms:

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

現在一切工作的推進關鍵部件如預期。我只是錯過了那個句柄上的鍵的捕獲。我真的不希望有自己的冒險在掛鉤全鍵盤和檢測擊鍵是否在我的應用程序做或不該做我需要取消鍵或繼續處理。我寧願只獲得關鍵組合事件。我寧願不接受所有字母的傢伙按當他在鍵入一個文本框或任何東西。我真的在尋找什麼開始CTRLALTSHIFT或它們的任意組合是我想要做的

例子:

不受控制的應用程序:Notepad.exe的 我的中途程序:ShortcutHandler.exe 我的目標應用程序:A.exe,B.exe

ShortcutHandler.exe會偵聽Notepad.Exe快捷方式,然後將它們轉發給A.exe a第二B.EXE

現狀:

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 
+1

如果你寫的其他應用程序,爲什麼不把你的應用程序告訴其他應用程序,他們需要做什麼? –

+0

@RowlandShaw,因爲他想在任何*應用程序中掛接任意的按鍵/組合,然後在發生這種情況時在他的應用程序中執行一些操作。 – xan

+0

全球熱鍵會幫助你嗎?你試圖做的事情聽起來有點可疑 - 也許增加了一些你想要達到的目的的解釋會有助於 – xan

回答

3

前段時間,我必須做一些喜歡你,所以我發現這篇文章:​​,以及與此我能夠做什麼,我需要它。

但這是一個複雜的代碼,當你這麼說,你不想做讓所有鍵不放。對於我的節目,我創建了一個KeyboardHook類,使易與以前的文章中所獲得的代碼工作。

因此,有你可以用KeyboardHook類做一個片斷代碼:

// 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:如果你把這個你ShortcutHandler應用應用程序仍然會得到鑰匙。

而且下面是KeyboardHook代碼:

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); 
+0

這工作完美。但是你想補充一點,你需要在你的示例調用中調用'Start()'方法。 – Franck

+0

感謝您的通知,我更新了答案。 –