
Windows API を使い、コンソール画面への入力をリアルタイムに(即時に) 取得する方法を確認していきます。
過去の記事では scanf 関数などを使って、文字列の入力を受付して、 エンターが入力された段階でプログラムが文字列を受け取る、という仕組みでした。
しかし、これではリアルタイムに動作するアプリへの入力が処理できないですね。
例えばキャラクタを FPS などでよくある「WASD」キーや、十字キーで操作するなど。 毎回入力待ちでアプリが停止して知っては、成り立たないです。
スペースキーの入力があったら終了するプログラムです。
#include <stdio.h>
#include <windows.h>
int main() {
printf("キーボードでスペースキーを押したら終了します\n");
while(1) {
if(GetAsyncKeyState(VK_SPACE) & 0x01 ) {
// スペースキーが押された!
printf("スペースキーが押されました\n");
break;
}
Sleep(1);
}
}
実行すると下のような結果になりました。
キーボードでスペースキーを押したら終了します
スペースキーが押されました
スペースキー以外をおしても画面上になにも反応はでないです。 スペースキーを押すと即座に画面上に「スペースキーが押されました」と表示がされるかと思います。
今回、キーボードの入力を受け付けている部分のコードです。
while(1) {
if(GetAsyncKeyState(VK_SPACE) & 0x01 ) {
// スペースキーが押された!
printf("スペースキーが押されました\n");
break;
}
Sleep(1);
}
while(1){ ・・・プログラム・・・ }
という書き方で、while 文の中身のプログラムを無限ループできます。
while 文の条件式は true でも良いです。条件が "真" と評価されていれば繰り返されます。
5 行目で、GetAsyncKeyState 関数が登場しています。 これは Windows API を試用した関数で、その時点でのキーボードの状態を確認して結果を返す関数です。
確認したい対象のキーボードのキーを引数で渡します。
今回は VK_SPACE という定数を引数に代入しています。
VK_SPACE という定数も windows.h ヘッダーをインクルードすることで参照できるようになります。
これは、キーボーボードの「スペースキー」を表す定数です。 他にもマウスやテンキーボードのそれぞれのキーを表す定数もあらかじめ用意されており、 それぞれキーの状態を取得できます。
代表的なキーボードなどの入力確認定数一覧
入力内容 | 定数 |
---|---|
VK_F1 | F1キー |
VK_NUMPAD0 ~ 9 | テンキーの 0 ~ 9 |
VK_LEFT | ←キー |
VK_UP | ↑キー |
VK_RIGHT | →キー |
VK_DOWN | ↓キー |
VK_LBUTTON | マウスの左ボタン |
VK_RBUTTON | マウスの右ボタン |
VK_MBUTTON | マウスの中央ボタン |
0~9、A~Z キーは直接、数字で入力します。数字(キーコード)とキーボードのキーの対応表を下に乗せておきます。
コード | キー | コード | キー | コード | キー | コード | キー | コード | キー |
---|---|---|---|---|---|---|---|---|---|
0x30 | 0 | 0x31 | 1 | 0x32 | 2 | 0x33 | 3 | 0x34 | 4 |
0x37 | 7 | 0x38 | 8 | 0x39 | 9 | ||||
0x41 | A | 0x42 | B | 0x43 | C | 0x44 | D | 0x45 | E |
0x47 | G | 0x48 | H | 0x49 | I | 0x4A | J | 0x4B | K |
0x4D | M | 0x4E | N | 0x4F | O | 0x50 | P | 0x51 | Q |
0x53 | S | 0x54 | T | 0x55 | U | 0x56 | V | 0x57 | W |
0x59 | Y | 0x5A | Z |
テンキーのキーボードの 0~9 はまた別のキーコードが割り当てられていますので注意が必要です。
GetAsyncKeyState 関数で対象のキーボードの値を参照していると、 状態は下の用に切り替わっていきます。
それぞれの状態は下で判定できます。
状態 | 判定方法 |
---|---|
押していない状態 | if ( GetAsyncKeyState(キーコード) == 0 ) { ・・・ } |
キー入力時 | if ( GetAsyncKeyState(キーコード) & 0x01 ) { ・・・ } |
押されている間の状態 | if (GetAsyncKeyState(キーコード) & 0xff00 != 0 ) { ・・・ } |
while の無限ループの中に以下のSleep命令が含まれています。
while(1) {
if(GetAsyncKeyState(VK_SPACE) & 0x01 ) {
// スペースキーが押された!
printf("スペースキーが押されました\n");
break;
}
Sleep(1);
}
この 10 行目の Sleep 文がなくともプログラムは動作しますが、 Windows OS の動作が不安定になる可能性があります。
無限ループ処理などの中で Sleep 文を入れることで、このタイミングで CPU はこのプログラムの処理を中断して休むことができます。 Windows などの OS は複数のプログラムを同時に動かすことができるマルチタスクと呼ばれる仕組みが根本にあり、 一つのプログラムだけを集中して実行するのではなく、実行敷いているプログラムを非常に短い感覚で切替て他のプログラムも同時に動かしています。
この Sleep 文を定期的に実行することで、CPU はこのタイミングで、他のプログラムの処理に切り替えることができる目印となります。 もしこの Sleep 文がないと、CPU はこのプログラムの実行だけに集中してしまうので、Windows OS が動くための基本的なプログラムの 処理が行われずに、動作が不安定になってしまう可能性がある、ということです。
コメント、ありがとうございます。
ごめんなさい。エラーでうまく送信できませんでした。ご迷惑をおかけします。しばらくおいてから再度送信を試していただくか、以下から DM などでご連絡頂ければと思います。
Twitter:@NodachiSoft_jpお名前:以下の内容でコメントを送信します。よろしければ、「送信」を押してください。修正する場合は「戻る」を押してください
お名前: