現在押されているキーを検出する方法は?


123

Windowsフォーム、あなたは、いつでも、カーソルのおかげで現在の位置を知ることができるカーソルのクラスを。

同じことがキーボードで利用できないようです。たとえば、Shiftキーが押されたかどうかを知ることはできますか?

すべてのキーボード通知(KeyDownおよびKeyUpイベント)を追跡することは絶対に必要ですか?


WPF環境などで作業していますか?
エポッター2009

70
@epotter:2番目の単語はWinFormsを表します。
Eddinsが

回答:


162
if ((Control.ModifierKeys & Keys.Shift) != 0) 

Ctrl+ Shiftがダウンしている場合も同様です。Shiftだけが押されているかどうかを確認したい場合は、

if (Control.ModifierKeys == Keys.Shift)

継承するクラスControl(フォームなど)を使用している場合は、Control.


8
私が何かを逃していない限り、あなたは質問に正しく答えていません。OPはすべてのキーについて尋ね、Shiftキーは例としてのみ使用しました。では、AからZ、0から9などの他のキーをどのように検出しますか
Ash

2
彼は答えを受け入れたので、修飾キーだけが必要だったようです。他のキーが必要な場合は、GetKeyStateAPI関数を呼び出す必要があります。
SLaks、2009

2
GetKeyStateは必要ありません。メッセージフィルターを追加するだけです。私の答えを見てください。
アッシュ

2
以下のためにWPFのソリューションを使用できKeyboard.Modifiers == ModifierKeys.Shift (検索にここに来たもののために)
ビル・ターベル

3
代わりに(Control.ModifierKeys & Keys.Shift) != 0使用できますControl.ModifierKeys.HasFlag(Keys.Shift)
tomuxmon

55

以下のコードは、Shiftキーだけでなく、現在押されているほぼすべてのキーを検出する方法です。

private KeyMessageFilter m_filter = new KeyMessageFilter();

private void Form1_Load(object sender, EventArgs e)
{
    Application.AddMessageFilter(m_filter);
}


public class KeyMessageFilter : IMessageFilter
{
    private const int WM_KEYDOWN = 0x0100;
    private const int WM_KEYUP = 0x0101;
    private bool m_keyPressed = false;

    private Dictionary<Keys, bool> m_keyTable = new Dictionary<Keys, bool>();

    public Dictionary<Keys, bool> KeyTable
    {
        get { return m_keyTable; }
        private set { m_keyTable = value; }
    }

    public bool IsKeyPressed()
    {
        return m_keyPressed;
    }

    public bool IsKeyPressed(Keys k)
    {
        bool pressed = false;

        if (KeyTable.TryGetValue(k, out pressed))
        {
            return pressed;
        }

        return false;
    }

    public bool PreFilterMessage(ref Message m)
    {
        if (m.Msg == WM_KEYDOWN)
        {
            KeyTable[(Keys)m.WParam] = true;

            m_keyPressed = true;
        }

        if (m.Msg == WM_KEYUP)
        {
            KeyTable[(Keys)m.WParam] = false;

            m_keyPressed = false;
        }

        return false;
    }
}

1
GetKeyStateより効率的です。Windowsが既に行っている場合、すべてのキーを追跡しても意味がありません。
SLaks

3
@Slaks、いくつかのベンチマークデータがない限り、あなたは推測しています。さらに、最初にそのキーボードイベントをトラップできる場合、GetKeyStateはキーの状態を通知します。私の質問の解釈は、OPはいつでもキーの状態を取得する方法を知りたいということです。したがって、GetKeyState自体は役に立たない。
アッシュ

3
これをどの程度正確に使用して、押されているキーを表示しますか?
Gabriel Ryan Nahmias 2013

Gabriel:フォームのフィールドとしてKeyMessageFilterのインスタンスを作成します。これをForm_LoadのApplication.AddMessageFilter()に渡します。次に、あなたがに興味を持っていることを各/任意のキーのために、このインスタンス上)(IsKeyPressedを呼び出す。
アッシュ

@回答ありがとうございます。上記のSHIFTキーなどを確認するためのコード例を作成できますか?
BKSpurgeon

23

System.Windows.Inputを参照すると、以下も確認できます。

if (Keyboard.Modifiers == ModifierKeys.Shift)

Keyboard名前空間は、Keyboard.IsKeyDown(Key)を使用して他のキーの押された状態を確認するためにも使用できます。または、KeyDownEventまたは同様のイベントをサブスクライブしている場合、イベント引数は現在押されているキーのリストを保持します。


1
実際、Keyboard.Modifiersは常に正しく機能するとは限りません。ハードな方法を見つけなければならなかった:discoveringdotnet.alexeyev.org/2008/09/...
マキシムAlexeyev

これがフォーム修飾子を使用していないことを除いて、System.Windows.Input修飾子は別の名前空間であり、毎回問題なく機能しています。
ジェフウェイン

18

これらの答えのほとんどは、非常に複雑であるか、私にはうまくいかないようです(たとえば、System.Windows.Inputが存在しないようです)。次に、正常に動作するサンプルコードをいくつか見つけました:http : //www.switchonthecode.com/tutorials/winforms-accessing-mouse-and-keyboard-state

今後ページが表示されなくなる場合は、以下の関連するソースコードを投稿します。

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

namespace MouseKeyboardStateTest
{
  public abstract class Keyboard
  {
    [Flags]
    private enum KeyStates
    {
      None = 0,
      Down = 1,
      Toggled = 2
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
    private static extern short GetKeyState(int keyCode);

    private static KeyStates GetKeyState(Keys key)
    {
      KeyStates state = KeyStates.None;

      short retVal = GetKeyState((int)key);

      //If the high-order bit is 1, the key is down
      //otherwise, it is up.
      if ((retVal & 0x8000) == 0x8000)
        state |= KeyStates.Down;

      //If the low-order bit is 1, the key is toggled.
      if ((retVal & 1) == 1)
        state |= KeyStates.Toggled;

      return state;
    }

    public static bool IsKeyDown(Keys key)
    { 
      return KeyStates.Down == (GetKeyState(key) & KeyStates.Down);
    }

    public static bool IsKeyToggled(Keys key)
    { 
      return KeyStates.Toggled == (GetKeyState(key) & KeyStates.Toggled);
    }
  }
}

3
System.Windows.Input存在する; これに苦労している他の人にとっては、への参照とPresentationCore、列挙WindowsBaseにアクセスするための追加の参照を追加する必要がありSystem.Windows.Input.Keyます。この情報は常にMSDNにあります。
アルフィー

1
このクラスはそうstaticではないはずabstractです。
リトルエンディアン2015

1
リンクが壊れています(404)。
Peter Mortensen

2
「将来ページが消えた場合、以下の関連するソースコードを投稿します」
parsley72

12

.NET Frameworkバージョン3.0以降ではKeyboard.IsKeyDown、新しいSystem.Windows.Input名前空間のメソッドを使用できます。例えば:

if (((Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) && Keyboard.IsKeyDown(Key.F))
{
    // CTRL + F is currently pressed
}

これはWPFの一部ですが、WinFormアプリケーションでは正常に機能します(PresentationCore.dllおよびWindowsBase.dllへの参照を追加した場合)。ただし、残念ながら、Keyboard.IsKeyDownメソッドの3.0および3.5バージョンはWinFormアプリケーションでは機能しませんでした。したがって、WinFormアプリケーションで使用する場合は、.NET Framework 4.0以降をターゲットにして機能させる必要があります。


ただのメモ、これはWPF専用です
Diego Vieira 2013

2
@DiegoVieira実際には、そうではありません。この機能はWPFの一部として追加されたため、これらのWPFライブラリを参照する必要がKeyboard.IsKeyDownありますが、WinFormプロジェクトでもメソッドは機能します。
Steven Doggart 2013

実際、PresentationCore.dllを追加する必要があります
Diego Vieira

2
Win32KeyboardDevice.GetKeyStatesFromSystem(Key):(
LMK

@LMKナイスキャッチ。私はそれを自分でテストし、あなたの言ったことを確認しました。その情報を反映するように回答を更新しました。ありがとう!
Steven Doggart 2014年

8

次のことが可能P /呼び出しは、 Win32のにダウンGetAsyncKeyStateキーボードの任意のキーをテストします。

Keys列挙型(Keys.Shiftなど)からこの関数に値を渡すことができるため、追加するのに数行のコードしか必要ありません。


Keyboardコンパイラによって認識されませんでしたがGetAsyncKeystate、user32 では問題なく動作しました。ありがとう!
アインシュタインX.ミステリー

5
if ((ModifierKeys == Keys.Control) && ((e.KeyChar & (char)Keys.F) != 0))
{
     // CTRL+F pressed !
}

3

Windowsフォームフォームでキーボード入力を管理するために私が見つけた最良の方法は、キーストロークの後、フォーカスされたコントロールがイベントを受け取る前にそれを処理することです。Microsoftは、.KeyPreviewFormという名前の組み込みレベルのプロパティを維持して、この正確なことを容易にしています。

public frmForm()
{
    // ...
    frmForm.KeyPreview = true;
    // ...
}

次に、フォームの_KeyDown、_KeyPress、および/または_KeyUpイベントをマーシャリングして、フォーカスされたフォームコントロールに表示される前に入力イベントにアクセスし、ハンドラーロジックを適用してイベントをそこにキャプチャするか、フォーカスされたフォームコントロールにパススルーさせることができます。 。

XAMLのイベントルーティングアーキテクチャほど構造的に優雅ではありませんが、Winformsでのフォームレベルの関数の管理がはるかに簡単になります。警告については、KeyPreviewMSDNノートを参照してください。


2
if (Form.ModifierKeys == Keys.Shift)

上記のコードがフォームのkeydownイベントにあり、他のコントロールがキーダウンのkeydownイベントをキャプチャしない場合、テキストボックスに対して機能します。

また、次のキー処理を中止することもできます。

e.Handled = true;

2
if (Control.ModifierKeys == Keys.Shift)
    //Shift is pressed

カーソルのx / y位置はプロパティであり、キーの押下(マウスのクリック/マウス移動など)はイベントです。通常、ベストプラクティスは、インターフェイスをイベントドリブンにすることです。上記が必要になるのは、Shift +マウスクリックを実行する場合のみです。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.