レイヤードウィンドウというのは 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 の標準的なウィンドウと同じ)になっているようだ。
Trackback

3 comments untill now

  1. レイヤードウィンドウのサンプルコード

    せっかくなのでサンプルコードを貼り付けておきます。調査内容の記事もちょっと追記してるのでそちらもご覧あれ。 サンプルコード layeredtest.cpp 縦方向に色が変化(上が赤で下が青のグ…

  2. […] レイヤードウィンドウについて多少調べたこと […]

  3. […] 或るプログラマの一生 – レイヤードウィンドウについて多少調べたこと 関連記事: […]

Add your comment now