FAQ1-1
|
Q. 常に手前に表示するには
Windows3.1のアクセサリにある「時計」や,フリーソフトウェアなどで「常に手前に表示」という項目がありますが,その方法がわかりません.
BringWindowToTop()を使用してみたのですが,ただウィンドウがアクティブになるだけで,他のウィンドウをアクティブにするとその下に隠れてしまいます.もしそういう関数があるのならば教えてください.
|
|
|
A. 「常に手前に表示」にするには,SetWindowPos()またはCreateWindowEx()を使用する
SetWindowPos()を使用する
SetWindowPos()は,ただウィンドウの位置とサイズを変更するだけでなく,Zオーダ(ウィンドウの重なる順番)も変更することができます.
SetWindowPos()の使用方法:
BOOL SetWindowPos( hwnd, hwndInsertAfter, x, y, cx, cy, fuFlags );
HWND hwnd; ウィンドウハンドル
HWND hwndInsertAfter; 配置順序のハンドル
int x, y, cx, cy; 位置と大きさ
UINT fuFlags; ウィンドウ位置調整フラグ
ここで重要になるのが,hwndInsertAfterパラメータです.これは,通常Zオーダで直前に位置するウィンドウハンドルを指定して,任意の位置にZオーダを変更させるものですが,特定のデファイン値を指定することにより,「常に手前に表示」にすることができます.
常に手前に表示にするだけの場合,ウィンドウの位置や大きさを変えたくないので,fuFlagsパラメータにSWP_NOMOVEとSWP_NOSIZEを指定することで,x, y, cx, cy を無視することができます.
常に手前にする場合:
SetWindowPos( hwnd, HWND_TOPMOST, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE );
常に手前にしない場合
SetWindowPos( hwnd, HWND_NOTOPMOST,0,0,0,0, SWP_NOMOVE | SWP_NOSIZE );
CreateWindowEx()を使用する
CreateWindowEx()を使用する方法もあります.これは自分でウィンドウを作成する時点で,拡張スタイルにWS_EX_TOPMOSTを指定することで,SetWindowPos( hwnd, HWND_TOPMOST,・・・ ) とするのと同じことになります.
しかしこれは,ウィンドウ作成時に指定するものなので,「時計」のようにあとから属性を変えたいという場合,結局SetWindowPosを使用することになるので,あまり活用の場面はありません.
Zオーダは,Windows3.1になって,アクティブウィンドウを変更しても影響を受けず常に前面に表示される属性が追加されています.
しかし,「常に手前に表示」できるアプリケーションはWindows3.0の時代からありました.これは一体どのようにして実現していたのでしょうか?
それは,おそらくタイマーを使用し,毎回 ShowWindow(hwnd,SW_SHOWNA) していたと思われます.
SW_SHOWNAは,「アクティブなウィンドウは変えずに,ウィンドウを表示」する指定ですが,実は,
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
とするのと同じ動作をします.
通常のウィンドウが非アクティブからアクティブに変わるとき,必ずHWND_TOP(HWND_TOPMOSTではない)の位置になります.
こうすると,アクティブウィンドウが変わってもタイマーが来たときに,「アクティブは変えずに(SWP_NOACTIVATE),TOPに表示(HWND_TOP)」するので,疑似的に常に手前になります.
しかし,アクティブが変わるときに一時的にHWND_TOPが移ることになるので,チラつくことがあるので,あまりお薦めできません(図1-1).
[図1-1] :
Back to FAQ main page