あらかじめ日記

雑記とかブログで使えるスクリプトとかテクニックとか。その他、音楽やアニメ、漫画の話題とかも。

【C#】WinFormsのOnInitDialog? &Handleプロパティはnullチェックできない

MFCWinForms化でネタでついでにもう1つ。
(以前の記事はこちら)

allthewayfrom.hatenablog.com

 MFCのダイアログでコントロール関連の初期処理のタイミングと言えばお馴染みのOnInitDialogと、.NetFormLoadイベント。

一見すると同じようなタイミングですが、実はウインドウが表示されているかどうかと言う差があることに気づきました。
どちらもデザイナで配置したコントロールが生成され、ウインドウの表示準備が整った後で呼ばれますが、OnInitDialogはウインドウがまだ非表示で、Load表示状態と言う違いがあります。
まぁ大抵は同じで扱っても問題無いと思いますしWinFormsではLoadで行うのがセオリーでしょう。(デザイナ上のダブルクリックで生成されるイベントですし)
ただ全く同じではないことは意識しておいた方が良いかもしれません。

 

では、同じタイミングのイベントはあるのか。

 

WndProcをオーバーライドしてWM_INITDIALOGが来ればそのまま使えるかと思いましたが、メッセージは来ず。。

イベントの一覧を眺めていたところ、CreateHandledと言うものが。タイミングはウインドウハンドルが生成されたらで、Loadより前に呼ばれウインドウも非表示。こちらの方がかなり近そうなので、もし移植をするならこっちの方が良いかもしれません。

ただし、このイベントも注意点があり、ハンドルを任意のタイミングで生成していれば当然イベントが発生してしまいます。
これが、コンストラクタに自動で生成されているデザイナで配置したコントロールを生成するInitializeComponentよりも前に呼ばれてしまうとタイミングとしてはアウトです。。


さらにハンドル生成についても注意点があり、ハンドルを参照するHandleと言うメンバは、ハンドルが生成されていない状態で参照したら、参照した時点で勝手に生成されると言う仕様があります。
なのでInitializeComponentよりも前にHandleを操作されている場合もイベントが呼ばれてしまうのでダメですね。
と言うか、この仕様は参照のした時点で、なのでnullチェックをしようとHandleを参照した時点で生成されるということ、つまりその時点でnullでなくなるのでチェックしても意味が無いんですね。(この挙動は少しハマった。。)


結論としては、WinFormsにおいて基本的にはLoadだが、前述の仕様差で不都合がありる場合はコンストラクタでHandle操作を行っていない上で、CreateHandledを使うでしょうか。
多数のダイアログを移植する場合は、基底クラスを作ってMFCと同じ様にvirtualOnInitDialogを用意してCreateHandledの中から呼び出す(Handleも参照されない様に隠蔽してしまっても良いかも)、なんて作りでもアリかなと思います。

あとは、Handleの仕様にも要注意ですね。