DOBON.NET DOBON.NETプログラミング掲示板過去ログ

C# MaskedTextBoxにて、エンター移動時にValidatingでキャンセルするとマスクがおかしくなる

環境/言語:[VS2008 C# WinXP]
分類:[.NET]

お世話になります。

WindowsXP、VisualStudio2008 C#を使用しています。

formにMaskedTextBoxコントロールを2つ貼りつけた状態で、下記ソースを実行します。

---------------------------------------------------------------------------------------
public partial class Form1 : Form {
 public Form1() {
   InitializeComponent();

   maskedTextBox1.Mask = "0000/00/00";
   maskedTextBox2.Mask = "0000/00/00";

   maskedTextBox1.KeyDown += new KeyEventHandler(maskedTextBox1_KeyDown);

   maskedTextBox1.Validating += new CancelEventHandler(maskedTextBox1_Validating);
 }

 void maskedTextBox1_Validating(object sender, CancelEventArgs e) {
   MessageBox.Show("CHECK!");

   e.Cancel = true;
 }

 void maskedTextBox1_KeyDown(object sender, KeyEventArgs e) {
   if (e.KeyCode == Keys.Enter) {
    SelectNextControl(maskedTextBox1, true, true, true, false);

    e.Handled = true;
   }
 }

}
---------------------------------------------------------------------------------------

すると、1つめのコントロールでエンターを押して「CHECK!」が表示された後に、
キーを押すとマスク表示がおかしくなります。
(例:1キーを押すと、1____/__/__ 本当は 1___/__/__)
この状態で更にキーを押すと1回目に入力した文字が消えてしまいます。
(例:2キーを押すと、_2__/__/__ 本当は 12__/__/__)

修正方法・回避方法をご存じの方がいれば、教えて頂けないでしょうか。


試行錯誤した結果、下記事項は判明しています。
・MessageBox.Showしなければ問題なし。
・TABで移動すると問題なし。
 SelectNextControlをSendKeys.SendWait("{TAB}")はダメ。
・全選択してDELキーを押した後だと、問題なし。
 SelectAll後にSendKeys.SendWait("{DEL}")はダメ。
・VisualStudio2010でも同様。
■No31660に返信(hideさんの記事)

試していませんが状況から
Enter判断処理でSelectNextControlする前に
Validatingと同じチェックを行ってNGなら移動しなければ
よいのでは?
■No31662に返信(shuさんの記事)

下記のようにしてみましたが、同様の現象が発生します。

---------------------------------------------------------------------------
 public partial class Form1 : Form {
  public Form1() {
   InitializeComponent();
   maskedTextBox1.Mask = "0000/00/00";
   maskedTextBox1.KeyDown += new KeyEventHandler(maskedTextBox1_KeyDown);
  }

  void maskedTextBox1_KeyDown(object sender, KeyEventArgs e) {
   if (e.KeyCode == Keys.Enter) {
    MessageBox.Show("CHECK!");
    e.Handled = true;
    return;
   }
  }
 }
---------------------------------------------------------------------------
■No31666に返信(hideさんの記事)

ダイアログ表示が影響しているようですね。
KeyUpイベントで処理するようにした方がよさそうです。
まあ、コントロールが KeyDown イベントが実行されているのに、割り込みで同じコントロール Validating イベントなんて厄介なイベントが挟んでこれば、ややこしいことになりますね。

# Windows メッセージングをある程度知っている人なら、ちょっと怖くてできないことです。
# Handled = true でイベント送信が完全にキャンセルされるのは、これとはまた別の問題。

正しい方法としては、フォーカスを移動させるのをキーイベントが完全終了した後か、現在入力中のクライアント領域より外側のウィンドウ ハンドルを持つコントロール側で行うかでしょうね。
後者の場合は、KeyPreview のことも考慮しなくてはならないですが。

# 自分の場合は、拡張プロバイダでメッセージ フィルタを使って実現することが多いです。

DOBON.NET | プログラミング道 | プログラミング掲示板