

WindowsアプリケーションをC++で開発しています。

キーイベントを取得するには、まずはWM_KEYDOWNを取得。  
もっと早く知りたい場合は、グローバルフック。  
さらに早く知りたい場合は、KeyboardFilterDriverを開発...

このようにしてWindowsのキー入力について深堀してきたのですが、ハードからのキー入力をどのようにソフトで処理しているのか、一連の流れがつかめません。  
ハードからカーネル、ドライバ、ユーザーランド、ユーザーアプリケーション....といったキー入力の一連の流れを詳しく教えてはいただけないでしょうか。

目的は、ユーザーランド側（システムではない方）でいち早くキー入力を取得したいのです。  
ドライバ開発からすればシステムの一部としてキー入力を取得できるかもしれませんが、それではアプリケーションを利用できる層は限られています。（管理者でないといけない）  
なので、キー入力の仕組みをきちんと理解して、キー入力を取得できるようにしたいのです。

よろしくお願いします。


CC BY-SA 4.0
2019-04-21T04:53:40.843
54355
2019-04-22T06:19:02.773
question
c++ windows-10
Windowsでのキー入力の仕組みについて


**コメントから回答化**

一連の流れを図示しているのが、以下の記事の Fig.9 ですね。  
**ただし2011年の記事なので、Windows10では何かしらの変更が入っている可能性はあります。**  
[Keyloggers: Implementing keyloggers in Windows. Part
Two](https://securelist.com/keyloggers-implementing-keyloggers-in-windows-
part-two/36358/)

[![Fig 9: Overview of how Windows processes keyboard
input](https://i.stack.imgur.com/e0RlV.png)](https://i.stack.imgur.com/e0RlV.png)  
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](https://docs.microsoft.com/en-us/windows/desktop/inputdev/raw-
input) / [About Raw Input](https://docs.microsoft.com/en-
us/windows/desktop/inputdev/about-raw-input)  
[Registration for Raw Input](https://docs.microsoft.com/en-
us/windows/desktop/inputdev/about-raw-input#registration-for-raw-input)

> デフォルトでは、アプリケーションは生の入力を受け取りません。デバイスから生の入力を受け取るには、アプリケーションはデバイスを登録する必要があります。

こちらに、複数のキーボードを接続して、特定のキーボードからの入力を無視する仕組みのデモと解説の記事があります。ソフト開発の参考になるでしょう。  
[Combining Raw Input and keyboard Hook to selectively block input from
multiple keyboards](https://www.codeproject.com/Articles/716591/Combining-Raw-
Input-and-keyboard-Hook-to-selective)

このデモでは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](https://www.codeproject.com/Articles/716591/Combining-Raw-Input-and-
keyboard-Hook-to-selective#Chap5-3)  
[Raw Input message is
missing](https://www.codeproject.com/Articles/716591/Combining-Raw-Input-and-
keyboard-Hook-to-selective#Chap5-4)  
[Yet more oddities](https://www.codeproject.com/Articles/716591/Combining-Raw-
Input-and-keyboard-Hook-to-selective#Chap6)


CC BY-SA 4.0
2019-04-22T06:09:39.863
54383
2019-04-22T06:19:02.773
2019-04-22T06:19:02.773
26370
26370
54355
answer