トップ回答者
モードレスダイアログの表示順番を調べたい

質問
-
いつもお世話になっております
VS2008 でC++/CLIを使ってフォームアプリを作成しています
モードレスダイアログの表示順番を調べたいと思っています
ネットで検索してみましたが、情報が見つからず困っています
(キーワードは、C++/CLI、C#、.NET、Form、表示順 等)
やりたいことは、MainFormからFormA、FormB、FormC...と複数のモードレスダイアログを開き、
MainFormの画面を操作したときに、FormA,FormB,FormCの中で1番トップにあるダイアログに対して処理を行いたい、と思っています
このようなダイアログの表示順番を調べる方法をご教授頂けないでしょうか?
回答
-
「アクティブだったWindowのハンドルを求める方法」のような事をして、直前に表示していたフォームを憶えておく、のようなことをすれば良いと思います。
なお、フォームの表示順は「Z オーダー」といいます(画面上の平面位置である X, Y 軸と、奥行きの Z 軸)。そこで、検索文字列を「ウィンドウ order c++」に変えて検索すると、「ウィンドウを列挙したときのZオーダー」が見つかりました。このスレッド中で言及されている GetWindow 関数の URL は、リンクが切れています。ご注意下さい。
Jitta@わんくま同盟
- 回答としてマーク BB-X LARISSA 2012年5月26日 12:43
-
これも過去に似たような事をやった事があったので(ネイティブアプリでですが)
WinAPIだとJittaさんのあげられているようにフック系やEnum何々Windows系やGetWindow関数など
色々と候補はあるのですが
.NET Frameworkではどうかについては詳しく知らなかったので、コメントを控えていました
コメントを見た感じやっぱりそのものズバリはないようですね。
ただ、それらAPIもそれぞれに微妙な制約があったり、例え特定の環境で正常に動いたとしても確実性という点で疑問符(MSDNに明記されていないゆえに、という意味)
だったり、ちょこっとした事をやりたいだけなのにシステムグローバルな方法で無駄にコストをかけすぎてしまったり、ちょっと気の利いた事をやろうとしたときに仕様上うまくかみ合わず微妙だということになったりする可能性があります。てゆーか高いです。
なので、私としても自分で記録しておくのが最も確実でシンプルかと思います。
以前実際に大規模アプリを作っていた時、特定の派生クラスとなる複数のウインドウのZオーダーを正確に把握する必要が生じたときがあったのですが
その時もやはり自分でウインドウのZ順を記録する方法をとっていました。(そしてそれはその状況下では、最もすんなりいく方法でした)
ただし、そのためだけにフックをしかけるというのは、少々コストがオーバーな気がしなくもないです。
その時はウインドウ移動時にZ順が絡むだけであったので、ネイティブサイドのウインドウメッセージのWM_NCLDOWNとかの制御中でちょこっと入れ替えるのみで十分でしたが
今回の要件で、同様にして
しかも特定のフォームのうち1番トップにあるものを知りたい
だけである場合は、これはMainFormが影響を与える側となり、また
普通に2008 でC++/CLIでフォームを作ったらSystem::Windows::Forms::Formを継承してると思いますので
・MainFormに一つFormのハンドル(あるいは目的のフォームがさらに自分のカスタマイズ済みクラスから派生しているなら、その基底クラスのハンドル)をprivateメンバ変数として一つ持たせておくとかしといて
・FormA、FormB、FormC...の例えばActivatedが発生したときにMainFormのそのメンバを更新出来るような機構を作っておくとかすればそれだけで済んでしまうように感じます。
- 回答としてマーク BB-X LARISSA 2012年5月26日 12:43
- 編集済み mr.setup 2012年5月26日 14:11
すべての返信
-
「アクティブだったWindowのハンドルを求める方法」のような事をして、直前に表示していたフォームを憶えておく、のようなことをすれば良いと思います。
なお、フォームの表示順は「Z オーダー」といいます(画面上の平面位置である X, Y 軸と、奥行きの Z 軸)。そこで、検索文字列を「ウィンドウ order c++」に変えて検索すると、「ウィンドウを列挙したときのZオーダー」が見つかりました。このスレッド中で言及されている GetWindow 関数の URL は、リンクが切れています。ご注意下さい。
Jitta@わんくま同盟
- 回答としてマーク BB-X LARISSA 2012年5月26日 12:43
-
これも過去に似たような事をやった事があったので(ネイティブアプリでですが)
WinAPIだとJittaさんのあげられているようにフック系やEnum何々Windows系やGetWindow関数など
色々と候補はあるのですが
.NET Frameworkではどうかについては詳しく知らなかったので、コメントを控えていました
コメントを見た感じやっぱりそのものズバリはないようですね。
ただ、それらAPIもそれぞれに微妙な制約があったり、例え特定の環境で正常に動いたとしても確実性という点で疑問符(MSDNに明記されていないゆえに、という意味)
だったり、ちょこっとした事をやりたいだけなのにシステムグローバルな方法で無駄にコストをかけすぎてしまったり、ちょっと気の利いた事をやろうとしたときに仕様上うまくかみ合わず微妙だということになったりする可能性があります。てゆーか高いです。
なので、私としても自分で記録しておくのが最も確実でシンプルかと思います。
以前実際に大規模アプリを作っていた時、特定の派生クラスとなる複数のウインドウのZオーダーを正確に把握する必要が生じたときがあったのですが
その時もやはり自分でウインドウのZ順を記録する方法をとっていました。(そしてそれはその状況下では、最もすんなりいく方法でした)
ただし、そのためだけにフックをしかけるというのは、少々コストがオーバーな気がしなくもないです。
その時はウインドウ移動時にZ順が絡むだけであったので、ネイティブサイドのウインドウメッセージのWM_NCLDOWNとかの制御中でちょこっと入れ替えるのみで十分でしたが
今回の要件で、同様にして
しかも特定のフォームのうち1番トップにあるものを知りたい
だけである場合は、これはMainFormが影響を与える側となり、また
普通に2008 でC++/CLIでフォームを作ったらSystem::Windows::Forms::Formを継承してると思いますので
・MainFormに一つFormのハンドル(あるいは目的のフォームがさらに自分のカスタマイズ済みクラスから派生しているなら、その基底クラスのハンドル)をprivateメンバ変数として一つ持たせておくとかしといて
・FormA、FormB、FormC...の例えばActivatedが発生したときにMainFormのそのメンバを更新出来るような機構を作っておくとかすればそれだけで済んでしまうように感じます。
- 回答としてマーク BB-X LARISSA 2012年5月26日 12:43
- 編集済み mr.setup 2012年5月26日 14:11