- 締切済み
MFC モードレスDlgについて
はじめまして質問させてください。 VC++ 2005 MFC で開発しております。 以下に動作仕様を記載いたします。 ・ボタン押下でダイアログをモードレスで作成表示。 ・再度ボタンが押下された場合、表示されていれば無視。 表示されていなければ新規作成。 ・モードレスで作成したDlgはクローズ時に完全にDeleteしたい。 以下のように実装しましたところ、 【クラスA】メイン B* pB; pB = NULL; void A::Onボタンクリック{ if( pB == NULL ){ pB = new B(); pB->Create( ID, this ); } pB.ShowWindow( true ); } 【クラスB】モードレス void B::OnCancel() { //CDialog::OnCancel(); this->DestroyWindow(); } void B::PostNcDestroy() { //CDialog::PostNcDestroy(); delete this; } 2回目以降、クラスAで「pB」がNULLにならずに判定部分ではまっております。 どのような方法が最適かお詳しい方がおられましたらご教授お願い致します。 ちなみにポインタではなくメンバ変数の場合だと if( b.GetSafeHwnd() == NULL ) でうまくいくのですが ポイントはモードレスダイアログの毎回Deleteです。 クラスBでフラグを持つことで解決できますが あまりうまいやりかたではないと思うので質問させて頂きます。 以上になります。 よろしくお願い致します。
- みんなの回答 (5)
- 専門家の回答
みんなの回答
- redfox63
- ベストアンサー率71% (1325/1856)
pB->GetSafeHandle()を使って判断は可能なようです # 実装依存なので今後変わらないとはいえないが … Debugモードの場合 不定値としての0xcdcdcdcdが戻り Releaseモードでは 0が帰ってくるようです
- redfox63
- ベストアンサー率71% (1325/1856)
クラスB側で破棄される場合に呼ばれる OnOKやOnCnacelでクラスA側の特定の関数を呼ぶようにコーディングしましょう void A::MyDone() { pB = NULL; } といった publicアクセスのメンバ関数を用意しておいて クラスB側で void B::OnOK() { ((A*)this->GetParent())->MyDone(); this->DestroyWindow(); } void B::OnCancel() { ((A*)this->GetParent())->MyDone(); this->DestroyWindow(); } といった具合にします または RegisterWindowMessegeでクラスBを閉じる場合にクラスAに通知するメッセージを登録しておいて OnOKには this->GetParent()->PostMessage( uMsgRegist, 1, 0 ); OnCancelには this->GetParent()->PostMessage( uMsgRegist, 0, 0 ); などとしておいて クラスA側のメッセージマップに ON_REGISTERED_MESSAGE( uMsgRegist, MyDoneCallBack ) メンバ関数として LRESULT A::myDoneCallBack(WPARAM wParam, LPARAM lParam) { pB = NULL; if ( wParam == 1 ) { // OKで閉じたとき } else { // Cancelで閉じたとき } } といった具合でしょう
- machongola
- ベストアンサー率60% (434/720)
こんばんは。飽くまで参考意見という事で。 クラスBをシングルトンにする。 ただ、質問には「クラスBにフラグ等を持たせたく無い」とあるので、私ならこうする。 【クラスA】メイン class A : public CDialog { public: //フラグを操作するメンバ関数 void SetFlag(bool flagB) { this->m_flagB = flagB; } private: //クラスBダイアログが開いているかどうか 初期はfalse bool m_flagB; //その他色々 }; void A::Onボタンクリック() { //フラグが上がっているので引き返す if(m_flagB) return; //フラグを上げる m_flagB = true; //クラスBダイアログを開く B* pB = new B(); pB->Create(ID, this); pB->ShowWindow(SW_SHOW); } 【クラスB】モードレス void B::OnCancel() { // TODO: この位置に特別な後処理を追加してください。 A* p = dynamic_cast<A*>(this->GetParent()); if(p) { p->SetFlag(false); } this->DestroyWindow(); } void CDlgB::PostNcDestroy() { // TODO: この位置に固有の処理を追加するか、または基本クラスを呼び出してください delete this; }
- hidebun
- ベストアンサー率50% (92/181)
http://msdn.microsoft.com/ja-jp/library/zhk0y9cw.aspx によると、A::BoxDone()をオーバーライドしておけば モードレスダイアログが破棄された時点で通知される、と 読めるのですが、どうでしょうか。
- vipasigaru
- ベストアンサー率38% (16/42)
pBのポインタはdeleteしてもNULLにはならず、元の番地を指しているはずだと思うんですが・・・ やるなら pB->GetSafeHwnd() == NULL とかで判定してはどうですか? やったことないんで動作は分かりませんが。
お礼
vipasigaru 様 アドバイスありがとうございます。 Delete後に pB->GetSafeHwnd()をしても NULLは帰りません。 ですので困っております。