.NET TIPS

Windowsアプリケーションでキー処理が行われる順序は?

デジタルアドバンテージ
2004/12/17

 Windowsアプリケーションで、ユーザーがコントロールに対して入力したキーを処理するには、通常、キーイベント(KeyDownイベント、KeyPressイベント、KeyUpイベント)を処理するメソッドを追加して、そのメソッド内にキー処理内容を実装する(実際の実装方法は「TIPS:コントロールに対するキー入力をフォームで処理するには?」を参考にしてほしい)。このキー処理の工程を、ここでは「キーイベント・プロセス」と呼ぶことにする。

 しかし、ある特定のキー(以降、「特殊入力キー」)については、これらのキーイベントが発生しないことがある(つまり、前述のキーイベント・プロセスではキー処理が行えないことがあるのだ)。そのような場合に入力キーを独自に処理するには、キーイベントの発生前の処理工程である「プリプロセス」でキー処理を行う必要がある。この実装方法については「TIPS:Windowsアプリケーションで方向キーなどの特殊キーを処理するには?」で解説している。

 このように、Windowsアプリケーションでは、

  • 「プリプロセス」(前処理)
  • 「キーイベント・プロセス」(実処理)

という2つの処理工程が存在する。この2つの処理の流れをよく知っておくと、どの処理過程でキー処理を行うのが最も適切なのかを判断できる。本稿では、これらの工程における処理の流れについて簡単に説明する。なお以下の処理の流れは、Windowsフォーム(親フォーム)上にそのまま標準コントロール(子コントロール)が配置されているようなシンプルなフォーム・デザインの場合を想定している。複雑な階層で構成されたコントロールでは、このとおりに処理が行われるとは限らないのでご注意願いたい。

「プリプロセス」と「キーイベント・プロセス」

 プリプロセスとキーイベント・プロセスは、それぞれコントロール(System.Windows.Forms名前空間のControlクラス)の次のメソッドにより行われる。

(1)プリプロセス(前処理):コントロールのPreProcessMessageメソッドが呼び出される。

(2)キーイベント・プロセス(実処理):コントロールのProcessKeyMessageメソッドが呼び出される。

 Windowsアプリケーションでキー入力が行われると、アプリケーションのメッセージ・ループ処理(System.Windows.Forms名前空間のApplicationクラスのRunメソッド)から、最初に(1)PreProcessMessageメソッドが呼び出される。

 次にメッセージ・ループ処理では、入力キーに対応したWindowsメッセージ(WM_KEYDOWN、WM_SYSKEYDOWNなど。WM_SYSXXXというのは、[Alt]キーなどのシステム・キーやシステム文字を意味する)から別のWindowsメッセージ(WM_CHARなど)に変換してそれを生成する(TranslateMessage。生成されたWindowsメッセージはメッセージ・キューに格納され、次のメッセージ・ループで処理されることになる)。それから、(変換前の)Windowsメッセージがウィンドウ・プロシージャに送出される(DispatchMessage)。送出されたWindowsメッセージはコントロールのウィンドウ・プロシージャ(WndProcメソッド)が受信し処理する。これによりコントロールの(2)ProcessKeyMessageメソッドが呼び出されることになる。

 ちなみに、ProcessKeyMessageメソッドはアクセス修飾子がinternalのため、自作アプリケーション側のコントロールやフォーム(System.Windows.Forms名前空間のFormクラス)の派生クラスではオーバーライドすることができない。

(1)PreProcessMessageメソッド

 PreProcessMessageメソッドでは、キーが押されたことを意味するWM_KEYDOWNとWM_SYSKEYDOWNというWindowsメッセージ、さらに文字が入力されたことを意味するWM_CHARとWM_SYSCHARというWindowsメッセージに対して以下のような処理が行われる。

 WM_KEYDOWNメッセージとWM_SYSKEYDOWNメッセージに対するプリプロセスでは、次の順序で処理が行われる。

  1. コントロールのProcessCmdKeyメソッドの呼び出し:
     さらに、このProcessCmdKeyメソッドが親フォームのProcessCmdKeyメソッドを呼び出す。コントロールもしくはフォームのProcessCmdKeyメソッドで何らかのキー処理が行われると(つまりそれらのメソッドの戻り値がTrueの場合)、そこでキー処理は終了となる。

  2. コントロールのIsInputKeyメソッドの呼び出し:
     特殊入力キーかチェックする。通常入力キーならプリプロセスは終了する(プリプロセスが終了するだけで、次のキーイベント・プロセスは引き続き行われる)。

  3. コントロールのProcessDialogKeyメソッドの呼び出し:
     さらに、このProcessDialogKeyメソッドが親フォームのProcessDialogKeyメソッドを呼び出す。コントロールもしくはフォームのProcessDialogKeyメソッドで何らかのキー処理が行われると(つまり戻り値がTrueだと)、そこでキー処理は終了となる。

 また、WM_CHARメッセージとWM_SYSCHARメッセージに対するプリプロセスでは、次の順序で処理が行われる。

  1. コントロールのIsInputCharメソッドの呼び出し(WM_CHARの場合のみ):
     特殊入力文字かチェックする。通常入力文字ならプリプロセスは終了する(プリプロセスが終了するだけで、次のキーイベント・プロセスは続行される)。

  2. コントロールのProcessDialogCharメソッドの呼び出し:
     さらに、このProcessDialogCharメソッドが親フォームのProcessDialogCharメソッドを呼び出す。コントロールもしくはフォームのProcessDialogCharメソッドで何らかのキー処理が行われると(つまり戻り値がTrueの場合)、そこでキー処理は終了となる。

 コントロールの特殊入力キーは状況によって変化する場合があるので注意してほしい。例えばTextBoxコントロールでは、MultilineプロパティとacceptsReturnプロパティがTrueの場合にのみ[Enter]キーが特殊入力キーとなる。

(2)ProcessKeyMessageメソッド

 ProcessKeyMessageメソッドでは、WM_KEYDOWN、WM_SYSKEYDOWN、WM_CHARというWindowsメッセージのほかに(MSDNの記述によるとWM_SYSCHARは含まれていないようだ)、キーが押されたことを意味するWM_KEYUP、WM_SYSKEYUPというWindowsメッセージに対して、次の順序で処理が行われる。

  1. 親フォームのProcessKeyPreviewメソッドの呼び出し(親がある場合のみ):
     さらに、そのフォームのKeyPreviewプロパティがTrueの場合には、このProcessKeyPreviewメソッドがフォームのProcessKeyEventArgsメソッドを呼び出す(これにより、フォームのOnKeyPressメソッド、OnKeyDownメソッド、OnKeyUpメソッドのいずれかが呼び出され、さらにそれらのメソッドが通常のKeyDown、KeyPress、KeyUpといったキーイベントを生成する。そのため、コントロールでのキー入力をフォームで一括処理することが可能となる)。フォームのProcessKeyPreviewメソッドやProcessKeyEventArgsメソッドで何らかのキー処理が行われると(つまり戻り値がTrueだと)、そこでキー処理は終了となる。なお、コントロールのProcessKeyPreviewメソッドは呼び出されないので注意すること。

  2. コントロールのProcessKeyEventArgsメソッドの呼び出し:
     これにより、コントロールのOnKeyPressメソッド、OnKeyDownメソッド、OnKeyUpメソッドのいずれかが呼び出され、さらにそれらのメソッドから通常のキーイベント(KeyDownイベント、KeyPressイベント、KeyUpイベント)が生成される。

 以上の処理工程を見ると、最初のキー処理はコントロールのProcessCmdKeyメソッドで行われ、最後のキー処理はキーイベント・ハンドラで行われることが分かる。

 よってキー処理の実装は、基本的にキーイベント・ハンドラで行い、プリプロセスで処理される入力キーについてはProcessDialogKeyメソッドとProcessDialogCharメソッドをオーバーライドして処理することをお勧めする。フォームやコントロール側で完全にキー処理を制御するには(つまり、デフォルト処理を一切行わない場合)、プリプロセスのProcessCmdKeyメソッドをオーバーライドするとよいだろう。ProcessKeyPreviewメソッドをオーバーライドすることはほとんどない。End of Article

カテゴリ:Windowsフォーム 処理対象:キーボード
使用ライブラリ:Formクラス(System.Windows.Forms名前空間)
使用ライブラリ:Controlクラス(System.Windows.Forms名前空間)
使用ライブラリ:Applicationクラス(System.Windows.Forms名前空間)
関連TIPS:コントロールに対するキー入力をフォームで処理するには?
関連TIPS:
Windowsアプリケーションで方向キーなどの特殊キーを処理するには?
 
この記事と関連性の高い別の.NET TIPS
Windowsアプリケーションで方向キーなどの特殊キーを処理するには?
コントロールに対するキー入力をフォームで処理するには?
Windowsアプリケーションで[Enter]キーによるフォーカス移動を行うには?
時間がかかる処理での「応答なし」を回避するには?
WindowsフォームでWindowsメッセージを直接処理するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間