web-dev-qa-db-ja.com

フォーカスされていないときにkeyPressを検出するにはどうすればよいですか?

フォームが現在アクティブなアプリケーションではないときにPrint Screenボタンが押されたことを検出しようとしています。

可能であれば、それを行う方法は?

13
James Holland

はい、できます。これは「システムフック」と呼ばれます。 。NETのグローバルシステムフック をご覧ください。

11
Arash

まあ、もしあなたがシステムフックに問題があったら、ここに既製の解決策があります( http://www.dreamincode.net/forums/topic/180436-global-hotkeys/ に基づく):

プロジェクトで静的クラスを定義します。

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

プロジェクトでクラスを定義します。

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

使用を追加:

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

次に、フォームにフィールドを追加します。

_private KeyHandler ghk;
_

そしてフォームコンストラクタで:

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

これら2つのメソッドをフォームに追加します。

_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は、ボタンを押すハンドラです。ここで異なるパラメーターを渡すことでボタンを変更できます:ghk = new KeyHandler(Keys.PrintScreen, this);

これで、プログラムは集中していなくてもブトン入力に反応します。

19

API GetAsyncKeyState() は、Windowsフックをセットアップする代わりに、完全に受け入れ可能な代替手段です。

これは、入力の受け取り方法によって異なります。イベント駆動型の通知を希望する場合は、フックが有効です。ただし、状態の変更にキーボードをポーリングしたい場合は、上記のAPIを使用できます。

以下は、GetAsyncKeyStateの使用方法の簡単なデモです。
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
Nicholas Miller