質問: WindowsアプリケーションをC++で開発しています。 キーイベントを取得するには、まずはWM_KEYDOWNを取得。 もっと早く知りたい場合は、グローバルフック。 さらに早く知りたい場合は、KeyboardFilterDriverを開発... このようにしてWindowsのキー入力について深堀してきたのですが、ハードからのキー入力をどのようにソフトで処理しているのか、一連の流れがつかめません。 ハードからカーネル、ドライバ、ユーザーランド、ユーザーアプリケーション....といったキー入力の一連の流れを詳しく教えてはいただけないでしょうか。 目的は、ユーザーランド側(システムではない方)でいち早くキー入力を取得したいのです。 ドライバ開発からすればシステムの一部としてキー入力を取得できるかもしれませんが、それではアプリケーションを利用できる層は限られています。(管理者でないといけない) なので、キー入力の仕組みをきちんと理解して、キー入力を取得できるようにしたいのです。 よろしくお願いします。
回答: **コメントから回答化** 一連の流れを図示しているのが、以下の記事の Fig.9 ですね。 **ただし2011年の記事なので、Windows10では何かしらの変更が入っている可能性はあります。** Keyloggers: Implementing keyloggers in Windows. Part Two !Fig 9: Overview of how Windows processes keyboard input Fig 9: Overview of how Windows processes keyboard input 図の中で赤丸の1.1, 1.2, 1.4がそれぞれ以下になります。 > > * 1.1. Setting hooks for keyboard messages > * 1.2. Using cyclical querying of the keyboard > * 1.4. Using the raw input model > > > UserModeで一番早いタイミングで読み取れるのは 1.2.の`GetAsyncnKeyState/GetKeyState`ですが、これの呼び出しはキーのUp/Downと連携出来ないので、データを取りこぼすか、頻繁に呼び出して、むやみにシステムの負荷が高くなる、といった可能性が多くなります。 比較的に安定して早いのは、1.4.の`RawInput`でしょう。これに使われる`WM_INPUT`はデフォルトでは通知されないので、明示的に受け取る仕組みを作って動かしておく必要があります。 Raw Input / About Raw Input Registration for Raw Input > > デフォルトでは、アプリケーションは生の入力を受け取りません。デバイスから生の入力を受け取るには、アプリケーションはデバイスを登録する必要があります。 > > > こちらに、複数のキーボードを接続して、特定のキーボードからの入力を無視する仕組みのデモと解説の記事があります。ソフト開発の参考になるでしょう。 Combining Raw Input and keyboard Hook to selectively block input from multiple keyboards このデモではRaw Input と keyboard Hookの両方を使っていますが、以下のような注意事項があり、LowLevelKeyboard Hookは使っていません。 > > フックに関しては、事はもう少しトリッキーになります。最初にAPIの組み合わせを試していたときは、グローバルなLow Level Keyboard Hook(WH_KEYBOARD_LL)を使おうとしました。問題は、低レベルキーボードフックを使用して何らかの入力をブロックすると(メッセージの進行を止めると)、WindowsはRaw Inputイベントを生成しないことを意味します。つまり、アプリケーションは適切なRaw Input message(WM_INPUT)を取得できません。そのため、Low Level Keyboard Hookを使用することはできませんが、標準のKeyboard Hook(WH_KEYBOARD)を使用する必要があります。これは設定が少し困難です。このフックをグローバルに、つまり実行中のアプリケーションに対して使用したい場合、そのプロシージャは別のDLLモジュール内になければなりません。 > > > ただし、上記のように組み合わせても、メッセージが通知されなかったり、色々と奇妙な現象が発生することが記載されています。注意しておいてください。 Hook message is missing Raw Input message is missing Yet more oddities