« 続・タクスバーからアイコンを消す | メイン | WebBrowser Controlを使う »

2005年12月03日

mixi Alert 開発日誌:: 非メインフォームを常に最前面ウィンドウに

    

多くのページでは
SetWindowPos(Handle,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE );
とすれぱ、常に最前面に出来るとか、FormStyleにfsStayOnTopを設定すれば、出来ると書かれていたが、それはメインフォームの場合で、そうでないフォームだとそれでは出来ない。
VCLの場合、アプリケーションが非アクティブになる時にTApplication::NormalizeTopMoststがコールされ、メインフォーム以外の最前面ウィンドウを非最前面ウィンドウに戻してしまうようだ。
それではと、TApplication::OnDeactivateでまた最前面ウィンドウになるようにしたのだが、それでは不十分だった。
非最前面ウィンドウに戻されてしまうケースがある。
その後いろいろなイベントで最前面ウィンドウになるようにしてみるがうまくいかず、諦めてメインフォームにしてみたら、SetWindowPosとfsStayOnTopでうまくいった。
が、そのフォームをメインフォームにしてしまうといろいろと都合が悪い。
で、非メインフォームに戻すと最前面ウィンドウでなくなるケースが発生する。

もう無理かなと諦めかけていて気付いた。
非最前面ウィンドウになる時になんらかのメッセージが送られてくるのではないか?と。
調べると、WM_WINDOWPOSCHANGINGがウィンドウのサイズ、位置、または Z オーダーが変更される時に呼ばれるようだ。
SetWindowPosがSWP_NOSENDCHANGINGフラグ付きで呼ばれた場合、このメッセージは送られてこないようだが、幸いVCLのソースを見るとSWP_NOSENDCHANGINGフラグは付いていない。
そこで、目的のフォームでWM_WINDOWPOSCHANGINGをディスパッチすることにした。
WM_WINDOWPOSCHANGINGメッセージのlParamがWINDOWPOSへのポインタになっているので、WINDOWPOS::flagsにSWP_NOZORDERが付いていない時で、WINDOWPOS::hwndInsertAfterがHWND_TOPMOSTでない場合に再びSetWindowPosで最前面ウィンドウにするようにした。(実際の処理は設定によって切り替わる)
で、実際に動作させてみると常に最前面ウィンドウになるようになった。



投稿者 Takenori : 2005年12月03日 14:03




comments powered by Disqus
Total : Today : Yesterday : なかのひと