none
TextBoxでEnterキーが押された時に、タブオーダーが次のコントロールにフォーカスを移動させたとき RRS feed

  • 質問

  • DOBON.NETさんのサンプル
    http://dobon.net/vb/dotnet/control/enterliketab.html#section1
    をお借りして試してみました。

    9つのTextBoxが配置されているのですが、Enterキーを押すとなぜか、
       1→3→5→7→9→2→4→6→8→1・・・
    と、移動します。

    正しい順序で移動させたいのですが、どのようにしたらよろしいのでしょうか。お教え願います。




    zen73
    2009年8月14日 5:37

回答

  • DOBON.NET さんのサンプルコードでは、テキストボックスではなく、フォームの KeyUp で処理をしています。
    フォームにもテキストボックスにも KeyUp イベントを実装しているということはないですか?
    また、KeyUp でタブキーに置き換えたときに、e.Handled に true をセットして、それ以降のイベントの伝播を正しく止めていますか?
    手元で試したところ、上記の条件を満たすと現象が再現できました。他にも同様の現象を発生させる方法はいくらでもあるとは思いますが。
    • 回答としてマーク zen73 2009年8月14日 20:54
    2009年8月14日 8:45
  • this.Load += new System.EventHandler(this.Form1_Load);
    this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
    最初に指摘しましたようにLoadイベント中でもKeyUpイベントの登録が実行されているので、このままだと2回イベントの登録をしています。
    • 回答としてマーク zen73 2009年8月14日 20:54
    2009年8月14日 15:05

すべての返信

  • それは2回KeyUpイベントが実行されているからだと思われます。

    サンプルのソースではLoadイベント中でKeyUpイベントの登録を行っていますが、別のところでもイベントの登録をしていませんか?
    デザイナでフォームを選択したときのプロパティから見られるイベントでKeyUpイベントが登録されていませんか?
    2009年8月14日 5:59
  • gekkaさん、ありがとうございます。
    それは2回KeyUpイベントが実行されているからだと思われます。

    サンプルのソースではLoadイベント中でKeyUpイベントの登録を行っていますが、別のところでもイベントの登録をしていませんか?
    デザイナでフォームを選択したときのプロパティから見られるイベントでKeyUpイベントが登録されていませんか?

    実際の場面では、KeyPressイベントなどをあちこちに設定(KeyUPイベントの設定はない)しております。


    それでまっさらのフォームに、Textboxを配置し、KeyUPイベント以外になんらのイベントの登録なしにDOBON.NETさんのコードを実行してみたところまったく同じ結果となりました。

    ということで、実際の場面ではKeyPressイベントを利用して、
          private void noTextBox_KeyPress(object sender, KeyPressEventArgs e)
              {
                    if((e.KeyChar <'0' || e.KeyChar >'9') && e.KeyChar != '\b')
                    {
                          e.Handled =true;
                    }
                    if (e.KeyChar == (char)13)
                    {
                          SendKeys.Send("{Tab}");
                    }
          }
    などとしてこの不具合を切り抜けようとしてはいますが、どうして上でいう「まっさらなフォーム」でKeyUpイベントが2回実行されるのでしょうか。

     


    zen73
    2009年8月14日 6:53
  • 私がテストしてみた限りではきちんと遷移します。
    テスト環境 XP SP3/VS2008SP1/ターゲットFramework2.0

    以下のソースでも発生します?
    #Designer.csを含めたコード見ないとまっさらかどうか判断しかねます。

    using System;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public class Form1 : Form
        {
            public Form1()
                : base()
            {
                this.KeyPreview = true;
                this.KeyUp += new KeyEventHandler(Form1_KeyUp);
    
                for (int y = 0; y < 3; ++y)
                {
                    for (int x = 0; x < 3; ++x)
                    {
                        int tab;
                        tab = x * 3 + y;
    
                        TextBox box;
                        box = new TextBox();
                        box.Text = tab.ToString();
                        box.TabIndex = tab;
                        box.TabStop = true;
                        box.Width = 30;
                        box.Top = y * 30;
                        box.Left = x * 40;
                        this.Controls.Add(box);
                    }
                }
            }
    
            private void Form1_KeyUp(object sender , KeyEventArgs e)
            {
                //Enterキーが押されているか確認
                if (e.KeyCode == Keys.Enter)
                {
                    CheckFocus();
    
                    this.ProcessTabKey(!e.Shift);
    
                    CheckFocus();
                    Console.WriteLine();
                    
                    e.Handled = true;
                }
            }
    
            private void CheckFocus()
            {
                foreach (Control ctl in this.Controls)
                {
    
                    if (ctl.Focused)
                    {
                        Console.WriteLine(ctl.ToString());
                    }
                }
            }
        }
    }
    
    2009年8月14日 7:43
  • DOBON.NET さんのサンプルコードでは、テキストボックスではなく、フォームの KeyUp で処理をしています。
    フォームにもテキストボックスにも KeyUp イベントを実装しているということはないですか?
    また、KeyUp でタブキーに置き換えたときに、e.Handled に true をセットして、それ以降のイベントの伝播を正しく止めていますか?
    手元で試したところ、上記の条件を満たすと現象が再現できました。他にも同様の現象を発生させる方法はいくらでもあるとは思いますが。
    2009年8月14日 8:44
  • DOBON.NET さんのサンプルコードでは、テキストボックスではなく、フォームの KeyUp で処理をしています。
    フォームにもテキストボックスにも KeyUp イベントを実装しているということはないですか?
    また、KeyUp でタブキーに置き換えたときに、e.Handled に true をセットして、それ以降のイベントの伝播を正しく止めていますか?
    手元で試したところ、上記の条件を満たすと現象が再現できました。他にも同様の現象を発生させる方法はいくらでもあるとは思いますが。
    • 回答としてマーク zen73 2009年8月14日 20:54
    2009年8月14日 8:45
  • gekkaさん、何度もありがとうございます。

    私がテストしてみた限りではきちんと遷移します。
    テスト環境 XP SP3/VS2008SP1/ターゲットFramework2.0
    私の環境も同じです。
    以下のソースでも発生します?
    一つ飛びということはなく、きちんと動作しました。
    #Designer.csを含めたコード見ないとまっさらかどうか判断しかねます。
    gekkaさんは、コントロールを動的に配置しておられますが、私の場合はツールボックスからドラッグ&ドロップしているだけですので、断定はできませんが、まっさらのはずだと・・・。


    totojoさん、ありがとうございます。
    フォームにもテキストボックスにも KeyUp イベントを実装しているということはないですか?
    Designer.csを見た限りでは、テキストボックスにも KeyUp イベントを実装しているということはないですね。
           // textBox1
                // 
                this.textBox1.Location = new System.Drawing.Point(44, 12);
                this.textBox1.Name = "textBox1";
                this.textBox1.Size = new System.Drawing.Size(100, 19);
                this.textBox1.TabIndex = 0;
    また、KeyUp でタブキーに置き換えたときに、e.Handled に true をセットして、それ以降のイベントの伝播を正しく止めていますか?
    どうせねばならないのか、正しく理解できていません。
    namespace WindowsFormsApplication3
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                //キーイベントをフォームで受け取る
                this.KeyPreview = true;
                //KeyUpイベントハンドラを追加
                this.KeyUp += new KeyEventHandler(Form1_KeyUp);
            }
    
            private void Form1_KeyUp(object sender, KeyEventArgs e)
            {
                //Enterキーが押されているか確認
                if (e.KeyCode == Keys.Enter)
                {
                    //あたかもTabキーが押されたかのようにする
                    //Shiftが押されている時は前のコントロールのフォーカスを移動
                    this.ProcessTabKey(!e.Shift);
    
                    e.Handled = true;
                }
            }
        }
    }


    zen73
    2009年8月14日 11:02
  • gekkaさんは、コントロールを動的に配置しておられますが、私の場合はツールボックスからドラッグ&ドロップしているだけですので、

    動的に配置していると感じられているようですが、このコードはInitializeComponent()で実行されるコードとなんら変わりはありません。
    デザイナで余計なコードが付加しておかしくなっていないかを確認するために最小限のコードになるように書いたのです。

    で、断定はできませんが、まっさらのはずだと・・・。
    断定できないのでしたら、きちんと確認しましょう。
    きちんとなっているはずだという先入観でいつまでもバグが見つからないのはよくあることです。

    挙げたコードで問題なく遷移するということはzen73さんが正しいはずだと思い込んでいるごコードに問題があるということです。
    ご自身で確認できないのでしたらコードをDesigner.csを全て見せていただかないと、どこがおかしいのか誰にもわかりません。
    totojoさんもおっしゃっているように、このような動作をするコードはいくらでもあるのですから。
    2009年8月14日 14:00
  • 挙げたコードで問題なく遷移するということはzen73さんが正しいはずだと思い込んでいるごコードに問題があるということです。
    ご自身で確認できないのでしたらコードをDesigner.csを全て見せていただかないと、どこがおかしいのか誰にもわかりません。
    totojoさんもおっしゃっているように、このような動作をするコードはいくらでもあるのですから。
    このような事情があるとは理解せず、しかも動作そのものは代替コードで解決済みなのに質問をここまで引っ張り、お手数をおかけしておりますことをお詫びいたします。

    ----------------------Designer.cs-------------------------------------------------------------------------------------------------------------------------------------
    namespace WindowsFormsApplication3
    {
        partial class Form1
        {
            /// <summary>
            /// 必要なデザイナ変数です。
            /// </summary>
            private System.ComponentModel.IContainer components = null;
    
            /// <summary>
            /// 使用中のリソースをすべてクリーンアップします。
            /// </summary>
            /// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
    
            #region Windows フォーム デザイナで生成されたコード
    
            /// <summary>
            /// デザイナ サポートに必要なメソッドです。このメソッドの内容を
            /// コード エディタで変更しないでください。
            /// </summary>
            private void InitializeComponent()
            {
                this.textBox1 = new System.Windows.Forms.TextBox();
                this.textBox2 = new System.Windows.Forms.TextBox();
                this.textBox3 = new System.Windows.Forms.TextBox();
                this.textBox4 = new System.Windows.Forms.TextBox();
                this.textBox5 = new System.Windows.Forms.TextBox();
                this.textBox6 = new System.Windows.Forms.TextBox();
                this.textBox7 = new System.Windows.Forms.TextBox();
                this.textBox8 = new System.Windows.Forms.TextBox();
                this.textBox9 = new System.Windows.Forms.TextBox();
                this.SuspendLayout();
                // 
                // textBox1
                // 
                this.textBox1.Location = new System.Drawing.Point(44, 12);
                this.textBox1.Name = "textBox1";
                this.textBox1.Size = new System.Drawing.Size(100, 19);
                this.textBox1.TabIndex = 0;
                // 
                // textBox2
                // 
                this.textBox2.Location = new System.Drawing.Point(44, 50);
                this.textBox2.Name = "textBox2";
                this.textBox2.Size = new System.Drawing.Size(100, 19);
                this.textBox2.TabIndex = 1;
                // 
                // textBox3
                // 
                this.textBox3.Location = new System.Drawing.Point(44, 91);
                this.textBox3.Name = "textBox3";
                this.textBox3.Size = new System.Drawing.Size(100, 19);
                this.textBox3.TabIndex = 2;
                // 
                // textBox4
                // 
                this.textBox4.Location = new System.Drawing.Point(44, 133);
                this.textBox4.Name = "textBox4";
                this.textBox4.Size = new System.Drawing.Size(100, 19);
                this.textBox4.TabIndex = 3;
                // 
                // textBox5
                // 
                this.textBox5.Location = new System.Drawing.Point(44, 171);
                this.textBox5.Name = "textBox5";
                this.textBox5.Size = new System.Drawing.Size(100, 19);
                this.textBox5.TabIndex = 4;
                // 
                // textBox6
                // 
                this.textBox6.Location = new System.Drawing.Point(44, 213);
                this.textBox6.Name = "textBox6";
                this.textBox6.Size = new System.Drawing.Size(100, 19);
                this.textBox6.TabIndex = 5;
                // 
                // textBox7
                // 
                this.textBox7.Location = new System.Drawing.Point(44, 253);
                this.textBox7.Name = "textBox7";
                this.textBox7.Size = new System.Drawing.Size(100, 19);
                this.textBox7.TabIndex = 6;
                // 
                // textBox8
                // 
                this.textBox8.Location = new System.Drawing.Point(44, 293);
                this.textBox8.Name = "textBox8";
                this.textBox8.Size = new System.Drawing.Size(100, 19);
                this.textBox8.TabIndex = 7;
                // 
                // textBox9
                // 
                this.textBox9.Location = new System.Drawing.Point(44, 344);
                this.textBox9.Name = "textBox9";
                this.textBox9.Size = new System.Drawing.Size(100, 19);
                this.textBox9.TabIndex = 8;
                // 
                // Form1
                // 
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(589, 521);
                this.Controls.Add(this.textBox9);
                this.Controls.Add(this.textBox8);
                this.Controls.Add(this.textBox7);
                this.Controls.Add(this.textBox6);
                this.Controls.Add(this.textBox5);
                this.Controls.Add(this.textBox4);
                this.Controls.Add(this.textBox3);
                this.Controls.Add(this.textBox2);
                this.Controls.Add(this.textBox1);
                this.Name = "Form1";
                this.Text = "Form1";
                this.Load += new System.EventHandler(this.Form1_Load);
                this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
                this.ResumeLayout(false);
                this.PerformLayout();
    
            }
    
            #endregion
    
            private System.Windows.Forms.TextBox textBox1;
            private System.Windows.Forms.TextBox textBox2;
            private System.Windows.Forms.TextBox textBox3;
            private System.Windows.Forms.TextBox textBox4;
            private System.Windows.Forms.TextBox textBox5;
            private System.Windows.Forms.TextBox textBox6;
            private System.Windows.Forms.TextBox textBox7;
            private System.Windows.Forms.TextBox textBox8;
            private System.Windows.Forms.TextBox textBox9;
        }
    }
    
    

    zen73
    2009年8月14日 14:59
  • this.Load += new System.EventHandler(this.Form1_Load);
    this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
    最初に指摘しましたようにLoadイベント中でもKeyUpイベントの登録が実行されているので、このままだと2回イベントの登録をしています。
    • 回答としてマーク zen73 2009年8月14日 20:54
    2009年8月14日 15:05
  • totojoさん、gekkaさん、ありがとうございました。

    this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
    が、自動的に登録されたイベントとは、まったく思いもしませんでした。
    いい経験でした。


    zen73
    2009年8月14日 21:01