web-dev-qa-db-fra.com

Comment détecter keyPress alors que je ne suis pas concentré?

J'essaie de détecter l'appui sur le bouton Print Screen alors que le formulaire n'est pas l'application active actuelle.

Comment faire cela, si possible?

12
James Holland

Oui, cela s'appelle "Crochets système", jetez un coup d'œil à Crochets système globaux dans .NET .

11
Arash

Eh bien, si vous avez eu des problèmes avec les hooks System, voici une solution toute prête (basée sur http://www.dreamincode.net/forums/topic/180436-global-hotkeys/ ):

Définissez la classe statique dans votre projet:

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

Définir la classe dans votre projet:

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

ajouter des usings:

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

maintenant, dans votre formulaire, ajoutez un champ:

private KeyHandler ghk;

et dans le constructeur de formulaire:

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

Ajoutez ces 2 méthodes à votre formulaire:

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 est votre gestionnaire de presse de bouton. Vous pouvez changer le bouton en passant un paramètre différent ici: ghk = new KeyHandler(Keys.PrintScreen, this);

Maintenant, votre programme réagit pour une entrée en mémoire, même s'il n'est pas ciblé.

18
Przemysław Kalita

L'API GetAsyncKeyState() peut constituer une alternative parfaitement acceptable à la configuration de Windows Hook.

Cela dépend de la manière dont vous souhaitez recevoir les informations. Si vous préférez les notifications événementielles, vous devez utiliser un crochet. Cependant, si vous préférez polling le clavier pour les changements d'état, vous pouvez utiliser l'API ci-dessus.

Voici une démonstration simple de l’utilisation de GetAsyncKeyState:
Dérivé de 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...
    }
}
0
Nick Miller