- PR -

MenuItemコントロールについて

1
投稿者投稿内容
kernel
常連さん
会議室デビュー日: 2005/10/05
投稿数: 22
投稿日時: 2007-02-06 16:37
フォームのメニューを作成する関数を作って、出来上がったメニューのHandleを保持しておきたいと考えています。そこで、以下のようなコードを書きました。このコードを関数化して複数回呼んだ場合、メニューが追加される度にHandleの値が違っているのですが、これは仕様なのでしょうか?

また、MenuItemクラスのメソッドで、GetHashCodeメソッドというのがありますが、これによって得られる値というのは出来上がった全メニューに一意に割り当てられるものでしょうか?

質問が長くなって申し訳ありませんん。よろしくお願いします。

// ルートメニュー
MenuItem mi = new MenuItem();
mi.Text = "テスト";
mi.Index = 0;

// サブメニュー1
MenuItem subm1 = new MenuItem();
subm1.Text = "テスト1";
subm1.Index = 0;
System.IntPtr hd1 = subm1.Handle; //<--本当はメンバ変数に代入

// サブメニュー2
MenuItem subm2 = new MenuItem();
subm2.Text = "テスト2";
subm2.Index = 1;
System.IntPtr hd1 = subm2.Handle; //<--本当はメンバ変数に代入

// ルートメニュー配下にサブメニュー追加
mi.MenuItems.AddRange(new MenuItem[] {subm1, subm2});

// テストルートメニューをメインメニュー追加
mainMenu.MenuItems.AddRange(new MenuItem[] {mi});
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-02-06 17:02
引用:

kernelさんの書き込み (2007-02-06 16:37) より:

メニューが追加される度にHandleの値が違っているのですが、これは仕様なのでしょうか?


"追加される度" ですか?
インスタンスを作成すれば当然別物になるでしょうし、なってもらわないと困りますよね。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
kernel
常連さん
会議室デビュー日: 2005/10/05
投稿数: 22
投稿日時: 2007-02-06 17:17
関数の最後で下のようなコードで確認しました。mainMenuは関数の外でインスタンス化したものを使いまわしています。なので、サブメニューを追加すると新しいサブメニューは当然、新たなhandleが割り当てられて当然だと思うのですが、古いメニューは最初に追加した時のままだろうと考えているのですが、私は何か勘違いしていますか?

Console.WriteLine("--handleのチェック開始--");
int mmCnt = mainMenu.MenuItems.Count;
for(int i=0; i<mmCnt; i++)
{
int smCnt = mainMenu.MenuItems[i].MenuItems.Count;
for(int j=0; j<smCnt; j++)
{
Console.WriteLine(mainMenu.MenuItems[i].MenuItems[j].Handle.ToString());
}
}
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2007-02-06 17:31

そもそもハンドルを保持しておく必要がいったいどこに?
API 呼び出しとかで必要になるにしてもそのたびに取得すれば良いだけですが。

引用:

MenuItemクラスのメソッドで、GetHashCodeメソッドというのがありますが、これによって得られる値というのは出来上がった全メニューに一意に割り当てられるものでしょうか?


ハッシュはハッシュです。
できる限り同じ数字が出ないようなのが良いハッシュですが、所詮は Int32 なので同じハッシュが出現し得ます。
kernel
常連さん
会議室デビュー日: 2005/10/05
投稿数: 22
投稿日時: 2007-02-07 09:48
メニューから先のビジネスロジックを同一のインターフェースから派生した別のクラスにしておき、それらのインスタンスを全てハッシュに入れ、メニューが押された時、以下のように連続で実行します。

IDictionaryEnumerator en = hashTbl.GetEnumerator();
while(en.MoveNext())
{
clsInterface interface = (clsInterface)en.Value;
interface.clickMethod(メニューのhandle);
}

各クラスのclickMethodの先頭で、クラスのメンバ変数に保持したhandleと、引数のhandleを比較して同じなら、そのクラスのビジネスロジックが走るという風にしたいのです。そうすれば、機能追加の時、新しいメニューのクラスをインターフェースから派生して作るだけだから楽かなあと思ったのです。

少し話しがそれてしまいましたが、メニュー追加の度にhandleが変わるのであれば、他の方法を考えようと思います。ありがとうございました。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-02-07 10:51
引用:

kernelさんの書き込み (2007-02-07 09:48) より:

各クラスのclickMethodの先頭で、クラスのメンバ変数に保持したhandleと、引数のhandleを比較して同じなら、そのクラスのビジネスロジックが走るという風にしたいのです。そうすれば、機能追加の時、新しいメニューのクラスをインターフェースから派生して作るだけだから楽かなあと思ったのです。


(ご説明を正しく理解できていないかもしれませんが)
Handle で比較して判断するのではなく、同一インスタンスかどうかで判断すれば良いと思うのですが...

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
KI
大ベテラン
会議室デビュー日: 2007/01/10
投稿数: 239
投稿日時: 2007-02-07 12:02
説明をいまいち理解できていないので外しているかも知れませんが、
(おそらくメニューが動的に変わるとかそういう理由で)
メニューそれぞれにハンドラを書くのが面倒なので、
共通のハンドラ用のメソッドを1つ用意して、
全メニューアイテムのClickイベントのハンドラに追加するようなことを
考えていらっしゃるのでしょうか?
つまり

引用:

IDictionaryEnumerator en = hashTbl.GetEnumerator();
while(en.MoveNext())
{
clsInterface interface = (clsInterface)en.Value;
interface.clickMethod(メニューのhandle);
}


このコードは
コード:
// メニュー追加後にこんな感じで書いて
int mmCnt = mainMenu.MenuItems.Count;
for(int i=0; i<mmCnt; i++)
{
    int smCnt = mainMenu.MenuItems[i].MenuItems.Count;
    for(int j=0; j<smCnt; j++)
    {
        Menuitem item = mainMenu.MenuItems[i].MenuItems[j];
        item.Clicked += MenuClicked(item, new EventArgs());
    }
}

// Clickイベントハンドラ
private MenuClicked(object sender, EventArgs e)
{
    IDictionaryEnumerator en = hashTbl.GetEnumerator();
    while(en.MoveNext())
    {
        clsInterface interface = (clsInterface)en.Value; 
        interface.clickMethod(メニューのhandle);
    }
}


こんな風に使われるのでしょうか?
だったら、MenuClicked内でループなんてまわさなくても
senderとのインスタンスの比較で出来るような気がします。

書いていて、やっぱり外してるような気がしてきました…
外してたらスルーしてください。
1

スキルアップ/キャリアアップ(JOB@IT)