メインが終了した場合、サブダイアログも終了するには?

解決


くろねこ  2010-02-26 08:48:33  No: 71444  IP: [192.*.*.*]

こんにちわ。

環境はVC++6.0、MFC、WindowsXPです。

メインが起動し、そこにあるボタン押下でサブダイアログをモーダルで起動しているのですが、メインでOnTimerを使っており、数秒後に条件に満たさない(接続通信エラー等)時にAfxMessageBoxを呼んで、OKを押下すると、プログラムを終了するのですが、サブのほうが閉じません。

このメインが閉じればサブも閉じる方法が分からないので、教えてくれませんでしょうか。よろしくお願いします。

編集 削除
ryo  2010-02-26 12:37:50  No: 71445  IP: [192.*.*.*]

質問内容が

・本当は、メッセージボックスだとか、メインの終了だとかはあまり関係なく
「メインからモーダルのダイアログを閉じる方法がわからない」
なのか、

・サブのダイアログを閉じる手法は分かるが
「メインが終了するときに、どこでソレをやればいいのかわからない」
なのか、
どっちでしょうか?もしくはどっちも?

他・
メインとはどんなものか?(ダイアログベース?)
サブダイアログの作成、および管理はどうしているのか?

編集 削除
仲澤@失業者  2010-02-26 12:50:07  No: 71446  IP: [192.*.*.*]

DoModal()で起動するDLGは本来のモーダルDLGではないため、
自動的に終了させることができます。

1.DLGクラスのContinueModal()をオーバーライドします。
2.DLGクラスにBOOL AutoExit = FALSE;を用意します。
3.SetTimer()してDLG::DoModal()します。
4.タイマーイベント時にDLG::AutoExitをTRUEします。
5.DLG::ContinueModal()内でAutoExitを監視してTRUEならば
    return FALSE;します。
6.DLGが自動的に消滅します。

編集 削除
くろねこ  2010-03-02 08:54:31  No: 71447  IP: [192.*.*.*]

遅くなってすみません。

ダイアログベースで作成しており、
サブダイアログはOnContextMenu()内でDoModal()として呼び出しています。

それでメインのOnTimer()内で数秒に一度通信による処理を行なっており、

通信が失敗すればAfxMessageBox()を呼んで、OKボタンをクリックすると、メインのアプリケーションが閉じるという処理をしています。

つまり現状はその通信の処理を行う前の数秒間の間にOnContextMenu()を呼び出すと、サブダイアログが作成され、通信が失敗すると、AfxMessageBox()が呼び出され、OKをクリックするとメインだけが閉じるとなっています。


分からない点・処理を行い点はメインが閉じるとサブダイアログも閉じることです。


よろしくお願いします。

編集 削除
仲澤@失業者  2010-03-02 10:36:44  No: 71448  IP: [192.*.*.*]

自分の示した手順をやってみましたか(質問)。

編集 削除
ryo  2010-03-02 12:18:42  No: 71449  IP: [192.*.*.*]

>分からない点・処理を行い点はメインが閉じるとサブダイアログも閉じることです。
つまり、
「どっちでしょうか?もしくはどっちも?」の、どっちも  ってことですね?

まず、閉じるべき場所は、閉じたいと思った場所で。
今回なら、AfxMessageBoxの結果でIDOKを受け取ったところ
かつ、メインを閉じる前。

閉じる方法だが・・・
たぶん、サブダイアログをOnContextMenu内のローカル変数にしてるのでしょう(*1)
そのため、OnTimer内からサブダイアログに対して
終了処理に限らず、なんの処理もかけることができないのではないでしょうか?
もし、そうなら、サブダイアログをメインのダイアログのメンバ変数にしてください。
そうすりゃ、OnTimer内からでも処理できます。
注:ただし、今回想定された動作以外で動かすと
エラーが起きる可能性があるので、エラー避けが必要です

*1:この予想(てか、解答側に予想させないで・・・)が外れてるなら
サブダイアログについての情報をもっと提示してください。

編集 削除
ryo  2010-03-02 12:33:29  No: 71450  IP: [192.*.*.*]

書き忘れ

OnTimer内から、サブダイアログに対し、アクセスできるようになれば
PostMessageでWM_CLOSEを送れば終了できる。
(サブダイアログの作りにもよりますが・・・)

編集 削除
tetrapod  2010-03-02 14:03:37  No: 71451  IP: [192.*.*.*]

EndDialog を使うほうが正規だと思うけど

編集 削除
gak  2010-03-02 17:24:49  No: 71452  IP: [192.*.*.*]

> 処理を行い点はメインが閉じるとサブダイアログも閉じること
乱暴かもしれないが、下記処理でもサブダイアログ等(メインをownerで、SC_CLOSEに対応している事が条件)を全て閉じられる。
サブダイアログがメッセージボックスを表示している等で、多重のモーダルループに入っていても全て閉じる。

void メイン::サブを閉じる処理() {
    CWnd* wnd;
    while ((wnd = GetLastActivePopup()) != this) {
        wnd->PostMessage(WM_SYSCOMMAND, SC_CLOSE, 0);
        MSG msg;
        while (::PeekMessage(&msg, wnd->GetSafeHwnd(), 0, 0, PM_REMOVE)) {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }
    }
}

# サブダイアログをモーダルで出している最中に他部分から強制終了を喰らう仕様には少々抵抗を感じる…何か怖ぃ

編集 削除
くろねこ  2010-03-05 08:55:17  No: 71453  IP: [192.*.*.*]

また遅くなってすみません。

みなさんのおかげで無事に解決することができました。

># サブダイアログをモーダルで出している最中に他部分から強制終了を喰らう仕様には少々抵抗を感じる…何か怖ぃ

そう思ったのですが、メインが閉じて、サブダイアログが残っているというのはおかしいと思ったのでこういう処理をすることにしました。


回答者の皆様、ありがとうございました。

編集 削除