web-dev-qa-db-ja.com

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

Windows Forms では、 Cursors クラスのおかげで、いつでもカーソルの現在位置を知ることができます。

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

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

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

これは次の場合にも当てはまります。 Ctrl+Shift ダウンしています。 Shiftのみが押されているかどうかを確認するには、

if (Control.ModifierKeys == Keys.Shift)

Controlを継承するクラス(フォームなど)にいる場合は、Control.を削除できます

160
SLaks

以下のコードは、現在押されているほとんどすべてのキーを検出する方法です。 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;
    }
}
54
Ash

System.Windows.Inputを参照する場合は、次も参照できます。

if (Keyboard.Modifiers == ModifierKeys.Shift)

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

23
Jeff Wain

これらの回答のほとんどは、あまりにも複雑すぎるか、私にはうまくいかないようです(たとえば、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);
    }
  }
}
17
parsley72

.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への参照を追加した場合)。ただし、残念ながら、3.0および3.5バージョンのKeyboard.IsKeyDownメソッドは、WinFormアプリケーションでは機能しませんでした。したがって、WinFormアプリケーションで使用する場合は、.NET Framework 4.0以降を対象にして、機能させる必要があります。

10
Steven Doggart

P/Invoke Win32まで GetAsyncKeyState を使用して、キーボードのキーをテストできます。

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

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

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

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

次に、フォームの_KeyDown、_KeyPress、および/または_KeyUpイベントをマーシャリングして、フォーカスされたフォームコントロールが表示される前に入力イベントにアクセスできます。 。

XAML's event-routing architectureほど構造的に優雅ではありませんが、Winformsのフォームレベルの機能の管理をはるかに簡単にします。 KeyPreviewのMSDNノート を参照してください。

3
Hardryv
if (Form.ModifierKeys == Keys.Shift)

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

また、さらにキー処理を停止したい場合があります:

e.Handled = true;
2
g.g
if (Control.ModifierKeys == Keys.Shift)
    //Shift is pressed

カーソルのx/y位置はプロパティであり、キー押下(マウスクリック/マウス移動など)はイベントです。通常、ベストプラクティスは、インターフェイスをイベント駆動型にすることです。上記が必要になるのは、Shift +マウスクリック操作をしようとしている場合だけです。

2
Rob Elliott

WinFormsの場合:

if( Form.ModifierKeys == Keys.Shift )

スタックオーバーフローの質問Windowsフォームでイベントを使用せずにShiftキーが押されたことを検出しますか?の複製のように聞こえます。

0
Will Eddins