プロが教えるわが家の防犯対策術!

はじめまして質問させてください。

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でフラグを持つことで解決できますが
あまりうまいやりかたではないと思うので質問させて頂きます。

以上になります。
よろしくお願い致します。

A 回答 (5件)

pB->GetSafeHandle()を使って判断は可能なようです


# 実装依存なので今後変わらないとはいえないが …

Debugモードの場合 不定値としての0xcdcdcdcdが戻り
Releaseモードでは 0が帰ってくるようです
    • good
    • 0

クラス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で閉じたとき
  }
}

といった具合でしょう
    • good
    • 0

 こんばんは。

飽くまで参考意見という事で。
 クラス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;
}
    • good
    • 0

http://msdn.microsoft.com/ja-jp/library/zhk0y9cw …
によると、A::BoxDone()をオーバーライドしておけば
モードレスダイアログが破棄された時点で通知される、と
読めるのですが、どうでしょうか。
    • good
    • 0

pBのポインタはdeleteしてもNULLにはならず、元の番地を指しているはずだと思うんですが・・・



やるなら
pB->GetSafeHwnd() == NULL
とかで判定してはどうですか?
やったことないんで動作は分かりませんが。
    • good
    • 0
この回答へのお礼

vipasigaru 様
アドバイスありがとうございます。

Delete後に
pB->GetSafeHwnd()をしても
NULLは帰りません。

ですので困っております。

お礼日時:2008/09/09 19:11

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!