ブログトップ 記事一覧 ログイン 無料ブログ開設

Kazzzの日記 このページをアンテナに追加 RSSフィード

2007-09-13

[][]System.Windows.Forms.Loadイベントは一度だけとは限らない


自分の経験とドキュメントを読んだ感覚で判断したことが実は単なる思い込みだったことはままあるが、今回もそんな一件。

WindowsFormにおいて、FormのLoadイベントの解説は日本語ドキュメントでは以下のように明記されている。

Form.Load イベント
フォームが初めて表示される直前に発生します。

これに基づきLoadイベントには一度しか実行されないことを期待した処理をコーディングするのだが、なんと以下のコードを実行するとLoadイベントはShowDialogメソッドを実行した回数、つまり3回発生するのである。むろん、Form1クラスのインスタンスの生成は一度しか行っていないのに、だ。

Form1 frm1 = Form1;
frm1.ShowDialog();
frm1.ShowDialog();
frm1.ShowDialog();

フォームが初めて表示される直前、初めて表示? 初めて?......
ここでMSDNに掲載されている同イベントの原文(英文)を見てみよう。

Form.Load Event.
Occurs before a form is displayed for the first time.


orz....

.NET WindowsFormを使って数年になるのだが、今の今まで気が付かなかった。恥かしい限りだ。

追記:

誤解を招くかもしれないので敢えて書くが、以下のようにShowメソッドを使う場合は何度実行してもLoadイベントは一回しか発生しない。(この一貫性の無さが上記の思い込みを生む元凶だ)

Form1 frm1 = Form1;
frm1.Show();
frm1.Hide();
frm1.Show();
frm1.Hide();
frm1.Show();

囚人囚人 2007/09/13 11:16 OH!
相変わらず変訳だらけですねぇ。原文を参照する癖をつけろ、という事なんでしょうか。

NyaRuRuNyaRuRu 2007/09/13 11:58 要するに WM_INITDIALOG 相当ってことなんですかねぇ.

結局 WinForms は『Windows プログラミングの極意』を読破した玄人向けというイメージがあったりします.

NyaRuRuNyaRuRu 2007/09/13 12:12 10.4.2 フレームウィンドウの作成
「ダイアログプロシージャでWM_CREATEといったウィンドウ作成メッセージを取得できないのは、このためである。フレームが作成される時点では、ダイアログプロシージャはまだ有効ではない。ダイアログマネージャがダイアログプロシージャをアタッチできるのは、フレームが作成された後である。」
-------------
もちろん WinForms は既存のダイアログテンプレートとは異なるフレームワークですが,どの辺に落とし穴があるかという点では類似性があるように思います.

Form1 frm1 = new Form1();
frm1.ShowDialog();
frm1.ShowDialog();
frm1.ShowDialog();

このコードを実行すると,ShowDialog のたびにウィンドウの生成の破棄が行われます.(実際 frm1.Handle をダンプしてみると一目瞭然)

C# のソースコードからは「同一のインスタンス」を使い回しているように見えますが,Win32 ウィンドウシステム的には 3 回のウィンドウ生成と破棄が行われていて,事態は結構複雑です.

KazzzKazzz 2007/09/13 12:30
みなさん、コメントありがとうございます。

>相変わらず変訳だらけですねぇ。原文を参照する癖をつけろ、という事なんでしょうか
変訳というか、意訳ミスのような気もします。
どちらにせよ確信が持てない場合は原文を見たほうが却ってピンとくることが多いですね。

>結局 WinForms は『Windows プログラミングの極意』を読破した玄人向けというイメージがあったりします.
どんなフレームワークであっても結局は根幹であるAPIとその原理原則を理解していないと駄目ということですね。

>このコードを実行すると,ShowDialog のたびにウィンドウの生成の破棄が行われます.(実際 frm1.Handle をダンプしてみると一目瞭然)
抽象度を上げて解り易くするために仕方が無かったのでしょうが、ハンドルのライフサイクルとマネジドインスタンスのライフサイクルが一致しないことに違和感があるんですよね。(無論、そのお陰でHWndを意識せずにプログラミングできるメリットがある訳ですが)

NyaRuRuNyaRuRu 2007/09/13 13:47 >抽象度を上げて解り易くするために仕方が無かったのでしょうが、ハンドルのライフサイクルとマネジドインスタンスのライフサイクルが一致しないことに違和感があるんですよね。

これは確かにかなりアブナイ実装なんですよねぇ.
http://bbs.wankuma.com/index.cgi?mode=al2&namber=6843&page=20&KLOG=18#4
この事例も Microsoft 自身が嵌っているっぽい様子でした.

私も昔,C++ をおぼえたての頃は,C 時代のハンドルが露出したフレームワークを嫌ってずいぶんラッパークラスを作りましたが……
怖くて当時のソースが読めません.

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/Kazzz/20070913/p4