• 締切済み

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

現在、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以外で表示させれる方法がありましたら教えて下さい。 よろしくお願いします。

みんなの回答

  • akinori_s
  • ベストアンサー率60% (21/35)
回答No.6

もし作成したダイアログのポインタを削除する為だけにポインタ配列を用意する のでしたら変わりにこんな方法もあります。 CMyDialog::PostNcDestroy()をオーバーライド CMyDialog::PostNcDestroy() { CDialog::PostNcDestroy(); delete this; } こうすればモードレスダイアログが閉じられた時に自動でメモリも削除されるし 楽かなと思いますけど。 とりあえず参考まで...

  • itohh
  • ベストアンサー率45% (210/459)
回答No.5

こんにちは。itohhといいます。 その後、進展はありましたか? もし、まだ悩んでいるようでしたら、子ダイアログのオブジェクトを配列で持つときの注意点を。 1.上限を決めたとき、それ以上はダイアログが表示されないようにする。 2.子ダイアログを閉じたとき、配列のどの位置のオブジェクトを削除するかわかるようにする。 3.親ウィンドウが終了するときには、子ダイアログはすべて閉じてオブジェクトもすべて   削除しなければいけない。 大まかに注意事項を上げるとするとこんなところでしょうか。 配列で管理する場合、配列の添字の管理が難しいと思います、配列の何番目がどの子ダイアログ なのかとか、配列の空きはあるのかとかです。 配列の代わりとしてCObArrayクラスから派生させてコレクションにするという手もあります。 わからないところがあれば再度、補足をしてください、出来る範囲でお手伝いしますよ。 これからも頑張ってください。

  • bir
  • ベストアンサー率44% (11/25)
回答No.4

> このやり方が一般的と考えていいのでしょうか? newで実体を得る方法が一般的ですが、ポインタ変数をグローバル化してしまうのはお行儀が悪い気がします。 グローバル変数ではなく、親ウィンドウ(ダイアログ?)クラスのメンバ変数にしてしまうのがスマートではないかと思います(^_^; > これは、グローバル変数のところで、dlg[10]のように枚数分設定しておくということなのでしょうか? あらかじめ枚数が分かっているならそれでも良いと思います。その場合は、枚数の上限を超えて開かれないようにチェックしないといけませんね。 枚数が不定の場合にはリスト構造等でポインタ変数を動的に管理すれば可能だと思います。 要は作ったダイアログ(自分で確保したメモリ)全てを、終了時に確実に破棄できれば良いだけなので、自分で管理しやすいデータ構造を選べばいいと思いますよ。

hatch13
質問者

お礼

返答ありがとうございます! お礼が遅くなってしまって申し訳ありません。 >グローバル変数ではなく、親ウィンドウ(ダイアログ?)クラスのメンバ変数にして>しまうのがスマートではないかと思います(^_^; すいません、ついついグローバル変数と書いてしまいました。(・・; メンバ変数のことですよね。 ローカルにしたり、グローバルと言ったり…。 あまりに知らなくて申し訳ないのですが、 リスト構造、データ構造…今の私のレベルからだとかなり難しいことのように 思えます。 枚数を決めてみたものの、変数が登場する度に[]の中の数字をどうするのか ??です。[]の中にint型変数をいれて管理するのでしょうか?? 

  • itohh
  • ベストアンサー率45% (210/459)
回答No.3

こんにちは。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
質問者

お礼

返答ありがとうございます! お礼が遅くなってしまって申し訳ありません。 一難去ってまた一難ってかんじです..。(;_;) >で、一つの変数に2個、3個と上書きしていきますからメモリーリークを起こし>ますよ。 >(deleteすることが出来なくなると言うことです。) この場合、どうしたらいいのでしょうか?? 漠然とした質問で申し訳ありません…。 実はまだプログラムを始めたばかりで、何がどうなっているのか 解らない状態です。 ダイアログを作る度に、変数のアドレスが移動して、deleteできないっていう理解でいいのでしょうか? 今、子ダイアログのほうにdeleteが設定してあるのですが、どこにdeleteを設定していようと、変数が一つなら必ずメモリーリークが起きるということでしょうか?

  • itohh
  • ベストアンサー率45% (210/459)
回答No.2

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

参考URL:
http://www2s.biglobe.ne.jp/%7Emaekawa/dev/vc/dialog/index.html
hatch13
質問者

お礼

早速の回答、ありがとうございます!! 教えて頂いたHPのソースで作ってみたら、上手くいきました! 解り易いHPですね! ただ、同じダイアログを複数表示したかったので、 表示の際のif文3つ{ return;}のところ、削除しました。 今のところ問題は無さそうなのですが、このif文は何の為にあるのでしょうか?

  • bir
  • ベストアンサー率44% (11/25)
回答No.1

ダイアログクラスの実体がローカル変数として宣言されているので、その関数を抜けた時点でウィンドウとメモリが破棄されているだけでは? この場合はCDlg1型ポインタをメンバ変数で用意しておき、newでインスタンスを得るのが一般的だと思います。 (ダイアログが不要になった場合は、DestroyWindow()後、deleteで破棄します。) モードレスダイアログを何枚も開く場合は、ポインタ変数の管理が必要ですね。 JPEGファイル表示のほうはネット上にライブラリやソースが落ちてるので、それを参考に自前で表示処理を書いてあげれば可能だと思います。

hatch13
質問者

お礼

早速の回答ありがとうございます!! 仰る通り、ローカル変数が原因でした。 CDlg1* dlg;        とグローバル変数にし、 dlg = new CDlg1(this); dlg->ShowWindow(SW_SHOW); としたら上手くいきました! このやり方が一般的と考えていいのでしょうか? >モードレスダイアログを何枚も開く場合は、ポインタ変数の管理が必要ですね。 これは、グローバル変数のところで、dlg[10]のように枚数分設定しておくという ことなのでしょうか? ポインタがイマイチよく解っていないので、申し訳ありませんが教えて頂けますでしょうか?

関連するQ&A

  • SendMessage();の使い方

    よろしくお願いします。 <環境> WIN98 VC++6.0 MFC SDIにてウィンドウをクリックすると、モードレスダイアログ1とモーダルダイア ログ2が開くようにしました。 void CMy222View::OnLButtonDown(UINT nFlags, CPoint point) { CDlg1 *dlg; dlg = new CDlg1; dlg->Create(IDD_DIALOG1); dlg->ShowWindow(SW_SHOW); CDlg2 dlg2; dlg2.DoModal(); CView::OnLButtonDown(nFlags, point); } ダイアログ2のボタン押し下げにてダイアログ1のボタン1を押し下げたいのですが 、どのようにすれば実現できるのでしょうか? void CDlg2::OnButton2() { SendMessage(); //■ここの書き方が分かりません CDialog::OnOK(); } 宜しくお願いいたします。

  • 複数のダイアログの作成について

    環境 WIN98 VC++6.0 MFC SDIにて 1.メニューの”ダイアログ作成”をクリックすると、 void CMainFrame::OnKNew() { CInput dlg; int iID = dlg.DoModal(); } として、ダイアログを作成します。 2.次に、ダイアログのボタン押し下げにてダイアログを非表示にします。 void CInput::OnButton1() { ShowWindow(SW_HIDE); } このようなコードにおいて、一旦非表示にした後で、また”ダイアログ作成”メニューにてダイアログを作成した場合、 1.これは新たに2個目のダイアログが作られたのでしょうか? 2.それとも、単に最初に作られたダイアログが非表示から表示状態になっただけでしょうか? 3.それとも、最初のダイアログの上に2個目のダイアログが上書きされてしまうのでしょうか? 以上よろしくお願いします。

  • (MFC)別々のプロジェクト内で作成したダイアログを表示させる方法

    VC++2005のMFCにてアプリケーションを作成しています。 一つのソリューション内に二つのプロジェクトA、Bが存在し、 プロジェクトAで発生したあるイベント(例:ボタン押下)にて、 プロジェクトBで作成したダイアログを表示させたいのですが、 実装したところ、下記コンパイルエラーが出てしまいます。 「error C2065: 'IDD_TEST2_DIALOG' : 定義されていない識別子です。」 現在のプロジェクトの設定としては、 ・プロジェクトAの依存先をプロジェクトBに設定 ・プロジェクトA選択状態で、  「プロジェクト」→「プロパティ」→「構成プロパティ」  →「C/C++全般」→「追加のインクルードディレクトリ」にて、プロジェクトBのパスを指定 と設定しているのですが、どこに問題があるのでしょうか? もし問題があるようでしたら、正しい設定方法、また実装方法について、 お手数おかけしますが、ご教授お願いできませんでしょうか? また下記にソースコード実装例を記載します。 【プロジェクトA(呼び出し側)】 #include "test2Dlg.h" //プロジェクトBのヘッダファイル ・・・ void Ctest1Dlg::OnBnClickedOk() { CDlgTest MyDlg; MyDlg.DoModal(); //プロジェクトBのダイアログ生成 } 【プロジェクトB(呼出され側)】 ・リソースビューにて、ダイアログ(IDD_TEST2_DIALOG)の「クラスの追加」で、  クラス名「CDlgTest」と指定

  • ダイアログの表示、非表示の切り替えについて

    環境 WIN98 VC++6.0 MFC SDIにて 1.ポップアップメニューの”ダイアログ作成”をクリックすると、 void CMainFrame::OnKNew() { CInput dlg; int iID = dlg.DoModal(); } として、ダイアログを作成します。 2.次に、ダイアログのボタン押し下げにてダイアログを非表示にします。 void CInput::OnButton1() { ShowWindow(SW_HIDE); } このようなコードにおいて、非表示状態での”ダイアログ作成”クリックでは非表示から表示に切り替えることを実現するにはどのようにすれば良いのでしょうか? よろしくお願いいたします。

  • OnDestroy() について

    環境 WIN98 VC++6.0 MFC SDIにて アプリ起動と同時にダイアログを表示しています。 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { 略 dlg = new CInput(this); dlg->Create(IDD_DIALOG1); dlg->ShowWindow(SW_SHOW); return 0; } <質問1> このような場合に、CInputクラスに以下のようにOnDestroy()を追加しましたが、 ダイアログを閉じた時もアプリ終了時にもメッセージが飛んできません。 どうしてなのですか? void CInput::OnDestroy() { CDialog::OnDestroy(); AfxMessageBox("789"); } <質問2> 更に、以下のように新規にダイアログバーを追加したところ、メッセージが飛ぶようになりました。 どうしてなのでしょうか? int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { 略 if (!m_wndMyDialogBar.Create(this, CG_IDD_MYDIALOGBAR, WS_VISIBLE , CG_ID_VIEW_MYDIALOGBAR)) { TRACE0("Failed to create dialog bar m_wndMyDialogBar\n"); return -1; // 作成に失敗 } dlg = new CInput(this); dlg->Create(IDD_DIALOG1); dlg->ShowWindow(SW_SHOW); return 0; }

  • DLLでダイアログ

    VC++6.0にてMFCを使うDLLを作成しています。 関連HPを参考になんとかDLLを作ることが出来ました。 そこで今度はDLL側でダイアログボックスを作成して表示させようとしたところうまくいきません。 エラーも無くスルーされてしまいます。 こういう使い方は出来ないのでしょうか。 ↓DLL関数のソースファイルです。 ---------------------------------------------- #include "StdAfx.h" #include "Defs.h" #include "Func.h" #include "resource.h" #include "testdlg.h" #include "dlg2.h" int WINAPI DllFunc( CString &p_rcStr, CWnd *p_pcWnd ) { TestDlg dlg; Cdlg2 dlg2; dlg.ps = p_rcStr; dlg2.DoModal();//なにも出ない AfxMessageBox(p_rcStr);//コレはOK dlg.DoModal();//何もでない return TRUE; } --------------------------------------------

  • windowを常に手前にしたい。

    すみません。教えてください。 [環境] windows2000 visual c++6.0 [内容] 親ウインドウから子ウインドウを呼び出して、常に子ウインドウを手前にし、かつ常にアクティブにしたいのですが、うまくいきません。 [ソース] 親ウインドウ : : : CSysCp02Dlg2* frm02Dlg; frm02Dlg = new CSysCp02Dlg2(); frm02Dlg->Create(IDD_SYSCP02_DIALOG,NULL); frm02Dlg->ShowWindow(SW_SHOW); : : (裏で処理をする) :  delete frm02Dlg; (処理の終了) [ソース]子ウインドウ : : :  this->SetActiveWindow();  this->SetWindowPos(&wndTop,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE); : : : イメージ的には、DoModalで子ウインドウを表示し、裏の親ウインドウで処理をしたいのです。(もちろんDoModalでは無理なので、Createをしていますが....) どなたかご存知の方いらっしゃいましたら、ご教授お願いいたします。

  • 連続してダイアログを表示したい?

    VC++6.0を使用しています。 以下のようなコードでダイアログを連続して表示しようと思っています。1番目のダイアログを表示してOKボタンを押下後(このときこのダイアログは消えて)、2番目のダイアログを表示したいと思っているのですが2番目が表示できません。(1番目のところをコメントにすれば2番目は表示できます。)どうして2番目のダイアログが表示できないのでしょうか? // 1番目のダイアログ   CTest1Dlg dlg;   m_pMainWnd = &dlg;   int nResponse1 =dlg.DoModal(); // 2番目のダイアログ   CTest2Dlg dlg;   m_pMainWnd = &dlg;   int nResponse2 =dlg.DoModal(); //   if (nResponse1 == IDOK) {   :以下省略 これだけの情報でアドバイスができますでしょうか? すみません。よろしくお願い致します。

  • ダイアログを終了させてもハンドルが1つ増加したまま。。。

    VC++のMFCを使ってダイアログベースのEXEを造っています。 ハンドルのリークが発生し、困っています。 <動作内容> メインのダイアログで、ボタン押下により別のダイアログを表示します。 DoModal()でモーダルダイアログを作成します。 別のプロセスからブロードキャストされるメッセージを処理したいため、 ボタン押下のルーチンで DoModal() せずに、スレッドを作成し、 そのスレッドで DoModal() を実行しています。 スレッド作成は AfxBeginThread() を使用しています。 <サンプルソース> ●メインダイアログ // ボタン押下のルーチン void CTestModalDlg::OnButton1() { AfxBeginThread( TestDlgThread, (LPVOID)this, THREAD_PRIORITY_NORMAL ); } // スレッド static UINT TestDlgThread(LPVOID pThis) { CTestDlg1 Dlg; Dlg.DoModal(); } ●DoModal() で表示されるダイアログ 何も手を加えてない、デフォルトのまま。 <結果> DoModal() で表示されたダイアログを CDialog::OnCancel() で終了させ、 メインのスレッドが終了しても、ハンドルカウントが1つ増加しています。 Sleep() を入れて値をみてみると、 ・スレッド作成:2増加 ・DoModal() でダイアログ表示:1増加 ・OnCancel() で終了:増減なし ・スレッド終了:2減少 =>結果、1増加となっていました。 以下のパターンでは問題ありませんでした。 ・スレッドを作成+終了(ダイアログ表示しない) ・スレッドを作成せずに、ボタン押下ルーチンから DoModal() でダイアログ表示+終了 ということで、AfxBeginThread()、DoModal() 自体は問題ないのですが、 スレッドを作成して DoModal() するとリークが発生します。 識者の方、原因、対策など、ご教授願います。

  • 非表示のメインウィンドウを表示させるには?

    環境 WIN98 VC++6.0 MFC SDIにて タスクトレイに常駐するアプリにおいて 1.起動時にメインウィンドウを非表示にしています。 2.起動時と同時にダイアログを表示しています。 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { 略 dlg = new CInput(this); dlg->Create(IDD_DIALOG1); dlg->ShowWindow(SW_SHOW); return 0; } 3.このような場合に、ダイアログのボタン押し下げにて、メインウィンドウを表示させるには、どうすれば良いでしょうか? 以下のようにしてみましたが、不正な処理で落ちてしまいます。 void CInput::OnButton1() { CWnd* mywnd = (CWnd*)GetParent(); mywnd->ShowWindow(SW_SHOW); }

専門家に質問してみよう