私のアプリケーションにはいくつかのウィンドウがあり、それぞれが異なるCDialog
派生クラスです。
ウィンドウ フレームの右上隅にある「X」ボタンを押すと、ウィンドウが閉じられ、 が呼び出されますPostNcDestroy
。
PostNcDestroy
ただし、4 つのウィンドウの 1 つについては、さらに別のウィンドウの () も呼び出し、そのウィンドウも非表示にします。
何か案は?
短い回答: この動作はm_pMainWnd
、4 つのウィンドウすべてを作成した後に設定したことが原因でした。2 番目のウィンドウを作成する前に設定すると、上記の問題は発生しなくなります。
長い答え: 問題は、ウィンドウが互いに兄弟ではないことです。彼らはそれぞれ PREVIOUS の CHILD です。
ウィンドウ 1 の親は値 "0" (デスクトップ) です。ウィンドウ 2 の親はウィンドウ 1 です。ウィンドウ 3 の親はウィンドウ 2 です。ウィンドウ 4 の親はウィンドウ 3 です。
私の最初の問題レポートでは、ウィンドウ 3 が閉じられたときにウィンドウ 4 が不思議なことに閉じられたことが指摘されていました。これで理由は明らかです。(ウィンドウを閉じると、そのすべての子も閉じられます。) その後、ウィンドウ 2 を閉じると、ウィンドウ 3 と 4 も閉じられることがわかりました。(3 は 2 の子なので閉じるので、3 の子である 4 が閉じます。) 最後に、ウィンドウ 1 を閉じると、保存されていない作業がチェックされ、何も呼び出されない場合は が呼び出されますexit()
。このウィンドウが終了しなければ、他のウィンドウもすべて閉じていたと思います。
CDialog::Create()
NULL
2 番目の arg のデフォルト パラメータがあり、親が「メイン アプリケーション ウィンドウに設定されている」ことpParentWnd
を意味します。NULL
に足を踏み入れると、CDialog::Create()
が呼び出され、最終的には になります。そのメソッドがまだ設定されていない場合は、最近作成されたウィンドウを返すだけです。CDialog::CreateIndirect()
AfxGetMainWnd()
CWinThread::GetMainWnd()
m_pMainWnd
CWnd::GetActiveWindow()
だから:問題の原因は、私のアプリが4つのウィンドウを作成し、 THEN set m_pMainWnd
. これが、ウィンドウ 3 がウィンドウ 2 (その時点でアクティブなウィンドウ) の子であった理由です。4 は 3 の子であり、以下同様です。
ウィンドウ1を作成した後に設定m_pMainWnd
すると、ウィンドウ2、3、および4が1の子になります。したがって、「ウィンドウ3を閉じるとウィンドウ4も閉じる」という問題が解消されます。
これは、ウィンドウ 1 が他の 3 つのウィンドウの前面に表示されないようにするため、まだ必要なものではありません。これは私の元の質問の範囲外ですが、ここで修正します。Create()
呼び出しを明示的に渡すように変更するとGetDesktopWindow()
、アプリが思いどおりに動作するようになり、4 つのウィンドウを個別に閉じて、ウィンドウ スタック内で自由に並べ替えることができるようになりました。
Create( resource_ID, GetDesktopWindow() );
これらの関数のどれも (VS2008Pro の時点で) ドキュメントにm_pMainWnd
は、設定されていないときに実際に何をするかが実際に説明されており、その単純な割り当てをm_pMainWnd
ウィンドウ作成の最後に移動すると、これが有名な問題ではないことに驚いています。おそらく、2つ以上のウィンドウを作成したアプリは台無しになります...
あなたは多くの情報を与えていません。推測することしかできません... すべてのウィンドウがダイアログであると述べているので、アプリケーションの InitInstance() メソッド内で、メインの CDialog 派生クラスの DoModal() への呼び出しがあると推測できます。メイン ダイアログを閉じた後、DoModal() ループを終了し、InitInstance() を終了してアプリケーションをシャットダウンします。アプリケーションをシャットダウンすると、他のダイアログが破棄され、WM_NCDESTROY が送信され、PostNcDestroy() が呼び出されます。