• 締切済み

Closeメソッド詳細を教えてください

MDI親フォームよりMDI子フォームをCloseした場合で困っています。 Class MDI子フォーム Private m_Class as New Class Public Sub New() WithEvent ユーザコントロールイベント End Sub Public Sub MDI子フォーム_Closed m_Class = Nothing End Sub Private Sub ユーザコントロール_ユーザコントロールイベント ' m_Class を使用 End Sub End Class といった感じのMDI子フォームを親フォームLoad時にNew後、Showします。MDI子フォームにて、m_Classをユーザコントロールイベントで参照を行います。ユーザコントロールイベントは、コントロール自身に対するメッセージを受け取ると発生します。 ・プロセスA 親フォームをスタートアップとしMDIフォーム ・プロセスB ユーザコントロールハンドルに対しメッセージ送信を行う 以上をふまえていただいて、プロセスAにてMDI子フォームを表示→Closeを繰り返し、プロセスBにてメッセージ送信を行っているとNull例外(ArgumentNullException?)が発生します。 Q1.子フォームがCloseされたあと、ユーザコントロールイベントが発生しているように思えるのですが、この認識は正しいのでしょうか? (Close処理後、Disposeされるまでの間にイベント通知されると、ユーザコントロールハンドルは開放されていないため、プロセスBよりメッセージ通知が可能となり、例外発生して当然のような気がしています) Q2.Closeメソッドは具体的に何をするのですか? (Closeしてもハンドル開放されず、Disposeで初めてハンドル開放されるのでしょうか?) 以上です。よろしくお願いいたします。

みんなの回答

回答No.3

WM_CLOSEが送られて来ても、WM_DESTROYが起こるまで、ハンドルは生きてるはずです。 だから >WM_CLOSEを認識(Closeメソッドが発行された)している間に、別プロセスがユーザコントロールにユーザーメッセージを送る事は可能なのでしょうか。 可能です。 >対象となるユーザコントロールをFindWindowExにてハンドルより探し出し 外見的に見えるユーザコントロールなのですか? それならば、QueryUnload時に、フォームを非可視にしてしまえば、FindWindowEx+IsWindowVisibleのAPIの組み合わせで、送信すべきかどうかを判定できます。 ところでこれってVB6ですよね?それとも.NETですか? VB6なら Private m_Class as New Class を Private m_Class as Class に型だけ宣言して、インスタンス生成は、別タイミングにしておいた方がいいですよ。 開放がされづらくなります。

donta01
質問者

お礼

度々の回答たいへんありがとうございます。 最初に、質問しているのは.NETです。 回答頂いた件(WM_CLOSEが送られて来ても、WM_DESTROYが起こるまで、ハンドルは生きてる)ですが、Spyで確認してみた所、私の方でも確認できました。報告が遅れ申し訳ありません。 1.子フォームには、メンバー変数としてNewしているオブジェクト変数A(単なるbyte型変数の集まり)がある。 2.子フォームは、Closedイベント発生時にオブジェクト変数Aを論理的開放(Nothing)。 3.子フォームのユーザーコントロールイベントにより、オブジェクト変数Aに対しMarshal.Sizeofを実施。 4.別プロセスはユーザーコントロールハンドルだけでメッセージを送る(メッセージを受けた子フォームのユーザーコントロールはRaiseEventにより子フォームのユーザーコントロールイベント発生) JITによると、3.にて極まれに、Marshal.SizeofでArgumentNULL例外が発生してしまいます。.NETにてデバッグモード実行していると同様の例外が発生し、オブジェクト変数AがNothingになっています。 私は、オブジェクト変数AがNothingとなるのは、 1.WM_CLOSEを受け取った時 2.子フォームがCLOSEされ、オブジェクト変数Aへの参照がなくなった時 と認識しています。  現在の所の私の推測ですが、上記例外が発生するのは、WM_CLOSEにより、オブジェクト変数AがNothingになり、その後、子フォームのユーザーコントロールイベント発生した際、オブジェクト変数A(=Nothing)に対しMarshal.Sizeofしているためだと思っています。  子フォームがWM_CLOSEを受け取っているにも関わらず、子フォームのユーザーコントロールがイベントを発生させる(別プロセスからのユーザーメッセージを受け取る)事ができる点に問題があるように思えます。ユーザーコントロールにて、自身の親である子フォームがCLOSEを受けとったかどうか判断する方法はないものでしょうか? 度々の質問ですが、よろしくお願いします。

回答No.2

ユーザコントロール側で、オブジェクト変数が破棄されないままユーザコントロールが破棄される場合に、発生した記憶があります。 小窓に張り付いたユーザコントロールが、オブジェクトを握った(オブジェクト変数が開放されていない)まま、小窓が閉じられようとしていませんか? この場合、親離れできないゴーストがメモリに居残ろうと、無意味に頑張ります。 私の場合は、ユーザコントロール側で、ユーザコントロールの親窓(この場合MDIの小窓)をフックして、親窓のWM_DESTOROYを認識し、ユーザコントロール内部で使用しているオブジェクト群を、オール破棄しました。 具体的な作りがわかれば、もっと詳細な事が言えそうなのですが。。。

donta01
質問者

お礼

再び、ありがとうございます。 ユーザコントロールでは、オブジェクト変数すらありません。単純に別プロセスからのユーザーメッセージを受けたら、Eventを発生させるだけです。 親窓のWM_DESTOROYを認識しという点からの想像ですが、ユーザコントロールの親フォームがWM_CLOSEを認識(Closeメソッドが発行された)している間に、別プロセスがユーザコントロールにユーザーメッセージを送る事は可能なのでしょうか。 別プロセスは対象となるユーザコントロールをFindWindowExにてハンドルより探し出し、ハンドルがなければ、ユーザーメッセージ送信を取りやめています。

回答No.1

よくわかっておりません。 小窓達の分だけ、ユーザコントロールが派生される作りでしょうか? (1小窓→1ユーザコントロール) さらに、ユーザコントロールの所有者は、その小窓ということですか? そうであれば、小窓が閉じる前に、ユーザコントロールを破棄するか、ユーザコントロール側で、小窓の破棄通知を取得して、独自で親離れする必要があると思います。 (作りがよくわかっておりませんので、外していたらすいません。)

donta01
質問者

補足

どうもありがとうございます。 A1.ユーザコントロールの所有者は、その小窓ということですか →そのとおりです 独自で親離れするという点を、出来ましたらもう少し具体的に教えて頂きたいです。 ユーザーコントロールをあるイベントが発生する派生ラベルコントロールと想定した場合、フォームデザイン時に、派生ラベルコントロールを配置してしまえば、ユーザコントロールの所有者(=小窓)が破棄される直前に、その派生ラベルコントロールが破棄され、勝手に親離れすると思い込んでいたのですが、違うのでしょうか?

関連するQ&A

専門家に質問してみよう