SetWindowPosの引数によるZオーダーの順番に関して

[戻る]
Palmer 2012/06/13(水) 13:11:36
環境:XP、VC6.0、MFC

親ウインドウ
−子ウインドウA(Modal)
−子ウインドウB(Modeless)
−子ウインドウC(Modeless)
−子ウインドウD(Modeless)

子B、C、Dが表示されている状態で、
子Aを子B、C、Dより背面に表示したい場合に
子Aのクラスで
this->SetWindowPos(this->GetParent(), 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
もしくは
::SetWindowPos(this->m_hWnd, this->GetParent()->m_hWnd, 0, 0, 0, 0, SWP_NOMOVE |
SWP_NOSIZE);
を呼んでやると、求めていたZオーダー順(モードレスのB、C、Dより背面)が実現で
きました。

SetWindowPosの第1引数(SDKだと第2引数)はMSDNによると
MFC「Z順でこのCWndオブジェクトより前に配置されるCWndオブジェクトを識別します。」
SDK「hWndで指定したウインドウは、このパラメータで指定したウィンドウの後ろに置か
れます。」
と記載されており、最初は親ウインドウのハンドルを指定することを思いつきませんでした。

子Aはモーダルなので、親の背面には表示できないが「親より前面でかつ最も背面」という
Zオーダーになったということなのでしょうか。
また、親ウインドウのハンドルを指定するやり方は一般的なのでしょうか。

ご存知の方がおられましたら、教えていただけると幸いです。

仲澤@失業者 2012/06/13(水) 13:43:14
>子Aはモーダルなので、親の背面には表示できないが「親より前面でかつ最も背面」と
>いうZオーダーになったということなのでしょうか。

そもそもZオーダーとは「同じ親を持つ子ウィンドウ間での重なり順位」ですね、
子ウインドウは親の背後に配置されることはありません。
トップレベルウインドウは全てデスクトップの子という扱いです。
従って、「そういう解釈も成り立つ」かもしれません。

>また、親ウインドウのハンドルを指定するやり方は一般的なのでしょうか。

ドキュメントにはこの場合の特別な解説を見つけることはできませんでしたが、
原理的に、又は意味的に「そうならざるを得ない」と言えます。

ちなみに、HWND_BOTTOMではうまくいかなかったということでしょうか(質問)。

Palmer 2012/06/13(水) 15:59:17
レスありがとうございます。

HWND_BOTTOMを指定すると、子Aと親ウインドウが結びついているため
親ウインドウも最背面に移動し、親ウインドウの背面に別アプリ等を
起動していた場合に、それらの背面に回ってしまいました。
(背面でブラウザが起動していた場合、A表示のタイミングでブラウザが最前面に表示さ
れた。)

・親ウインドウのZオーダー順位を変更しない。
・モードレスの子ウインドウB、C、DのZオーダー順位を変更しない。
を満たした上で、親とB、C、Dの間にAを表示したかったため、
試行錯誤の上、親ウインドウを指定するという方法に行き着いた次第です。

仲澤@失業者 2012/06/13(水) 16:44:09
なるほど、そうでしたね(vv;)。
「オーナーウインドウのZオーダーを変更しない」というオプションは
試してみましたか。
SetWindowPos( 対象, HWND_BOTTOM,
          ・・・, SWP_NOOWNERZORDER | SWP_NOMOVE ・・・);
とか。

Palmer 2012/06/13(水) 17:08:06
[[解決]]
SWP_NOOWNERZORDERを見落としていました。
教えていただいた通り、以下のような記述で同様に
「親とB、C、Dの間にAを表示」を実現できました。

・MFCの場合
this->SetWindowPos(&wndBottom, 0, 0, 0, 0, 
        SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER);
・SDKの場合
::SetWindowPos(this->m_hWnd, HWND_BOTTOM, 0, 0, 0, 0, 
        SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER);

大変勉強になりました。ありがとうございました。

古いスレッドには追加発言できません。