MDIでダイアログをモードレスで表示するには?


リポD  2005-08-26 00:19:49  No: 58759

現在MDIでプログラム組んでるんですが、システム設定用のダイアログを
表示して設定を行う機能を作っていて、ダイアログをモーダルじゃなくて、モードレスで表示させる方法を教えてください。
一応過去ログで
http://madia.world.coocan.jp/cgi-bin/Vcbbs/wwwlng.cgi?print+200311/03110042.txt
という方法を見つけたのですが、この方法ですと
・複数起動できてしまう
  →設定画面なので複数は困る。しかし、モーダルにはしたくない
・ダイアログを移動させると、MDIの枠の外へ移動できてしまう。
  →出来れば子ウィンドウみたいにMDIの枠の中だけで移動させたい
という問題があります。わがままだとは思いますが、ご助力いただければ
助かります。

ちなみに環境はVC++6.0でOSはXP.Proです。


てつや  2005-08-26 01:47:56  No: 58760

>複数起動できてしまう
ウィンドウがあるかどうか確認して、ない場合のみ作ればいいです。

>ダイアログを移動させると、MDIの枠の外へ移動できてしまう。
ダイアログのスタイルをポップアップからチャイルドへ変更します。

ダイアログバーにした方が使い勝手がよさそうです。


リポD  2005-08-26 18:23:09  No: 58761

回答ありがとうございます。
>ウィンドウがあるかどうか確認して、ない場合のみ作ればいいです。
それはそうなんですが、その方法がよくわからないのです。そのダイアログのポインタを取得してなんか処理をするんですか?

>ダイアログのスタイルをポップアップからチャイルドへ変更します。
ポップアップからチャイルドに変更したら、表示されなくなりました。
m_pXXXDlg->Create(IDD_DLG_XXX,NULL);
m_pXXXDlg->ShowWindow(SW_SHOW | SW_RESTORE);
何か引数間違ってますか?もしくは足りない部分ありますか?
他に解決しそうな引数が見つかりませんでした。


PATIO  2005-08-27 01:21:32  No: 58762

>それはそうなんですが、その方法がよくわからないのです。
>そのダイアログのポインタを取得してなんか処理をするんですか?

モードレスで出す以上は、ダイアログクラスのインスタンスをどこかで
管理する必要があると思いますけれど、管理していないのでしょうか?
インスタンスを管理しているところはモードレスダイアログを開く処理を
行っているところでしょうから、インスタンスに対して問い合わせをするとか、
すればよいのでは?
メインフレームで管理してしまうのが一番無難だと思いますけれど。

>何か引数間違ってますか?もしくは足りない部分ありますか?
>他に解決しそうな引数が見つかりませんでした。

リソースエディタでダイアログのプロパティを見てみましたか?
設定する箇所があったはずですけれど。


PATIO  2005-08-27 01:27:58  No: 58763

>>何か引数間違ってますか?もしくは足りない部分ありますか?
>>他に解決しそうな引数が見つかりませんでした。
>
>リソースエディタでダイアログのプロパティを見てみましたか?
>設定する箇所があったはずですけれど。

失礼、回答文を読み違えていました。
m_pXXXDlg->Create(IDD_DLG_XXX,NULL);で、
なぜ親ウインドウのポインタがNULLなんですか?
チャイルドで設定するなら当然親ウインドウは指定するべきだと思いますけれど。


リポD  2005-08-27 02:01:25  No: 58764

Cdialog::Createの引数をMSDNで調べたところ、
ダイアログ オブジェクトが所属する CWnd 型の親ウィンドウオブジェクトへのポインタ。NULLを指定すると、ダイアログ オブジェクトの親ウィンドウはメインアプリケーションウィンドウになります。

とあります。という事はGetParentで親ウィンドウを取得でいいんですよね?
しかし、GetParentでもm_pXXXDlg->GetParentでもうまく行きませんでした。
色々やってみましたが、エラーで落ちたり、表示されなかったりです。
何か勘違いしてますか?


てつや  2005-08-27 02:30:51  No: 58765

m_pXXXDlgはどのクラスのメンバなのですか?

m_pXXXDlgがメインフレーム(メインウィンドウ)のメンバである前提で書きます。

コンストラクタでm_pXXXDlg = NULL ;とします。

if(m_pXXXDlg == NULL )//ない時
{
   m_pXXXDlg->new CDialog ;
   m_pXXXDlg->Create(IDD_DLG_XXX,this);
   m_pXXXDlg->ShowWindow(SW_SHOW | SW_RESTORE);
}
else
{
   if(!m_pXXXDlg->IsWindowVisible() )//あるんだけど見えない時
      m_pXXXDlg->ShowWindow(SW_SHOW | SW_RESTORE) ;
}
リンク先に書いてあるdelete thisは使ってはいけません。
OnDestroy あたりで
if( m_pXXXDlg )
{
   if(m_pXXXDlg->m_hWnd )
      m_pXXXDlg->DestroyWindw() ;
   delete m_pXXXDlg ;
}
としましょう。
もしかしたらぬけがあるかもしれません。(Escボタンや右上の閉じるボタンで
ダイアログを閉じたりした時とか)
動的メンバにする必要があるかどうかもわかりません。


PATIO  2005-08-27 03:03:07  No: 58766

>CDialog::Createの引数をMSDNで調べたところ、
>ダイアログ オブジェクトが所属する CWnd 型の親ウィンドウオブジェクトへのポインタ。
>NULLを指定すると、ダイアログ オブジェクトの親ウィンドウはメインアプリケーションウィンドウになります。

確かにそうなんですが、NULLだとかなり涙ぐましい処理をしてメインウインドウを探しているという話を聞いた事があります。
指定しない特別な理由が無いならしてした方が処理が早いのでは?
あと、ダイアログがインスタンスをdeleteする自滅型の構成では、
メインフレーム側で管理できませんから、てつやさんが書かれているように
きちんとメインフレーム側で管理するような公正に変えた方がいいです。


PATIO  2005-08-27 03:03:55  No: 58767

誤字。(^^;

誤)
きちんとメインフレーム側で管理するような公正に変えた方がいいです。

正)
きちんとメインフレーム側で管理するような構成に変えた方がいいです。


リポD  2005-08-29 20:05:27  No: 58768

てつやさん、PATIOさんアドバイスありがとうございます。
m_pXXXDlgはメインフレームのメンバです。書き忘れてました・・・。
てつやさんの通り書いて見ましたが、やはり表示されませんでした。
m_pXXXDlg->new CDialog  というのは恐らく、m_pXXXDlg = new CDialog
だと思いますが、それだとエラーが出るので、m_pXXXDlg->new CXXX
でエラーはでなくなりましたが、ダイアログが表示されませんでした。

ダイアログのスタイルを色々いじったんですが、「兄弟ウィンドウをクリップする」
のチェックを外すと表示されますが、ただ描画されていると言う感じで、
何も操作も出来ません。

もう少しアドバイスください。


PATIO  2005-08-30 01:07:17  No: 58769

m_pXXXDlg = new CDialog;
に関してはそういう話だと思います。
ただ、てつやさんもリポDさんが作ったクラス名は知らないわけですから
読み替えは必要ですね。

Zオーダーの関係なのでは?
他にメインフレームの子ウインドウがあれば、そのウインドウとの
Zオーダーの関係で裏側に回ってしまったりすると思いますけれど。
他のMDIのウインドウが上にきてしまっているとかありませんか?


リポD  2005-09-02 20:53:57  No: 58770

返事遅くなってすいません。

子ウィンドウの裏側に回ってるという指摘ですが、子ウィンドウを最小化、移動などしてもダイアログが無かったので、Zオーダーではないと思います。
ついでに表示位置がおかしいのかと考えたので、念のため中央表示するように設定しましたが、変わりありませんでした。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加