2015-04-10 1 views
0

Я работаю над программой, которая будет делать что-либо всякий раз, когда нажимается определенный ключ независимо от того, находится ли форма в фокусе. Сейчас это работает отлично, но только с одной горячей клавишей. Я не могу понять, как сделать больше горячих клавиш, и проверить их в инструкции if или так. Код ниже:Зарегистрировать несколько нажатых клавиш, когда форма не находится в фокусе

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 

namespace DotA_2_Timer 
{ 
    public partial class Form1 : Form 
    { 
     private KeyHandler ghk; 
     private KeyHandler ghk2; 

     public Form1() 
     { 
      InitializeComponent(); 
      ghk = new KeyHandler(Keys.A, this); 
      ghk2 = new KeyHandler(Keys.B, this); 
      ghk.Register(); 
      ghk2.Register(); 
     } 

     public class KeyHandler 
     { 
      [DllImport("user32.dll")] 
      private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk); 

      [DllImport("user32.dll")] 
      private static extern bool UnregisterHotKey(IntPtr hWnd, int id); 

      private int key; 
      private IntPtr hWnd; 
      private int id; 

      public KeyHandler(Keys key, Form form) 
      { 
       this.key = (int)key; 
       this.hWnd = form.Handle; 
       id = this.GetHashCode(); 
      } 

      public override int GetHashCode() 
      { 
       return key^hWnd.ToInt32(); 
      } 

      public bool Register() 
      { 
       return RegisterHotKey(hWnd, id, 0, key); 
      } 

      public bool Unregiser() 
      { 
       return UnregisterHotKey(hWnd, id); 
      } 
     } 

     public static class Constants 
     { 
      //windows message id for hotkey 
      public const int WM_HOTKEY_MSG_ID = 0x0312; 
     } 

    private void HandleHotkey() 
    { 
     if (ghk == Keys.A) { 
      MessageBox.Show("The Key A is pressed"); 
     } 
     if (ghk2 == Keys.B) { 
      MessageBox.Show("The Key B is pressed"); 
     }  
    } 

    protected override void WndProc(ref Message m) 
    { 
     if (m.Msg == Constants.WM_HOTKEY_MSG_ID) 
      HandleHotkey(); 
     base.WndProc(ref m); 
    } 
} 

Он не будет принимать, если заявление вообще с «ГХК» и «ghk2». Заранее благодарю за помощь.

С наилучшими пожеланиями

+0

Вот почему вам нужно * идентификатор * аргумент. Вы не можете использовать два из этих классов, они оба создают одно и то же сообщение. –

+0

Im не surre, что вы имеете в виду .. Извините –

ответ

0

Я хотел сделать то же самое, и нашел решение here. В нем указано, что wParam хранит ключевой идентификатор. Так что вам нужно сделать (в WndProc) является:

//WndProc(ref Message m) 
if (m.WParam.ToInt32() == ghk.GetHashCode()) 
    //The key associated with ghk got pressed 
if (m.WParam.ToInt32() == ghk2.GetHashCode()) 
    //The key associated with ghk2 got pressed 

Тогда вы можете просто передать ключ к HandleHotkey(), если вы хотите или иметь два различных метода.

Edit: Вот как сделать это передать параметр Ключи к методу обработчика:

private List<KeyHandler> Handlers = new List<KeyHandler>(); 
public MainForm() 
{ 
    InitializeComponent(); 
    Handlers.Add(new KeyHandler(Keys.Z, this)); 
    Handlers.Last().Register(); 
    Handlers.Add(new KeyHandler(Keys.H, this)); 
    Handlers.Last().Register(); 
} 

protected override void WndProc(ref Message m) 
{ 
    if (m.Msg == Constants.WM_HOTKEY_MSG_ID) 
    { 
     int key = m.WParam.ToInt32(); 
     HandleHotkey(Handlers.First(entry => entry.GetHashCode() == key).Key); 
    } 
    base.WndProc(ref m); 
} 

private void MainForm_FormClosing(object sender, FormClosingEventArgs e) 
{ 
    Handlers.ForEach(entry => entry.Unregiser()); 
}