Home > Tags > Win32猫

Win32猫

ウィンドウ形状を変える3

●レイヤードウィンドウでウィンドウ形状を変える

【使う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

●ウィンドウリージョンを使ってウィンドウの形を変える

【使う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猫

Search
Feeds
Authorized
奨学金支援制度
Meta

Return to page top