モードレスダイアログの破棄について – プログラミング – Home

モードレスダイアログの破棄について
 
通知
すべてクリア

[解決済] モードレスダイアログの破棄について


よし
 よし
(@よし)
ゲスト
結合: 23年前
投稿: 23
Topic starter  

環境: WINXP, VC6.0, ダイアログベース

○モードレスダイアログの破棄方法についてご教授下さい。
仕様として下記なのですが、2.3.はクリアしたのですが、
1.をうまく制御できません。

1.子ダイアログは、あるイベントにて何度でも生成可能
2.子ダイアログから親ダイアログへ遷移(子ダイアログは消去)
3.親ダイアログを閉じると子ダイアログも消去

下記に必要そうな部分のコードを抽出しました。
すいませんが、宜しくお願いします。

親ダイアログ(モーダル)
CParentDlgクラス
(.h)
class CParentDlg : public CDialog
{
private
CChildDlg* m_pdlg;
};
(.cpp)
BOOL CParentDlg::OnCommand(WPARAM wParam, LPARAM lParam)
{
switch(wParam) {
case 1:
if(m_pdlg) {
m_pdlg->DestroyWindow();
 delete m_pdlg; <-ここの処理でwarnningが発生
}
m_pdlg = new CChildDlg;
m_pdlg->Create(this);
m_pdlg->CenterWindow();
m_pdlg->ShowWindow(SW_SHOW);
break;
}
}

子ダイアログ(モードレス)
CChildDlgクラス
(.h)
class CDaily1MinDlg : public CDialog
{
private
BOOL m_bFlg; // TRUE:メモリ確保中, FALSE:メモリ破棄済み
};
(.cpp)
BOOL CChildDlg::DestroyWindow()
{
--- 略(解放処理) ---
return TRUE;
// return CDialog::DestroyWindow();
}

void CDaily1MinDlg::PostNcDestroy()
{
// ダイアログのデータを削除
if(m_bFlg) {
   DestroyWindow();
m_bFlg = FALSE;
  ]
delete this;
// CDialog::PostNcDestroy();
}

void CDaily1MinDlg::OnCancel()
{
if(m_bFlg) {
DestroyWindow();
m_bFlg = FALSE;
}
ShowWindow(SW_HIDE);
// CDialog::OnCancel();
}


引用未解決
トピックタグ
よし
 よし
(@よし)
ゲスト
結合: 23年前
投稿: 23
Topic starter  

CDaily1MinDlgクラス → CChildDlgクラスとして読み取って下さい。


返信引用
Kerry
 Kerry
(@Kerry)
ゲスト
結合: 20年前
投稿: 192
 

> m_bFlg

↑このフラグが何を表しているのかよくわかりません。

1.~3.の動作を行いたいだけならば以下のようなコードで実現可能です。

class CParentDlg : public CDialog
{
private:
CChildDlg m_dlg;
};

void CParentDlg::OnXXXX()
{
if (::IsWindow(m_dlg.m_hWnd))
m_dlg.DestroyWindow();

m_dlg.Create(this);
m_dlg.CenterWindow();
m_dlg.ShowWindow(SW_SHOW);
}

class CChildDlg : public CDialog
{
};

void CChildDlg::OnCancel()
{
DestroyWindow();
}


返信引用
rin
 rin
(@rin)
ゲスト
結合: 18年前
投稿: 112
 

BOOL CChildDlg::DestroyWindow()
{
--- 略(解放処理) ---
return TRUE;
// return CDialog::DestroyWindow();
}

ここで基本クラスのDestroyWindowの呼び出しを制限してますが
「 --- 略(解放処理) ---」のところで、
それに変わる内容をちゃんとしてるのでしょうか?


返信引用
よし
 よし
(@よし)
ゲスト
結合: 23年前
投稿: 23
Topic starter  

返答ありがとうございます。

Kerryさん、m_bFlgはDestroyWindow();を処理したか否かのフラグです。

rinさん、DestroyWindow()内のデフォルト処理は残しておいても良いのでしょうか?
// TODO: この位置に固有の処理を追加するか、または基本クラスを呼び出してください
となっていますが。。。

とりあえず、Kerryさんの方法で実装してみます。


返信引用
よし
 よし
(@よし)
ゲスト
結合: 23年前
投稿: 23
Topic starter  

Kerryさんのコードで試してみましたが、子ダイアログのDestroyWindow()内で解放処理
を行い、親ダイアログから子ダイアログのDestroyWindow()処理する為、解放領域を再度
解放しようとする為、落ちてしまいます。
CDialog::DestroyWindow();を実行するとCDialog::PostNcDestroy()を処理してくれるの
でしょうか?


返信引用
Kerry
 Kerry
(@Kerry)
ゲスト
結合: 20年前
投稿: 192
 

DestroyWindowではなく、子ダイアログのOnDestroy(WM_DESTROY)で
その解放処理とやらを行えばよいと思います。


返信引用
よし
 よし
(@よし)
ゲスト
結合: 23年前
投稿: 23
Topic starter  

下記のように変更したら解決しました。

①子ダイアログにOnDestroy()を追加
②DestroyWindow()では、CDialog::DestroyWindow();を処理
③OnDestroy()では、子ダイアログで確保した領域の解放処理
④PostNcDestroy()では、delete this; を処理

※メモリリーク、ワーニング共に解消されました。
※DestroyWindow() → OnDestroy() → PostNcDestroy() の順で処理してくれるの
 ですね。
※親側で明示的にdeleteしなくてもいいこともわかりました。

返答をくれた方々、ありがとうございます。


返信引用
よし
 よし
(@よし)
ゲスト
結合: 23年前
投稿: 23
Topic starter  

解決にチェックを入れ忘れたので。。。


返信引用
たいちう
 たいちう
(@たいちう)
ゲスト
結合: 23年前
投稿: 662
 

いまさらだけど、一時的に非表示にするだけでは駄目だったのかな?


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました