MaskedTextBox コントロールでキーボード入力を処理する場合の注意点について
こんにちは、Visual Studio サポート チームです。
今回は、MaskedTextBox コントロール (以下、MaskedTextBox) でキーボード入力を処理する場合の注意点についてご紹介します。
MaskedTextBox は、マスク パターンを指定して、入力制限を行うことができる TextBox です。
郵便番号、日時、電話番号などの標準的なマスクは、あらかじめ用意されており、マスクを設定しておくと、その形式に合わない入力を拒否できます。
入力が不可欠な文字スペース、英数字だけ受け付ける、など様々な条件を組み合わせて、マスクをきめ細かく作成することもできます。
また、パスワードなどの入力を受け付ける場合、画面に入力された文字を表示せず、代替文字を表示するような設定もできる非常に便利なコントロールです。
この MaskedTextBox の内部では、Enter キーの入力に対して他のキーとは異なる特別な処理が実装されていますので、ご注意いただく必要があります。
MaskedTextBox コントロールでの特別な処理について
まず、キーが押された時に発生するキー イベントの順番は、次のようになります。
KeyDown → KeyPress → KeyUp
MaskedTextBox では、 KeyDown イベントにおいて、Enter キーが検知されると、コントロール内部で特殊なフラグが設定されます。
このフラグは、KeyPress イベント内で再設定されます。
このように、MaskedTextBox が Enter キーを他のキーとは異なる特別なキーとして処理しています。
しかし、他のコントロールによるイベント処理の影響で、KeyPress イベントがキャンセルされると、上記フラグが設定されたままとなるため、次の文字入力以降で不整合が発生します。
Windows フォームでは、キーボード メッセージがコントロールに到達する前に、それらをフォーム レベルで処理できますが、この Enter キーに対する特別な処理のために、問題が発生することがあります。
注意が必要なケースについて、具体例と合わせてご説明します。
注意が必要な例
Form 上に、MaskedTextBox を配置し、Enter キーが押された際に、次のコントロールにフォーカスを移動する処理を実装します。
ここでは、Form の KeyPress イベント ハンドラ内で、明示的に TAB キーを発生させ、イベント処理をキャンセルします。
たとえば、以下のソース コードを実装します。
Private Sub Form_KeyPress(ByVal eventSender As System.Object, ByVal eventArgs As System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress
Dim KeyAscii As Short = Asc(eventArgs.KeyChar)
‘ Enter キーが押下された場合
If KeyAscii = System.Windows.Forms.Keys.Return Then
System.Windows.Forms.SendKeys.Send("{TAB}")
‘ イベントキャンセル
eventArgs.Handled = True
End If
End Sub
上記のように、Enter キーを押下した場合に、Form の KeyPress イベントでイベントがキャンセルされると、MaskedTextBox の KeyPress イベントが発生しない状態となります。
このため、前項の MaskedTextBox 内の特殊なフラグが設定されたままとなり、次の文字入力以降で、不整合が発生します。
対処方法
イベントのキャンセルの影響で MaskedTextBox の KeyPress イベントが発生しなくなる現象については、以下の 2 通りの対処方法が考えられます。
- フラグが立たないように、MaskedTextBox の KeyDown が発生しないようにする
→ Form の KeyDown で、 KeyPressEventArgs.Handled = True を行う。 - MaskedTextBox の KeyDown イベントと KeyPress イベントの両方が発生するようにする
→ Form の KeyPress で、KeyPressEventArgs.Handled = True を行わない。
最後に
以下の技術資料にもあるように、イベントをキャンセルする処理はサポートされており、一般的にもよく利用されるものです。
方法 : キーボード入力をフォーム レベルで処理する
<https://msdn.microsoft.com/ja-jp/library/ms171538.aspx>
ただし、今回の MaskedTextBox のように、独自にイベント処理をしているコントロールもあるため、イベントのキャンセル処理を利用される場合は、十分な検証を行ってください。