- ベストアンサー
モードレスダイアログの作成について
- モードレスダイアログの作成方法について詳しく解説されています。
- クラスウィザードを使用して新規ダイアログを追加する際に、識別名を宣言する際のエラーについての対処方法を教えてください。
- モードレスダイアログの作成に関する問題についての質問です。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
>CTestDlgを破棄するときに、m_pTest = NULLとしたいのですが、'm_pTest' が定義されていないと言われてしまいます。 m_pTestはサンプルどおりに作られているのでしたらCModelessDlgのメンバ変数ですよね。 CTestDlgを破棄するときというのは、どこのことを言っていますか? CTestDlg::PostNcDestroy()の中でしょうか? m_pTestはCModelessDlgのメンバなので、単純にm_pTest = NULLとしてもだめなのは分かりますか? 今回は、親ウィンドウのクラスのインスタンス、つまり、m_pParentのメンバ変数のm_pTestをNULLにしたいはずです。 で、 m_pParent->m_pTest = NULL; とすればOKそうに見えるのですが、このサンプル、なぜかm_pParentがCWnd * で宣言されています。 このため、m_pTestを参照するにはサブクラスである CModelessDlg * でキャストする必要があります。 ((CModelessDlg *)m_pParent)->m_pTest = NULL; これでもいいのですが、オブジェクト指向の考え方だと、 通常、外部からはメンバ変数は直接操作させません。 メソッドや、プロパティといったものを経由してアクセスさせます。 ((CModelessDlg *)m_pParent)->EndTestDlg(); の記述で呼び出しているCModelessDlg::EndTestDlg()が m_pTestをNULLにするためのメソッドなのかな?と 想像はつきますが、どこにも記述がないので何ともいえません。 これまでに出てきた用語が分からないのであれば、オブジェクト指向について学習されることをお勧めします。 #通常、親と子の双方でCWndのポインタを持ち合うなんて事はしません。親と子は1対多の関係なんですからCWnd::GetParent()で取得できます。 また、持つにしてもわざわざCWnd*で持つ必要はありません。キャストの必要が発生してわずらわしいだけです。 さらに派生クラスを作って仮想関数呼び出しをするのでない限り。
その他の回答 (4)
- taka_tetsu
- ベストアンサー率65% (1020/1553)
>>CTestDlg::PostNcDestroy()の中にある、 >>((CModelessDlg *)m_pParent)->EndTestDlg(); >>消してないんですよね? > >もともとこの記述がないのですが、、、 urlのページの、下から2つ目くらいのところですかねぇ。
お礼
お付き合い頂き、ありがとうございました。 CTestDlg::PostNcDestroy()が抜けており、 追加したらうまく行きました。 今回は慌ててプロジェクトを作成したため、コードの抜け等が不具合の原因と考えます。 申し訳ありませんでした。
- taka_tetsu
- ベストアンサー率65% (1020/1553)
> ((CModelessDlg *)m_pParent)->m_pTest = NULL; 本当にここで「'm_pTest' : 'CWnd' のメンバではありません。」がでましたか? こんなエラーは出るはず無いんですが。 >>想像はつきますが、どこにも記述がないので何ともいえません。 >以下のことでしたら、サンプルコードの中に記述が有りますが、、、 > >void CModelessDlg::EndTestDlg() >{ >m_pTest = NULL; > >} あ、あったんですか。別のurl見なかったもんで。 で、これ記述されてます? これが書いてあったらモードレスダイアログを一旦閉じて 開きなおしても新たに開くはずなんですけど。 CTestDlg::PostNcDestroy()の中にある、 ((CModelessDlg *)m_pParent)->EndTestDlg(); 消してないんですよね? >>親と子は1対多の関係なんですからCWnd::GetParent()で取得できます。 > >void CTestDlg::OnCancel() >{ > CWnd::GetParent()->m_pTest = NULL; >CDialog::OnCancel(); >} GetParent()は親のCWnd*を返します。 CWndのメンバにはm_pTestはないですよね。 このために、ここではキャストが必要になります。 ((CModelessDlg *)GetParent())->m_pTest = NULL; となります。 説明のために、CWnd::GetParent()と書きましたが、意味的には、CWndクラスのGetParentメソッドを呼び出してね。という意味です。 CTestDlgはCWndの派生クラスなので、自分でオーバーライドしていない限り、CWnd::を頭につけてスコープを指定する必要は無いですよ。
お礼
回答ありがとう御座います。 今時間が無いので気づいたことのみ報告します。 >CTestDlg::PostNcDestroy()の中にある、 >((CModelessDlg *)m_pParent)->EndTestDlg(); >消してないんですよね? もともとこの記述がないのですが、、、
- taka_tetsu
- ベストアンサー率65% (1020/1553)
>エラーは出ませんが、実行時にCTestDlgを一度閉じると、>再度表示されない問題が発生しました。 そりゃそうです。 // TODO: この位置に・・・ if( m_pTest == NULL) { m_pTest = new CTestDlg; m_pTest->Create(this); } else { m_pTest->BringWindowToTop(); } m_pTestがNULLならCreate、NULL以外だったら前面に表示という処理しかないんですから。 では、m_pTestがNULLになるのはいつ? やり方はいくらでもあるのでいろいろと試してください。 CModelessDlg::EndTestDlg()の実装がどこにもないのが 気になりますが。 #VitaminBBさんの見てるサンプル、どれも問題ありな気がするんですが・・・・ サンプル鵜呑みは止めましょうね。
お礼
回答ありがとうございます。 CTestDlgを破棄するときに、m_pTest = NULLとしたいのですが、'm_pTest' が定義されていないと言われてしまいます。 どう対処すれば良いのでしょうか?
- taka_tetsu
- ベストアンサー率65% (1020/1553)
>************************* >クラスウィザード(Ctrl+W)で、新規ダイアログを追加>します。 >クラス名をCTestDlgとします。 CModelessDlgクラスに>CTestDlgのデータメンバを追加します。 >(ヘッダーも追加してください) >************************* 参考urlに、上の記述の画面出てないですけど、具体的に どんな操作されました? その手順が問題ありだと思うのですが・・・
お礼
回答ありがとうございます。 再度プロジェクトを作り直したらうまく行きました。 特にヘッダーファイルのインクルード位置がポイントでした。 エラーは出ませんが、実行時にCTestDlgを一度閉じると、再度表示されない問題が発生しました。
お礼
いつも回答ありがとう御座います。 質問の仕方が悪く情報が足りないようで申し訳ありません。 以後気をつけます。 >m_pTestはサンプルどおりに作られているのでしたらCModelessDlgのメンバ変数ですよね。 サンプル通り作っています。 >CTestDlgを破棄するときというのは、どこのことを言っていますか? キャンセルボタンにて破棄しようとしています。 void CTestDlg::OnCancel() { m_pTest = NULL; CDialog::OnCancel(); } >m_pTestはCModelessDlgのメンバなので、単純にm_pTest = NULLとしてもだめなのは分かりますか? 一応分かっているつもりです。 CModelessDlgのm_pTestを取得するにどうすればよいか。と質問すべきでした。 void CTestDlg::OnCancel() { ((CModelessDlg *)m_pParent)->m_pTest = NULL; CDialog::OnCancel(); } このように変更してみましたが、'm_pTest' : 'CWnd' のメンバではありません。とエラーがでます。 >これでもいいのですが、オブジェクト指向の考え方だと、 >通常、外部からはメンバ変数は直接操作させません。 >メソッドや、プロパティといったものを経由してアクセスさせます。 考え方は理解しているつもりです。しかし、今回は勉強のためにこの方法でやりたいです。 >((CModelessDlg *)m_pParent)->EndTestDlg(); >の記述で呼び出しているCModelessDlg::EndTestDlg()が >m_pTestをNULLにするためのメソッドなのかな?と >想像はつきますが、どこにも記述がないので何ともいえません。 以下のことでしたら、サンプルコードの中に記述が有りますが、、、 void CModelessDlg::EndTestDlg() { m_pTest = NULL; } >親と子は1対多の関係なんですからCWnd::GetParent()で取得できます。 void CTestDlg::OnCancel() { CWnd::GetParent()->m_pTest = NULL; CDialog::OnCancel(); } このように変更してみましたが、'm_pTest' : 'CWnd' のメンバではありません。とエラーがでます。 ということで、まだうまく行っていません。基本的に親ウィンドウのハンドルを取得する方法が 良く判っていません。さらにアドバイス頂けると大変助かります。