2015-08-28 3 views
6

Что мне нужно сделать:ярлыки Захват клавиатуры и вперед

мне нужно, чтобы захватить все нажатия клавиш быстрого доступа, такие как Ctrl + S от конкретного применения. Любая комбинация клавиш, даже если это не ярлык для этого приложения.

Затем мое приложение midway, которое захватывает эти ключи, должно проверить эту комбинацию клавиш и проверить, может ли другое из наших приложений работать на этот ключ, и если он может отправить ему команду.

То, что я до сих пор:

Поскольку мы писали другие приложения, мы можем легко отправить ключи для обработки, что это не проблема. Я могу получить дескриптор окна приложения. Мне нужно захватить сочетания клавиш. Это приложение, которое я знаю, оно построено на C++. Я ищу, чтобы найти способ, чтобы захватить эквивалент следующего события в Winforms:

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

Сейчас все работает, как ожидается, на ключевой части вперед. Мне просто не хватает захвата ключей на этом дескрипторе. Я действительно не хочу прибегать к тому, чтобы подключить всю клавиатуру и определить, выполняется ли ключевой штрих в моих приложениях или нет, и мне нужно отменить ключ или продолжить процесс. Я бы предпочел также получать только ключевые комбинации событий. Я бы предпочел не получать все письма, которые нажимает парень, когда он вводит текстовое поле или что-то еще. Я действительно искал что-нибудь, начиная с CTRL, ALT, SHIFT или любой их комбинации

Пример того, что я хочу сделать:

бесконтрольное применение: Notepad.exe мое приложение midway: 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

Некоторое время назад я должен сделать что-то, как вы, так что я нашел эту статью: A Simple C# Keyboard Hook, и с этим я был в состоянии сделать то, что мне это нужно.

Но это сложный код, и, как вы сказали, вы не хотите, чтобы все было нажато. Для моей программы я создал класс 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

Спасибо за уведомление, я обновил ответ. –

Смежные вопросы