web-dev-qa-db-ja.com

C ++でキーが押されているかどうかを確認する方法

Windowsでキーが押されているかどうかを確認するにはどうすればよいですか?

9
snivy9014

他の人が述べたように、これを行うクロスプラットフォームの方法はありませんが、Windowsでは次のようにできます:

以下のコードは、キー「A」がダウンしているかどうかを確認します。

if(GetKeyState('A') & 0x8000/*Check if high-order bit is set (1 << 15)*/)
{
    // Do stuff
}

シフトなどの場合、次のいずれかを渡す必要があります。 https://msdn.Microsoft.com/de-de/library/windows/desktop/dd375731(v = vs.85).aspx

if(GetKeyState(VK_SHIFT) & 0x8000)
{
    // Shift down
}

下位ビットは、キーが切り替えられているかどうかを示します。

SHORT keyState = GetKeyState(VK_CAPITAL/*(caps lock)*/);
bool isToggled = keyState & 1;
bool isDown = keyState & 0x8000;

ああ、また忘れないで

#include <Windows.h>
17
Frank S.

キーがヒットしたかどうかをチェックし、ヒットしなかった場合は続行できる移植可能な機能はありません。これは常にシステムに依存します。

Linuxおよびその他のposix準拠システムのソリューション:

ここでは、Morgan Mattewsのコードの場合 POSIX準拠システムと互換性のある方法でkbhit()機能を提供します。彼は、termiosレベルでバッファリングを非アクティブ化するトリックを使用します。

ウィンドウの解決策:

Windowsの場合、Microsoftは _kbhit() を提供しています

2
Christophe

キーが押されたかどうかを確認し、はいの場合は、何かをする

この(報告によるとPosix)関数がOSで利用可能な場合、 'select()'を検討してください。

'select()'は、提供されている関数を使用して作成する3セットのビットを使用します(man select、FD_SETなどを参照)。おそらく入力ビットを作成するだけです(今のところ)


manページから:

'select()' "プログラムが複数のファイル記述子を監視できるようにし、1つまたは複数のファイル記述子がI/O操作のクラス(たとえば、入力可能)で"準備完了 "になるまで待機します。対応するI/O操作を実行することが可能です(たとえば、ブロックせずにread(2)...)」

Selectが呼び出されたとき:

a)関数はセットで識別された各fdを調べ、そのfd状態が何かを実行できる(おそらく読み取り、おそらく書き込み)ことを示している場合、selectは戻り、それを実行させます...ビットをスキャンし、設定されたビットを見つけ、そのビットに関連付けられたfdでアクションを実行します。

最初のセット(selectに渡される)には、アクティブな入力fd(通常はデバイス)が含まれます。おそらく、このセットの1ビットで十分です。そして、1 fd(つまり、キーボードからの入力)、1ビットのみで、これはすべて非常に簡単です。このselectからの戻り値を使用して、(おそらく、charをフェッチした後に)「do-stuff」を実行できます。

b)関数にはタイムアウトもあります。これにより、fd状態の変化を待つ時間を特定できます。 fdの状態が変わらない場合、タイムアウトにより 'select()'が0で返されます(つまり、キーボード入力がありません)この時点でコードは何か、おそらく出力を行うことができます。

fyi-fdは通常0,1,2 ...です。CがSTDIN、1、およびSTDOUTとして0を使用することに注意してください。


簡単なテストのセットアップ:ターミナル(コンソールとは別)を開き、そのターミナルでttyコマンドを入力してそのIDを見つけます。応答は通常、「/ dev/pts/0」、3、または17などです。

次に、openを使用して「select()」で使用するfdを取得します。

// flag options are: O_RDONLY, O_WRONLY, or O_RDWR
int inFD = open( "/dev/pts/5", O_RDONLY ); 

この値を計算すると便利です。

考慮すべきスニペットは次のとおりです(man selectから):

  fd_set rfds;
  struct timeval tv;
  int retval;

  /* Watch stdin (fd 0) to see when it has input. */
  FD_ZERO(&rfds);
  FD_SET(0, &rfds);

  /* Wait up to five seconds. */
  tv.tv_sec = 5;
  tv.tv_usec = 0;

  retval = select(1, &rfds, NULL, NULL, &tv);
  /* Don't rely on the value of tv now! */

  if (retval == -1)
      perror("select()");
  else if (retval)
      printf("Data is available now.\n");  // i.e. doStuff()
      /* FD_ISSET(0, &rfds) will be true. */
  else
      printf("No data within five seconds.\n"); // i.e. key not pressed
1
2785528