none
TreeViewとContextMenu.SourceControlの不具合 RRS feed

  • 質問

  • 開発環境はVS2003 SP1 + .NET Framework 1.1(SP1) と他に .NET Framework 2.0 SDK

    OSはWindowsXP Professional SP2

     

    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;

    namespace WindowsApplication_Test_2
    {
     /// <summary>
     /// Form1 の概要の説明です。
     /// </summary>
     public class Form1 : System.Windows.Forms.Form
     {
      private System.Windows.Forms.TreeView treeView1;
      private System.Windows.Forms.TextBox textBox1;
      private System.Windows.Forms.RichTextBox richTextBox1;
      private System.Windows.Forms.RichTextBox richTextBox2;
      private System.Windows.Forms.ContextMenu contextMenu1;
      private System.Windows.Forms.MenuItem menuItem1;
      /// <summary>
      /// 必要なデザイナ変数です。
      /// </summary>
      private System.ComponentModel.Container components = null;

      public Form1()
      {
       //
       // Windows フォーム デザイナ サポートに必要です。
       //
       InitializeComponent();

       //
       // TODO: InitializeComponent 呼び出しの後に、コンストラクタ コードを追加してください。
       //
      }

      /// <summary>
      /// 使用されているリソースに後処理を実行します。
      /// </summary>
      protected override void Dispose( bool disposing )
      {
       if( disposing )
       {
        if (components != null)
        {
         components.Dispose();
        }
       }
       base.Dispose( disposing );
      }

      #region Windows フォーム デザイナで生成されたコード
      /// <summary>
      /// デザイナ サポートに必要なメソッドです。このメソッドの内容を
      /// コード エディタで変更しないでください。
      /// </summary>
      private void InitializeComponent()
      {
       this.treeView1 = new System.Windows.Forms.TreeView();
       this.textBox1 = new System.Windows.Forms.TextBox();
       this.richTextBox1 = new System.Windows.Forms.RichTextBox();
       this.richTextBox2 = new System.Windows.Forms.RichTextBox();
       this.contextMenu1 = new System.Windows.Forms.ContextMenu();
       this.menuItem1 = new System.Windows.Forms.MenuItem();
       this.SuspendLayout();
       //
       // treeView1
       //
       this.treeView1.ImageIndex = -1;
       this.treeView1.Location = new System.Drawing.Point(32, 24);
       this.treeView1.Name = "treeView1";
       this.treeView1.SelectedImageIndex = -1;
       this.treeView1.TabIndex = 0;
       this.treeView1.DoubleClick += new System.EventHandler(this.treeView1_DoubleClick);
       this.treeView1.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterSelect);
       //
       // textBox1
       //
       this.textBox1.ContextMenu = this.contextMenu1;
       this.textBox1.Location = new System.Drawing.Point(40, 160);
       this.textBox1.Name = "textBox1";
       this.textBox1.TabIndex = 1;
       this.textBox1.Text = "textBox1";
       //
       // richTextBox1
       //
       this.richTextBox1.ContextMenu = this.contextMenu1;
       this.richTextBox1.Location = new System.Drawing.Point(168, 24);
       this.richTextBox1.Name = "richTextBox1";
       this.richTextBox1.TabIndex = 2;
       this.richTextBox1.Text = "richTextBox1";
       //
       // richTextBox2
       //
       this.richTextBox2.ContextMenu = this.contextMenu1;
       this.richTextBox2.Location = new System.Drawing.Point(168, 136);
       this.richTextBox2.Name = "richTextBox2";
       this.richTextBox2.TabIndex = 3;
       this.richTextBox2.Text = "richTextBox2";
       //
       // contextMenu1
       //
       this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
                           this.menuItem1});
       this.contextMenu1.Popup += new System.EventHandler(this.contextMenu1_Popup);
       //
       // menuItem1
       //
       this.menuItem1.Index = 0;
       this.menuItem1.Text = "テスト";
       //
       // Form1
       //
       this.AutoScaleBaseSize = new System.Drawing.Size(5, 12);
       this.ClientSize = new System.Drawing.Size(544, 342);
       this.Controls.Add(this.richTextBox2);
       this.Controls.Add(this.richTextBox1);
       this.Controls.Add(this.textBox1);
       this.Controls.Add(this.treeView1);
       this.Name = "Form1";
       this.Text = "Form1";
       this.Load += new System.EventHandler(this.Form1_Load);
       this.ResumeLayout(false);

      }
      #endregion

      /// <summary>
      /// アプリケーションのメイン エントリ ポイントです。
      /// </summary>
      [STAThread]
      static void Main()
      {
       Application.Run(new Form1());
      }

      private void Form1_Load(object sender, System.EventArgs e)
      {
       TreeNode temptn = new TreeNode("ee1");
       TreeNode temptn2 = new TreeNode("ee2");
       TreeNode newnode = new TreeNode();
       temptn2 = temptn2.Nodes.Add("e2");
       temptn2.Nodes.Add("e21");
       temptn2.Nodes.Add("e22");
       temptn2.Nodes.Add("e23");
       temptn2 = temptn2.Parent;

       temptn.Nodes.Add("e1");
       temptn.Nodes.Add(temptn2);
       treeView1.Nodes.Add(temptn2);

      }

      private int[] fg = new int[] {1,2,3};

      private void treeView1_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
      {
       textBox1.Text = fg[treeView1.SelectedNode.Index].ToString();
      }

      private void treeView1_DoubleClick(object sender, System.EventArgs e)
      {
       treeView1.SelectedNode.Remove();
      }

      private void contextMenu1_Popup(object sender, System.EventArgs e)
      {
       Control control = contextMenu1.SourceControl;
      }
     }
    }

     このコードを実行するとtreeView1にノードが表示されます。e2 ノードを選択しダブルクリックしてこのノードを削除すると SelectedNode.Index = 2 となり存在しないノードの値を返します。

     RichTextBox1とRichTextBox2のContextMenuにcontextMenu1を設定しPopupさせるとcontextMenu1.SourceControlプロパティがRichTextBox1またはRichTextBox2ではなく未定義の値を返します。RichTextBoxが一つでも同様の現象が発生します。他のコントロールは正しいControlを返します。他の方の環境でも発生しますか。


    ---------------------------------------------------------------------
     テストありがとうございます。

    訂正します。e2ノードではなくe22ノードの間違いでした。失礼しました。

    補足いたします。私の環境ではe22ノードを削除するとe23ノードが繰り上がりe23ノードを示します。 treeView1.SelectedNode.Remove();
     のあとに

      private void treeView1_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
      {
       textBox1.Text = fg[treeView1.SelectedNode.Index].ToString();
      }

    が実行され

    SelectedNode.Index = 0 はe21ノード
    SelectedNode.Index = 1 はe23ノード

    でSelectedNode.Index は 2以上の値をとらないはずなのですがデバッグで追跡すると SelectedNode.Index = 2 となり fg[2]=3 の値をtextBox1に表示します。

    private void treeView1_DoubleClick(object sender, System.EventArgs e)
      {
       treeView1.SelectedNode.Remove();

    の後に  textBox1.Text = fg[treeView1.SelectedNode.Index].ToString(); を加えると SelectedNode.Index = 1 を返し fg[1]=2 の値を textBox1に正しく表示します。


     ContextMenu.SourceControl の不具合はフォーカスのあるRichTextBoxによってContextMenuのMenuItemの一部を表示しないようにコードを追加した際に発見しました。

     

    2007年2月7日 7:33

回答

  • とりあえず、提示されたコードで試してみました。環境は、せと際開発者さんと同じです。

     せと際開発者 さんからの引用

    このコードを実行するとtreeView1にノードが表示されます。e2 ノードを選択しダブルクリックしてこのノードを削除すると SelectedNode.Index = 2 となり存在しないノードの値を返します。

    再現しませんでした。「エラー : 'treeView1.SelectedNode.Index' は存在しません。」と表示され、この動作は正しいように思えます。
    私の削除の手順が違うのかもしれません。

     せと際開発者 さんからの引用

    RichTextBox1とRichTextBox2のContextMenuにcontextMenu1を設定しPopupイベントが発生するとcontextMenu1.SourceControlプロパティがRichTextBox1またはRichTextBox2ではなく未定義の値を返します。RichTextBoxが一つでも同様の現象が発生します。他のコントロールは正しいControlを返します。

    再現しました。

    取り急ぎ、テスト結果です。

    2007年2月7日 7:54
    モデレータ
  •  せと際開発者 さんからの引用

    SelectedNode.Index = 0 はe21ノード
    SelectedNode.Index = 1 はe23ノード
    でSelectedNode.Index は 2以上の値をとらないはずなのですがデバッグで追跡すると SelectedNode.Index = 2 となり fg[2]=3 の値をtextBox1に表示します。

    最終的には、
    SelectedNode.Index = 0 はe21ノード
    SelectedNode.Index = 1 はe23ノード
    になっています。

    e22ノードをダブルクリックして削除した後にe23がセレクトされ、AfterSelectイベントが発生しますが、この段階ではまだe23のSelectedNode.Indexは2のままです。
    その後、最終的に全てのTreeViewの内部的な処理が終わった後、正しくe23ノードのSelectedNode.Indexは1になります。
    要は、イベントの発生するタイミングの問題のようです。

     せと際開発者 さんからの引用

     ContextMenu.SourceControl の不具合はフォーカスのあるRichTextBoxによってContextMenuのMenuItemの一部を表示しないようにコードを追加した際に発見しました。

    調べてみました。これはどうやら既知の問題のようです。回避策としては、

    1.RichTextBoxのMouseDownイベントにて、RichTextBoxがクリックされたことを変数にしまって置き、それをPopUpメソッド内で参照して判断する。

    もしくは、

    2.以下のコードのように、MouseDownイベントにて、ContextMenuを呼び出す。

    private void richTextBox3_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
    {
     if (e.Button == MouseButtons.Right)
      contextMenu1.Show(richTextBox3, new Point(e.X, e.Y));
    }

    とするようです。

    2007年2月8日 2:23
    モデレータ

すべての返信

  • とりあえず、提示されたコードで試してみました。環境は、せと際開発者さんと同じです。

     せと際開発者 さんからの引用

    このコードを実行するとtreeView1にノードが表示されます。e2 ノードを選択しダブルクリックしてこのノードを削除すると SelectedNode.Index = 2 となり存在しないノードの値を返します。

    再現しませんでした。「エラー : 'treeView1.SelectedNode.Index' は存在しません。」と表示され、この動作は正しいように思えます。
    私の削除の手順が違うのかもしれません。

     せと際開発者 さんからの引用

    RichTextBox1とRichTextBox2のContextMenuにcontextMenu1を設定しPopupイベントが発生するとcontextMenu1.SourceControlプロパティがRichTextBox1またはRichTextBox2ではなく未定義の値を返します。RichTextBoxが一つでも同様の現象が発生します。他のコントロールは正しいControlを返します。

    再現しました。

    取り急ぎ、テスト結果です。

    2007年2月7日 7:54
    モデレータ
  •  テストありがとうございます。

    訂正します。e2ノードではなくe22ノードの間違いでした。失礼しました。

    補足いたします。私の環境ではe22ノードを削除するとe23ノードが繰り上がりe23ノードを示します。 treeView1.SelectedNode.Remove();
     のあとに

      private void treeView1_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
      {
       textBox1.Text = fg[treeView1.SelectedNode.Index].ToString();
      }

    が実行され

    SelectedNode.Index = 0 はe21ノード
    SelectedNode.Index = 1 はe23ノード

    でSelectedNode.Index は 2以上の値をとらないはずなのですがデバッグで追跡すると SelectedNode.Index = 2 となり fg[2]=3 の値をtextBox1に表示します。

    private void treeView1_DoubleClick(object sender, System.EventArgs e)
      {
       treeView1.SelectedNode.Remove();

    の後に  textBox1.Text = fg[treeView1.SelectedNode.Index].ToString(); を加えると SelectedNode.Index = 1 を返し fg[1]=2 の値を textBox1に正しく表示します。


     ContextMenu.SourceControl の不具合はフォーカスのあるRichTextBoxによってContextMenuのMenuItemの一部を表示しないようにコードを追加した際に発見しました。

     

    2007年2月8日 0:46
  •  せと際開発者 さんからの引用

    SelectedNode.Index = 0 はe21ノード
    SelectedNode.Index = 1 はe23ノード
    でSelectedNode.Index は 2以上の値をとらないはずなのですがデバッグで追跡すると SelectedNode.Index = 2 となり fg[2]=3 の値をtextBox1に表示します。

    最終的には、
    SelectedNode.Index = 0 はe21ノード
    SelectedNode.Index = 1 はe23ノード
    になっています。

    e22ノードをダブルクリックして削除した後にe23がセレクトされ、AfterSelectイベントが発生しますが、この段階ではまだe23のSelectedNode.Indexは2のままです。
    その後、最終的に全てのTreeViewの内部的な処理が終わった後、正しくe23ノードのSelectedNode.Indexは1になります。
    要は、イベントの発生するタイミングの問題のようです。

     せと際開発者 さんからの引用

     ContextMenu.SourceControl の不具合はフォーカスのあるRichTextBoxによってContextMenuのMenuItemの一部を表示しないようにコードを追加した際に発見しました。

    調べてみました。これはどうやら既知の問題のようです。回避策としては、

    1.RichTextBoxのMouseDownイベントにて、RichTextBoxがクリックされたことを変数にしまって置き、それをPopUpメソッド内で参照して判断する。

    もしくは、

    2.以下のコードのように、MouseDownイベントにて、ContextMenuを呼び出す。

    private void richTextBox3_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
    {
     if (e.Button == MouseButtons.Right)
      contextMenu1.Show(richTextBox3, new Point(e.X, e.Y));
    }

    とするようです。

    2007年2月8日 2:23
    モデレータ
  • 丁寧な回答を頂きありがとうございます。参考にしてコードを修正します。
    2007年2月9日 2:27
  • 件名が間違っていたため ContextMenu.SourceControl に修正したところ文字化けしました。日本語の部分はこちらです。

     

    開発環境はVS2003 SP1 + .NET Framework 1.1(SP1) と他に .NET Framework 2.0 SDK

    OSはWindowsXP Professional SP2

     

    code

     

     このコードを実行するとtreeView1にノードが表示されます。e2 ノードを選択しダブルクリックしてこのノードを削除すると SelectedNode.Index = 2 となり存在しないノードの値を返します。

     RichTextBox1とRichTextBox2のContextMenuにcontextMenu1を設定しPopupイベントが発生するとcontextMenu1.SourceControlプロパティがRichTextBox1またはRichTextBox2ではなく未定義の値を返します。RichTextBoxが一つでも同様の現象が発生します。他のコントロールは正しいControlを返します。他の方の環境でも発生しますか。

    2007年2月10日 0:13
  • その後 Windows Update を実行したところ、この問題が修正されました。Windows XP用のセキュリティ更新プログラムに修正が含まれていたと考えています(2007/03)。現在は私の環境ではこの不具合は発生していません。

     

     

    2007年5月3日 8:01