Home > Tags > Win32猫
Win32猫
ウィンドウ形状を変える3
- 2009-07-17 (金)
- 技術
●レイヤードウィンドウでウィンドウ形状を変える
【使うAPI】
SetWindowLong, SetLayeredWindowAttributes
【要約】
拡張ウィンドウスタイルでレイヤードウィンドウ指定 → SetLayeredWindowAttributesで調整.
ウィンドウをレイヤードウィンドウにする(?)には,SetWindowLongで拡張ウィンドウスタイルにWS_EX_LAYEREDを設定します.
SetWindowLong( hWnd, GWL_EXSTYLE, GetWindowLong( hWnd, GWL_EXSTYLE ) | WS_EX_LAYERED );
(ウィンドウ生成時にCreateWindowExを使って指定してもOK.)
で,SetLayeredWindowAttributes関数で透過色(今回は白なのでRGB(255,255,255))を設定するだけです.この関数はウィンドウの透明度も設定できるので,猫を半透明にすることも可能です.
あとは猫の画像を描画すれば,勝手に指定した色の部分が透過されます.
(この辺はVisualStudioのバージョンとかで変わるのかもしれませんが)ビルドしようとすると,レイヤードウィンドウ関係の定数が「定義されていません」と言われます.
なにやらwindows.hあたりで#ifdefで定義するかしないかが切り替えられているようです.
windows.hをインクルードする前に
#define _WIN32_WINNT 0x0500
とかすると(本当にこれでいいのだろうか?)レイヤードウィンドウ関係の定数を定義させることができます.
レイヤードウィンドウを使うと,ウィンドウを猫型にするための処理はたったこれだけなので,
途中で猫の透明度を変えたりとかしないのであれば,ウィンドウプロシージャのWM_CREATEメッセージに対する処理あたりで,SetWindowLongとSetLayerdWindowAttributesを一度コールするだけでOK.
(4)ウィンドウ形状を変える4
- Comments (Close): 0
- Trackbacks (Close): 0
ウィンドウ形状を変える2
- 2009-07-17 (金)
- 技術
●ウィンドウリージョンを使ってウィンドウの形を変える
【使うAPI】
SetWindowRgn, CreateRectRgn, CombineRgn, (OffsetRgnとかも使えそう)
【要約】
ウィンドウの形を変えるには,リージョンを作って,SetWindowRgnでリージョンのハンドルを指定すればOK.
ウィンドウを猫型にするためには猫型リージョンを作ってSetWindowRgnに渡さねばなりません.
猫型リージョンを作るために猫画像の前景領域のリージョンを作る関数を自作しました.
//ビットマップの指定範囲からリージョンを作成する.
//指定矩形範囲から,任意の色のpixel領域を除いたリージョンを新たに作成し,そのハンドルを返す.
HRGN GetRegionFromBMP( HBITMAP hBMP, int left, int top, int width, int height, COLORREF TransColor )
{
画素の色を判断したいのでCreateDIBSectionでDIBセクションを作り,hBMPの画像内容をBitBltでコピー.
最初にCreateRectRgnで矩形リージョンを作っておき,
DIBの全画素走査して,透明色だったらCombinieRgn(…RGN_DIFF)でその部分を除く.
(1pixelずつやるのもあれなんで,透明色がX方向に連続している領域毎に除くとか)
}
みたいな感じで.
↑とは逆に,空のリージョンに透明色でない部分をCombinieRgn(…RGN_OR)で加えていくというのでもいいです.
(空のリージョンを作るにはCreateRectRgn(0,0,0,0)で良さげ.)
リージョン作成を毎回アニメーション切換えタイミングで行ってもいいのかもしれませんが,とりあえず画像パターン分のリージョンを最初に作成しておくことにします.
このときに注意すべきは,SetWindowRgnでセットしたリージョンは「以降,システム側が管理するから金輪際さわんな.いらなくなったら勝手に捨てるし.」とされていることです.
なので,用意しておいたリージョンのコピーを作ってSetWindowRgnに渡すようにしないとダメです.リージョンのコピーもCombineRgnで行えます.
//ウィンドウにセットしたリージョンはアプリ側で管理できなくなるので,コピーを作ってウィンドウにセットする
HRGN tmpRgn = CreateRectRgn( 0,0,0,0 );
CombineRgn( tmpRgn, 作って置いたリージョンのハンドル, NULL, RGN_COPY );
SetWindowRgn( hWnd, tmpRgn, TRUE );
最初に作成したリージョン群はSetWindowRgnに渡していないので,当然,アプリケーション終了時とかにDeleteObjectで始末する必要があります.
「SetWindowRgnの第3引数にTRUEを渡すと再描画する」とかヘルプに書かれているのですが,この再描画というの一体どこが再描画されるのか不明で,↑のコードだけだと以降の描画が挙動不審になってしまいました.
(以前のリージョン形状での描画内容が消えないで残る,以降の描画内容が反映されない,等…)なので,↑のSetWindowRgnの行を,
if( SetWindowRgn( hWnd, tmpRgn, TRUE ) )
{
InvalidateRect( hWnd, NULL, FALSE );
}
としてInvalidateRectも読んでおきます.
(SetWindowRgnの前にGetWindowRgnでそのときのリージョンを取得すれば,InvalidateRectではなくInvalidateRgnでいけるかもしれません.ちょっと試したのですが,ちらつきが出たりしてなかなかうまくいかないのでやめました…)
リージョンを設定できたら,設定したリージョンに対応している猫画像を表示すればOKです.
以上をまとめると,ウィンドウプロシージャは以下のような内容になりました.(ここではアニメーションには簡単にタイマー使用.)
- WM_CREATE 時(初期処理)
猫画像BMPのロードとリージョンの作成.
最初のパターン用のリージョンをSetWindowRgnで設定.
SetTimerでアニメーションのためのタイマーを開始.
- WM_TIMER 時(アニメーションパターンを次に進めるための処理)
次のパターンのリージョン(コピー)をSetWindowRgnで設定し,InvalidateRect.(↑のコードを参照)
必要なら同じタイマIDに対してSetTimerを読んで,パターン間の時間を変える.
- WM_PAINT 時(猫パターン画像の描画)
BitBlt等で表示すべき画像を表示する.
- WM_DESTROY 時(後始末)
KillTimerでタイマを止める.
猫画像BMPとリージョンを破棄.
※あと,ウィンドウを閉じる手段が別途必要.
(3)ウィンドウ形状を変える3
- Comments (Close): 0
- Trackbacks (Close): 0
Home > Tags > Win32猫