简体   繁体   中英

How do I detect keyPress while not focused?

I am trying to detect the Print Screen button press while the form is not the current active application.

How to do that, if possible?

Well, if you had problems with System hooks, here is ready-made solution (based on http://www.dreamincode.net/forums/topic/180436-global-hotkeys/ ):

Define static class in your project:

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

Define class in your project:

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

add usings:

using System.Windows.Forms;
using System.Runtime.InteropServices;

now, in your Form, add field:

private KeyHandler ghk;

and in Form constructor:

ghk = new KeyHandler(Keys.PrintScreen, this);
ghk.Register();

Add those 2 methods to your form:

private void HandleHotkey()
{
        // Do stuff...
}

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

HandleHotkey is your button press handler. You can change the button by passing different parameter here: ghk = new KeyHandler(Keys.PrintScreen, this);

Now your program reacts for buton input even if not focused.

是的,你可以,它被称为“系统钩子”,看看.NET 中的全局系统钩子

The API GetAsyncKeyState() may be a perfectly acceptable alternative to setting up Windows Hook.

This depends on how you desire to receive the input. If you prefer event-driven notifications, then a hook is the way to go; however, if you prefer polling the keyboard for state changes, you can use the API above.

Here is a simple demonstration of how to use GetAsyncKeyState :
Derived from Pinvoke.NET

[DllImport("User32.dll")]
private static extern short GetAsyncKeyState(int vKey);

private static readonly int VK_SNAPSHOT = 0x2C; //This is the print-screen key.

//Assume the timer is setup with Interval = 16 (corresponds to ~60FPS).
private System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();

private void timer1_Tick(object sender, EventArgs e)
{
    short keyState = GetAsyncKeyState(VK_SNAPSHOT);

    //Check if the MSB is set. If so, then the key is pressed.
    bool prntScrnIsPressed = ((keyState >> 15) & 0x0001) == 0x0001;

    //Check if the LSB is set. If so, then the key was pressed since
    //the last call to GetAsyncKeyState
    bool unprocessedPress = ((keyState >> 0)  & 0x0001) == 0x0001;

    if (prntScrnIsPressed)
    {
        //TODO Execute client code...
    }

    if (unprocessedPress)
    {
        //TODO Execute client code...
    }
}

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