OKWAVEのAI「あい」が美容・健康の悩みに最適な回答をご提案!
-PR-
締切り
済み

MFC、ダイアログベースでのモードレス作成

  • すぐに回答を!
  • 質問No.125205
  • 閲覧数4425
  • ありがとう数7
  • 気になる数0
  • 回答数6
  • コメント数0

お礼率 66% (4/6)

現在、MFCで検索プログラムを作成しています。
始めはDoModalで作成していたのですが、ダイアログを閉じずに、ダイアログを複数並べて見たいという意見が出た為、モードレスで作成し直そうとしたところ、ダイアログが現れてくれません。
インターネットで見つけたソースを試してみたのですが、上手くいきません。
どなたか教えて頂けますか?

=ダイアログに移るボタンコードに=

CDlg1 dlg;
dlg.Create(IDD_DIALOG1, this);
dlg.ShowWindow(SW_SHOW);

(dlg.DestroyWindow();は他に記述)


1.
上記では、ShowWindowに0が返ってしまい、一瞬ダイアログが映って
消えてしまいます。Createは1が返ってるのでいいかと思いますが…。

2.
あと、違うソースで試したところ、ダイアログは表示できるものの、
一回消してしまうと、もう一度ボタンを押しても再度は表示されません。
しかも、Destroy()を設定したOKボタンでは強制終了となってしまいます。

モードレスで作成すると、一回そのダイアログを消してしまうと再度表示ができないのでしょうか?
モードレスってただ他の処理ができるというだけで、そのダイアログを何枚も表示させておくことはできないのでしょうか?

3.
このダイアログにjpegファイルを表示させているのですが、ダイアログベース・htmlView以外で表示させれる方法がありましたら教えて下さい。

よろしくお願いします。
通報する
  • 回答数6
  • 気になる
    質問をブックマークします。
    マイページでまとめて確認できます。

回答 (全6件)

  • 回答No.2
レベル12

ベストアンサー率 45% (210/459)

こんにちは。itohhといいます。 モードレスで作成するのは、結構めんどくさいですよ。 (どのタイミングでWindowを作るのかとか、消す方法は?とか。) サンプルを作成しようかとも思いましたが、 解説しているHPがありますので、そちらを参照してください。 URL:http://www2s.biglobe.ne.jp/%7Emaekawa/dev/vc/dialog/index.html ...続きを読む
こんにちは。itohhといいます。

モードレスで作成するのは、結構めんどくさいですよ。
(どのタイミングでWindowを作るのかとか、消す方法は?とか。)

サンプルを作成しようかとも思いましたが、
解説しているHPがありますので、そちらを参照してください。
URL:http://www2s.biglobe.ne.jp/%7Emaekawa/dev/vc/dialog/index.html
お礼コメント
hatch13

お礼率 66% (4/6)

早速の回答、ありがとうございます!!

教えて頂いたHPのソースで作ってみたら、上手くいきました!
解り易いHPですね!

ただ、同じダイアログを複数表示したかったので、
表示の際のif文3つ{ return;}のところ、削除しました。
今のところ問題は無さそうなのですが、このif文は何の為にあるのでしょうか?
投稿日時 - 2001-08-28 22:08:21
  • 回答No.1
レベル8

ベストアンサー率 44% (11/25)

ダイアログクラスの実体がローカル変数として宣言されているので、その関数を抜けた時点でウィンドウとメモリが破棄されているだけでは? この場合はCDlg1型ポインタをメンバ変数で用意しておき、newでインスタンスを得るのが一般的だと思います。 (ダイアログが不要になった場合は、DestroyWindow()後、deleteで破棄します。) モードレスダイアログを何枚も開く場合は、ポインタ変数の管理が必要 ...続きを読む
ダイアログクラスの実体がローカル変数として宣言されているので、その関数を抜けた時点でウィンドウとメモリが破棄されているだけでは?
この場合はCDlg1型ポインタをメンバ変数で用意しておき、newでインスタンスを得るのが一般的だと思います。
(ダイアログが不要になった場合は、DestroyWindow()後、deleteで破棄します。)
モードレスダイアログを何枚も開く場合は、ポインタ変数の管理が必要ですね。

JPEGファイル表示のほうはネット上にライブラリやソースが落ちてるので、それを参考に自前で表示処理を書いてあげれば可能だと思います。
お礼コメント
hatch13

お礼率 66% (4/6)

早速の回答ありがとうございます!!

仰る通り、ローカル変数が原因でした。

CDlg1* dlg;        とグローバル変数にし、
dlg = new CDlg1(this);
dlg->ShowWindow(SW_SHOW); としたら上手くいきました!

このやり方が一般的と考えていいのでしょうか?

>モードレスダイアログを何枚も開く場合は、ポインタ変数の管理が必要ですね。

これは、グローバル変数のところで、dlg[10]のように枚数分設定しておくという
ことなのでしょうか?

ポインタがイマイチよく解っていないので、申し訳ありませんが教えて頂けますでしょうか?
投稿日時 - 2001-08-28 22:16:34
  • 回答No.3
レベル12

ベストアンサー率 45% (210/459)

こんにちは。itohhといいます。 動きましたか。良かったですね。(^_^)v >表示の際のif文3つ{ return;}のところ、削除しました。 これのことでしょうか? if(pDlgMless->GetSafeHwnd()) {   if(::IsWindow(pDlgMless->m_hWnd)) {     if(pDlgMless->IsWindowVi ...続きを読む
こんにちは。itohhといいます。

動きましたか。良かったですね。(^_^)v

>表示の際のif文3つ{ return;}のところ、削除しました。
これのことでしょうか?
if(pDlgMless->GetSafeHwnd()) {
  if(::IsWindow(pDlgMless->m_hWnd)) {
    if(pDlgMless->IsWindowVisible()) {
        //破棄部分pDlgMless->DestroyWindow();
        return;
        // returnで脱出しているのに注意。
    }
  }
}
これは一度、作成されている場合は再作成しないためです。
ですので、これを削除してしまうと、このあとにある
//生成部分
pDlgMless=new CDlgMless(this);
pDlgMless->ShowWindow(SW_SHOW);

で、一つの変数に2個、3個と上書きしていきますからメモリーリークを起こしますよ。
(deleteすることが出来なくなると言うことです。)

(注)関数はMSDNライブラリを参照しましょう。
お礼コメント
hatch13

お礼率 66% (4/6)

返答ありがとうございます!
お礼が遅くなってしまって申し訳ありません。

一難去ってまた一難ってかんじです..。(;_;)

>で、一つの変数に2個、3個と上書きしていきますからメモリーリークを起こし>ますよ。
>(deleteすることが出来なくなると言うことです。)

この場合、どうしたらいいのでしょうか??

漠然とした質問で申し訳ありません…。
実はまだプログラムを始めたばかりで、何がどうなっているのか
解らない状態です。

ダイアログを作る度に、変数のアドレスが移動して、deleteできないっていう理解でいいのでしょうか?
今、子ダイアログのほうにdeleteが設定してあるのですが、どこにdeleteを設定していようと、変数が一つなら必ずメモリーリークが起きるということでしょうか?
投稿日時 - 2001-09-01 01:47:06
  • 回答No.4
レベル8

ベストアンサー率 44% (11/25)

> このやり方が一般的と考えていいのでしょうか? newで実体を得る方法が一般的ですが、ポインタ変数をグローバル化してしまうのはお行儀が悪い気がします。 グローバル変数ではなく、親ウィンドウ(ダイアログ?)クラスのメンバ変数にしてしまうのがスマートではないかと思います(^_^; > これは、グローバル変数のところで、dlg[10]のように枚数分設定しておくということなのでしょ ...続きを読む
> このやり方が一般的と考えていいのでしょうか?

newで実体を得る方法が一般的ですが、ポインタ変数をグローバル化してしまうのはお行儀が悪い気がします。
グローバル変数ではなく、親ウィンドウ(ダイアログ?)クラスのメンバ変数にしてしまうのがスマートではないかと思います(^_^;


> これは、グローバル変数のところで、dlg[10]のように枚数分設定しておくということなのでしょうか?

あらかじめ枚数が分かっているならそれでも良いと思います。その場合は、枚数の上限を超えて開かれないようにチェックしないといけませんね。
枚数が不定の場合にはリスト構造等でポインタ変数を動的に管理すれば可能だと思います。

要は作ったダイアログ(自分で確保したメモリ)全てを、終了時に確実に破棄できれば良いだけなので、自分で管理しやすいデータ構造を選べばいいと思いますよ。
お礼コメント
hatch13

お礼率 66% (4/6)

返答ありがとうございます!
お礼が遅くなってしまって申し訳ありません。

>グローバル変数ではなく、親ウィンドウ(ダイアログ?)クラスのメンバ変数にして>しまうのがスマートではないかと思います(^_^;

すいません、ついついグローバル変数と書いてしまいました。(・・;
メンバ変数のことですよね。
ローカルにしたり、グローバルと言ったり…。

あまりに知らなくて申し訳ないのですが、
リスト構造、データ構造…今の私のレベルからだとかなり難しいことのように
思えます。

枚数を決めてみたものの、変数が登場する度に[]の中の数字をどうするのか
??です。[]の中にint型変数をいれて管理するのでしょうか?? 
投稿日時 - 2001-09-01 02:13:54
  • 回答No.5
レベル12

ベストアンサー率 45% (210/459)

こんにちは。itohhといいます。 その後、進展はありましたか? もし、まだ悩んでいるようでしたら、子ダイアログのオブジェクトを配列で持つときの注意点を。 1.上限を決めたとき、それ以上はダイアログが表示されないようにする。 2.子ダイアログを閉じたとき、配列のどの位置のオブジェクトを削除するかわかるようにする。 3.親ウィンドウが終了するときには、子ダイアログはすべて閉じてオブジェクト ...続きを読む
こんにちは。itohhといいます。

その後、進展はありましたか?

もし、まだ悩んでいるようでしたら、子ダイアログのオブジェクトを配列で持つときの注意点を。
1.上限を決めたとき、それ以上はダイアログが表示されないようにする。
2.子ダイアログを閉じたとき、配列のどの位置のオブジェクトを削除するかわかるようにする。
3.親ウィンドウが終了するときには、子ダイアログはすべて閉じてオブジェクトもすべて
  削除しなければいけない。

大まかに注意事項を上げるとするとこんなところでしょうか。
配列で管理する場合、配列の添字の管理が難しいと思います、配列の何番目がどの子ダイアログ
なのかとか、配列の空きはあるのかとかです。
配列の代わりとしてCObArrayクラスから派生させてコレクションにするという手もあります。


わからないところがあれば再度、補足をしてください、出来る範囲でお手伝いしますよ。

これからも頑張ってください。
  • 回答No.6
レベル8

ベストアンサー率 60% (21/35)

もし作成したダイアログのポインタを削除する為だけにポインタ配列を用意する のでしたら変わりにこんな方法もあります。 CMyDialog::PostNcDestroy()をオーバーライド CMyDialog::PostNcDestroy() { CDialog::PostNcDestroy(); delete this; } こうすればモードレスダイアログが閉じられた時に ...続きを読む
もし作成したダイアログのポインタを削除する為だけにポインタ配列を用意する
のでしたら変わりにこんな方法もあります。

CMyDialog::PostNcDestroy()をオーバーライド
CMyDialog::PostNcDestroy()
{
CDialog::PostNcDestroy();

delete this;
}

こうすればモードレスダイアログが閉じられた時に自動でメモリも削除されるし
楽かなと思いますけど。
とりあえず参考まで...
このQ&Aのテーマ
このQ&Aで解決しましたか?
関連するQ&A
-PR-
-PR-
こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する
-PR-
-PR-
-PR-

特集


いま みんなが気になるQ&A

関連するQ&A

-PR-

ピックアップ

-PR-
ページ先頭へ