12月
21
レイヤードウィンドウというのは Windows 2000 で追加された機能で、トップレベルウィンドウに半透明効果を与えるものです。メニューのフェード効果や、ファイルのドラッグ&ドロップで半透明になるのは、レイヤードウィンドウを使って実現されているようです(少なくとも Windows 2000 の時点では)。Aero Glass とは別の技術ですが、Windows 7 でもちゃんと使えるようです。
レイヤードウィンドウを使うには、以下の2通りの方法があります。
- SetLayeredWindowAttributes を使ってお手軽に(半)透明化する。ウィンドウの描画自体は普通のウィンドウと同様に WM_PAINT メッセージを処理する。
- UpdateLayeredWindow を使って詳細に制御する。この場合、ウィンドウ全体を自力で描画する必要がある。
以下は UpdateLayeredWindow を使い、その中でもピクセルごとのアルファ値を持つレイヤードウィンドウを実現するケースについて3時間ぐらいで調べたことです。動作に関しては Windows 7 x64 でのものです。
- トップレベルウィンドウにしか効かないぽい。子ウィンドウに WS_EX_LAYERED を付与しても何も起きないぽい。
- WM_PAINT は飛んでこなくなる。さらに、非クライアント領域まで含めて自前で描画する必要がある。
- ヒットテストにおいて、少しでもアルファ値がある部分はヒットテストの対象となり、完全に透明な部分は対象にならない。WS_EX_TRANSPARENT を追加で付与した場合はそもそもヒットテストされない。
- UpdateLayeredWindow の呼び出しで pptSrc と psize パラメータで示される矩形が hdcSrc に選択されたビットマップからはみ出す場合、UpdateLayeredWindow は TRUE を返すが、実際には何も起きない。
- ウィンドウの位置とサイズは UpdateLayeredWindow の呼び出しで pptDst と psize パラメータで指定されるものに更新されるが、その際 WM_MOVE や WM_SIZE は送られない。MoveWindow 等で動かした場合は通常時と同様に送られる。
- (12/25追記)UpdateLayeredWindow の呼び出しで hdcSrc に選択されたビットマップのアルファは「ストレートアルファ」ではなく「乗算済みアルファ」でなければならない。
- (12/26追記)実際に描画されたりヒットテストされたりする領域は、ウィンドウリージョン(SetWindowRgn によって設定できるウィンドウリージョン)によってもクリップされる。デフォルトだと左上と右上の角が丸くなった矩形(Windows XP の標準的なウィンドウと同じ)になっているようだ。
レイヤードウィンドウのサンプルコード
せっかくなのでサンプルコードを貼り付けておきます。調査内容の記事もちょっと追記してるのでそちらもご覧あれ。 サンプルコード layeredtest.cpp 縦方向に色が変化(上が赤で下が青のグ…
[…] レイヤードウィンドウについて多少調べたこと […]
[…] 或るプログラマの一生 – レイヤードウィンドウについて多少調べたこと 関連記事: […]