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

このQ&Aのポイント
  • ダイアログの表示と非表示を切り替える方法について
  • ウィンドウの非表示状態から表示状態に切り替える方法について
  • ダイアログの非表示と表示を切り替える方法について
回答を見る
  • ベストアンサー

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

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

質問者が選んだベストアンサー

  • ベストアンサー
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.2

モーダルだとなぜいけないかを書いてなかったですね。 別にMFCだからとかそんな理由ではないですよ。 スレッドが止まるとかいうことでもないですし。 理由:dlg.DoModal()の時点で、CMainFrame::OnKNew()の処理が止まっているから。 ここでさらなる疑問が出るでしょう。 なぜ、 CMainFrame::OnKNew()を複数回呼び出すと、処理が止まっているにもかかわらず新しいダイアログが表示されてしまうのか? 理由:CMainFrame::OnKNew()は止まっていると言ったが、 プログラム中にあるメッセージループはどこかで動いているからメッセージは受け取れる。 そして、最初と同様、dlg.DoModal()を呼び出すと処理は停止します。 ロックがかかっていても、メッセージを受け取れるというのは、当然といえば当然です。 描画のメッセージが受け取れなくなったら親ウィンドウの描画ができなくなってしまいますからね。 では、どうして呼び出し中の関数があるのにそんなことが可能なのでしょうか? 理由:CやC++の関数は、再帰呼び出しが可能だから です。 つまり、モーダルウィンドウが表示されている間でも、メッセージはシステムから(若しくは今回のように明示的にでも)飛んできます。 PostMessageで送られてきたものはメッセージキューにためられた後DispatchMessageから、SendMessageで送られたものは直接ウィンドウプロシージャが呼び出されます。 このとき、前回コールされて止まったままとなっている CMainFrame::OnKNew()の呼び出し元となっているウィンドウプロシージャはスタックにためられます。 前回の呼び出し分がスタックにためられるから、後から呼ばれたプロシージャは何事もなかったかのように動作することが出来ます。 ということで、 CInput dlg; がいくつも存在するかのように見える状態は、異常ではありません。スタックに詰まれていることになります。 実際には、オブジェクトが存在するアドレスが違います。 アドレスが違うということは、区別することも可能ですよね。 メンバ変数を上手く使えば確認できますよ。 ちなみに、スタックには限度というものがあるので。あまりやりすぎるとスタックオーバーフローで落ちます。 #確認したいのであれば、メッセージハンドラの中で同じメッセージSendすればすぐにできますよ(^^;

VitaminBB
質問者

お礼

>モーダルだとなぜいけないかを書いてなかったですね。 これ聞きたかったけど躊躇してました。察していただき感謝です。 >なぜ、 CMainFrame::OnKNew()を複数回呼び出すと、処理>が止まっているにもかかわらず新しいダイアログが表示さ>れてしまうのか? まさにこれが疑問でした。 >理由:CやC++の関数は、再帰呼び出しが可能だからです。 再帰ですか。これ始めて知ったとき凄く不可解でした。 だって、肉屋はどこ?八百屋のとなり。八百屋はどこ?肉屋のとなり。以下この繰り返し。みたいに感じたから。 >前回の呼び出し分がスタックにためられるから、後から呼ばれたプロシージャは何事もなかったかのように動作することが出来ます。 そうだったのですか。ようやく納得です。 >メンバ変数を上手く使えば確認できますよ。 これは確認できました。 >#確認したいのであれば、メッセージハンドラの中で同じメッセージSendすればすぐにできますよ(^^; メッセージSendする???良く分かりませんが、今となっては必要ないかな。。。 #今回の話は凄く面白かったです。また、お願いします。m(__)m

その他の回答 (2)

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.3

>再帰ですか。これ始めて知ったとき凄く不可解でした。 >だって、肉屋はどこ?八百屋のとなり。八百屋はどこ? >肉屋のとなり。以下この繰り返し。みたいに感じたから。 たしかに、いいサンプルがないと分かりづらいですね。 概念的にはバックトラック、いわゆる”しらみつぶし”ですね。 よく例に出されるのがチェスのナイトが一筆書きですべての64マスをまわれるかとか。 個人的には、ドライブのフォルダに含まれるファイルを順に列挙していくようなプログラムを作るのが分かりやすいと思います。 >メッセージSendする???良く分かりませんが、今となっては必要ないかな。。。 Windowsプログラムを組む上で、PostとSendの違いは重要です。 ちなみにPostとは、PostMessage()でメッセージ送信、SendとはSendMessage()でメッセージ送信です。 ここのサイトでも、よく使い方を間違ってる人を見ます。 たとえば、下の2つ、落ちずに1000000回メッセージが送られるのはどっち? ということです。 CMyWnd::OnLButtonDown(UINT nFlags, CPoint point) { if(m_iCount < 1000000 ) { SendMessage(WM_LBUTTONDOWN, 0, 0); m_iCount++; } } CMyWnd::OnLButtonDown(UINT nFlags, CPoint point) { if(m_iCount < 1000000 ) { PostMessage(WM_LBUTTONDOWN, 0, 0); m_iCount++; } } ちなみに、m_iCountはCMyWndのメンバ変数で、コンストラクタで初期化しておいてくださいね。

VitaminBB
質問者

お礼

ようやくやってみましたが、どちらも落ちませんでした。 理屈上落ちるのは、PostMessageだと思いますが、どうでしょうか?

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

モーダルで作ることがNGです。 モードレスで作りましょう。 いちばん簡単なのは、あらかじめ非表示作っておき、 非表示にしておきます。 そして、タスクトレイからメッセージがきたら表示してあげる、ボタンが押されたら非表示にする、とすれば問題ないでしょう。

VitaminBB
質問者

お礼

回答ありがとうございます。 モーダルで一応作ってみました。 ポインタがNULLかどうかの判定でうまく行きました。 と思ったらモーダルはNGとのことなので、モードレスに変更しました。 ところが、モーダルの作り方が分からないし、起動時に作っておいて非表示する方法がわからない。ということで色々やってみてようやくで出来ました。 以上報告です。

関連するQ&A

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

    環境 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個目のダイアログが上書きされてしまうのでしょうか? 以上よろしくお願いします。

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

    環境 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); }

  • ダイアログの再表示について

    宜しくお願いします。 <環境> WIN98 VC++6.0 MFC  ダイアログのボタン押し下げでウィンドウを生成し、 生成後はダイアログを非表示にしています。 void CInput::OnButton1()//ウィンドウの生成 { UpdateData (TRUE); pWnd = new CMyWnd( this); pWnd->m_left=100; pWnd->m_top=100; m_pAryDlg.Add ( pWnd ); //m_pAryDlg2.Add ( &m_InputData ); pWnd->m_moji=m_InputData; pWnd->Kado_Create(this); ShowWindow(SW_HIDE); //ダイアログの非表示 } ウィンドウをダブルクリックすると、ダイアログが非表示から 表示になるように以下のコードを書きましたが、表示されません。 どのようにすれば表示されるようになりますか? void CMyWnd::OnLButtonDblClk(UINT nFlags, CPoint point)  //ウィンドウのダブルクリック { CInput* pInput = (CInput*)GetParent(); // CInputは親ダイアログのクラス pInput->ShowWindow(SW_SHOW); CWnd::OnLButtonDblClk(nFlags, point); }

  • 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(); } 宜しくお願いいたします。

  • フォームの再表示について

    VC++初心者です。 ダイアログベースのアプリケーションをつくったんですが、その後ボタンクリックでモーダルダイアログを2つ順番に表示したいと思っています。 void CMFC_testDlg::OnBnClickedButton1() {   CmyDialog myDL;   ret1 = myDL.DoModal(); } で一つ目を表示 void CmyDialog::OnBnClickedOk() {   this->ShowWindow(SW_HIDE);   CmyDialog02 myDL02;   myDL02.DoModal(); } で一つ目を隠して、2つ目を表示 さらに2つ目のダイアログのボタンを押した時、2つ目を閉じて1つ目を再表示したいと思います。 void CmyDialog02::OnBnClickedOk() {   EndDialog(-1);   CmyDialog::ShowWindow(SW_SHOW); } と書いた所エラーになります。 どこがまずいんでしょうか。 エラーメッセージ:静的でないメンバ関数の呼び出しが正しくありません VBになれてしまっているため、C++の文法でどう書いていいのかわかりません。 どなたかお教えください。

  • 子ウィンドウから親ウィンドウへデータを渡すには?

    宜しくお願いします。 <環境> WIN98 VC++6.0 MFC  ダイアログのボタン押し下げでウィンドウを生成し、ダイアログのテキストボックスに入力した文字をウィンドウに表示しています。 また、ウィンドウ生成後はダイアログを非表示にしています。 void CInput::OnButton1()//ウィンドウの生成 { UpdateData (TRUE); pWnd = new CMyWnd( this); pWnd->m_moji=m_InputData; //テキストボックスの文字をウィンドウに表示されるう変数m_mojiに代入 pWnd->Kado_Create(this); ShowWindow(SW_HIDE); //ダイアログの非表示 } ウィンドウをダブルクリックすると、ダイアログを非表示から表示にし、ウィンドウに表示されている文字をダイアログのテキストボックスに表示させるために以下のようにしましたが、文字は表示されません。 どのようにすれば表示されるようになりますか? void CMyWnd::OnLButtonDblClk(UINT nFlags, CPoint point) { CInput* pInput = (CInput*)GetParent(); // CInputは親ダイアログのクラス pInput->m_InputData=m_moji;//変数に正しい文字が代入されていることは確認できました UpdateData(FALSE); pInput->ShowWindow(SW_SHOW); CWnd::OnLButtonDblClk(nFlags, point); }

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

    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) {   :以下省略 これだけの情報でアドバイスができますでしょうか? すみません。よろしくお願い致します。

  • ダイアログの非表示が遅い

    ダイアログの非表示が遅い Windows CE上で動作するソフトを作成中で、約2cm×2cmほどのボタンだけのダイアログが1つ(メインのダイアログ)、約2cm×1cmほどのボタンだけのダイアログが3つあります。(ダイアログの大きさは、それぞれのボタンと同じサイズで、メイン以外はモーダレスです。) その中の1つを押すと、別の全画面サイズのダイアログを表示し、そのダイアログ上のボタンを押すと、元のボタンだけになるようにしています。 全て、メインのダイアログのOnInitDiarog()で生成しておき、ShowWindow(SW_SHOW)で表示し、ShowWindow(SW_HIDE)で非表示にしているのですが、全画面サイズのダイアログを非表示にする際、表示が消える前に、ボタンのダイアログが表示されてしまい、見た目がかなり悪いのです。 Windows CEは遅いと聞いた事はあるのですが、どうにか対処する方法はないのでしょうか? どなたか助言をお願い致します。 環境は以下の通りです。 ・Windows CE 5.0 ・Visual C++ 2005 ・MFCスマートデバイス 以上、よろしくお願いします。

  • 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; }

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