« 10.10 影付きウィンドウ | ココ | 10.12 ミント初潜入 »

2006年10月11日

影付きウィンドウ(Layered-window)   このエントリーを含むはてなブックマーク 

お陰で、レイヤーだと分かっただけ良しとしよう。

…というわけで、「レイヤードウィンドウ(layered window)」について調べる。
関連する主だったAPIは…

  • SetLayeredWindowAttributes
  • UpdateLayeredWindow

てなところか。


まぁ、技術的には透過ウィンドウが可能になったWin2000からあるもんだから、資料は古いのばっかりなんですが(あぁ、それだけ僕は浦島太郎状態になってるってことなんだね)。でも、SetLayeredWindowAttributes()に関しては、VB.NET 2003では既にTransparencyKey, Opacityで実装がされているので、触ったことがないわけではない。先のMSのドキュメントに拠れば、UpdateLayeredWindowでは、もっと高度に扱えると言うことらしい。WM_PAINTを処理しないようになることで、高速化もするらしい。逆に、WM_PAINTがやってこなくなるからまさに『飾り』としてしか機能しなくなるわけだが。

KNOnline.NET Weblogにて、簡単なレイヤードウィンドウの使い方があった。これはごく最近んだ。しかし、これではまだ具体的なプログラムが見えてこない。

じゃあ、コード的にはどうなってんだ、と。

あのね…昔みたいに、APIをガシガシ使いたくないんだよ。

リハビリ中(ref. deee)を見たら、まさにやりたいことが書いてあって。

不定型で透明度が不均一なウィンドウはSystem.Windows.Forms.FormとSystem.Drawing.Regionの組み合わせだけでは作れないので、レイヤードウィンドウを使うことで実現。 これならSystem.Drawing.Graphics(ないしはBitmap)に描画したものをHDC経由でUpdateLayeredWindowに渡すだけで簡単にイメージが反映されるし、そのうえα値が0より大きい部分だけにマウス関連のメッセージが送られるようになるのでイメージと同じ形のRegionを作る必要も無し。

おお、それでいけるのか。…で、作ってみた。が。Bitmapをちゃんと使ってくれない。やったことは、

  • Dim g_sc As Graphics = Graphics.FromHWnd(IntPtr.Zero) ' スクリーンのGraphicsオブジェクト取得(描画はできないよ、念のため)
  • Dim hdc_sc As IntPtr = g_sc.GetHdc()
  • Dim bmp As Bitmap = とあるイメージ作成関数()
  • Dim g_bmp As Graphics = Graphics.FromImage(bmp) ' 画像のGraphicsオブジェクトを取得
  • Dim hdc_bmp As IntPtr = g_bmp.GetHdc()
  • UpdateLayeredWindow(Me.Handle, hdc_sc, New tPoint(Me.Left, Me.Top), New tSize(Me.Width, Me.Height), hdc_bmp, New tPoint(0, 0), 0, blend, 2) ' 透過処理実行
  • ...後片付け

で、APIはやだ…と思ってたけど、どうしてもSelectObject/DeleteObjectはしなきゃいけないらしい。

  • Dim oldhbmp As IntPtr = SelectObject(hdc_bmp, g_bmp.GetHBitmap())
  • DeleteObject(SelectObject(hdc_bmp, oldhbmp)) ' 後片付けにて

SetWindowLong()でWS_EX_LAYEREDをセットしないといけないんだが、それはFormのCreateParams()プロパティをオーバーライドすることで実現可能。『飾り』としてしか使えないのだから、派生させてコンポーネント化するほうがいいでしょう?

Protected ReadOnly Overrides Property CreateParams() As CreateParams
  Get
    Dim cp As CreateParams = MyBase.CreateParams()
    cp.ExStyle = cp.ExStyle Or WS_EX_LAYERED Or WS_EX_TRANSPARENT Or WS_EX_NOPARENTNOTIFY
    Return cp

  End Get
End Property

さっき見つけた。ここに書いてあること一通り書いてある。ただし、C#で。

By ただ at 21:54 カテゴリー ; さんぷるライブラリー , PinMarch Samples , VB, VB .net , プログラミング単語帳 , mein Erbe , 仕事関係

« 10.10 影付きウィンドウ | 10月の記事 | 10.12 ミント初潜入 »




トラックバック

このエントリーのトラックバックURL:
http://pinmarch.sakura.ne.jp/mt/mt-tb.cgi/665

このリストは、次のエントリーを参照しています: 影付きウィンドウ(Layered-window):

» 影付きウィンドウ(non-Layered-window) from PinMarch
前にLayered-windowで影を作ったけど。 いろいろ見てたら、もっと簡単...

トラックバック時刻: 2007年3月 8日 21:31