複数のモードレスダイアログの取り扱い

[戻る]
omiomi 2005/01/15(土) 09:30:29
VC++.net MFC WinXPです。初心者です。

1.モードレスダイアログ(子)作成時にCreate関数で親ウィンドウを指定すれば、
親ウィンドウを破棄するときに子ウィンドウも破棄されるので、
子に対してDestroyWindowをする必要はないということですが、
newした子ウィンドウをdeleteする必要もないということでしょうか?

2.親ダイアログ上のボタン押下時に子モードレスダイアログが開きます。
子モードレスダイアログは複数表示可能で、独立に閉じることができるようにしたいです。
今は以下のようにしています。

<親>
ヘッダ内
extern C子* pChild;


cpp内

C子* pChild=NULL;

C親::ボタン押下時関数()
{
   if(pChild){
       pChild=new C子;
       Create(子ダイアログのID,this);
   }
}

<子>
C子::OnClose()
{
   pChild=NULL;
}

心配なのは、子のOnClose()でpChildをNULLにしてしまうと
親を破棄した際にメモリリークしないかということです。
ただその場合は複数の子ダイアログそれぞれに対して別の子ダイアログをさすポインタが
必要になり、子ダイアログの最大値を決めていないので、処理が複雑になるという心配をしてい
ます。
ダイアログについてよくわかっていないので、見当はずれかもしれませんが、
よろしくお願いします。

omiomi 2005/01/15(土) 09:44:53
すみません。間違ってました。上のソースは
「ボタン押下時に子モードレスダイアログが表示されていたら表示しない」というものでした。
最初上記のようにしていたのですが、メモリリークの心配をし、子のOnCloseで親に
postMessageしてそこで
pChild->DestroyWindow();
delete pChild;
pChild=NULL;

としてました。1番目の質問と関係ありますが、この処理は必要ないということでしょうか?

そして2番目の問題ですが、
<親>
ヘッダ内
extern C子* pChild;


cpp内

C子* pChild=NULL;

C親::ボタン押下時関数()
{
    pChild=new C子;
    Create(子ダイアログのID,this);
}

<子>
C子::OnClose()
{
   pChild=NULL;
}

上記のようにしているのですが、やはりメモリリークするのでしょうか?
そうであれば、子ダイアログの数だけ子ダイアログをさすポインタをつくれば
いいのでしょうか?

dairygoods 2005/01/15(土) 10:47:57
> 子に対してDestroyWindowをする必要はないということですが、
> newした子ウィンドウをdeleteする必要もないということでしょうか?

DestroyWindowは不要ですが、deleteは必要です。
ウィンドウの親子関係はありますが、
メモリーに親子関係はありません。

MFCで一般に使われる技法としては、PostNcDestroy()をオーバーライドし、
void CChildDlg::PostNcDestroy()
{
  delete this;
}
とする方法があります。

こうすると、各子ウィンドウが自分で自分用のメモリーを解放するので、
親は子供全員のポインタを(配列に入れて)覚えておく必要はありません。


> C子::OnClose()
> {
>    pChild=NULL;
> }
変数にNULLを代入する行為自体は、メモリーリークを引き起こしませんが、
deleteすべきポインタ値が分からなくなってしまうので、
二度とdeleteすることができず、結果的にリークします。

omiomi 2005/01/15(土) 18:15:24
[[解決]]
わかりやすい説明ありがとうございます。
また何かあればよろしくお願いします。

古いスレッドには追加発言できません。