简体   繁体   中英

Register multiple keys pressed, when form is not in focus

I'm working on a program that will do something whenever a certain key is pressed regardless of whether or not the form is in focus. Right now it works just fine, but only with one hotkey. I can't figure out how to make more hotkeys, and check for them in a if statement or so. The code is below:

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);
    }
}

It won't accept the if statement at all with the "ghk" and "ghk2". Thank you in advance for helping.

Best regards

I wanted to do the same thing, and found the solution here . It states that the wParam stores the key identifier. So what you need to do (at WndProc) is:

//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

Then you can simply pass the key to HandleHotkey() if you want or have two different methods.

Edit: Here's how to make it pass the Keys parameter to the handler method:

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());
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM