以下のような背景が透明なウィンドウの作り方の続きです。前回はこちら
このウィンドウは、2枚のウィンドウを重ねて使います。 1枚目は、マウスメッセージを受信して処理する透明なウィンドウで、 2枚目は、文字などを表示する描画用のウィンドウです。
ウィンドウの設定より先に、Win2000以降でしか使えないAPIを使うことになるので、 定数を適切な値に設定しておきます。
どこかに以下のような定数定義がありましたら、
#define _WIN32_WINNT 0x0400
以下のように変更しておきましょう。
#define _WIN32_WINNT 0x0500
さて、肝心のウィンドウの設定ですが、 1枚目のウィンドウCXxxFrame(CFrameWnd派生クラス)のPreCreateWindowはこんな感じです。
BOOL CXxxFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; cs.x = 100; cs.y = 100; cs.cx = 200; cs.cy = 200; cs.style = WS_VISIBLE | WS_POPUP; cs.lpszClass = AfxRegisterWndClass(0); cs.dwExStyle = WS_EX_LAYERED; cs.hMenu = NULL; return TRUE; }
サイズなど細かい点はおいておきまして、注目するのはウィンドウスタイルです。 拡張スタイルとしてWS_EX_LAYEREDを指定しています。
1枚目のウィンドウのOnCreateはこんな感じです。
int CXxxFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; SetLayeredWindowAttributes(0,1,LWA_ALPHA); m_pFrame = static_cast(RUNTIME_CLASS(CYyyFrame)->CreateObject()); CRect rectWindow; GetWindowRect(&rectWindow); m_pFrame->CreateEx(0, NULL, "YYY", 0, rectWindow, this, 0); return 0; }
ポイントは2点。SetLayeredWindowAttributesでウィンドウのα値を1にしているところと、 CYyyFrameを生成しているところです。 なお、m_pFrameというのはCFrameWnd*型のメンバ変数です。
ウィンドウのα値を1にすると、ウィンドウはほとんど透明になります。 α値を0にすると完全に透明になりますが、残念ながら完全に透明にしてしまうと ウィンドウを操作できなくなってしまいます。そのためここではα値を1に留めておきます。
CYyyFrameというのは、文字などを表示する描画用のウィンドウです。 ちょうどCXxxFrameと同じ場所に表示することで、1つのウィンドウのように見せているわけです。
CYyyFrameのウィンドウスタイルは、CYyyFrameのPreCreateWindowで指定します。
BOOL CYyyFrame::PreCreateWindow(CREATESTRUCT& cs) { if (!CFrameWnd::PreCreateWindow(cs)) { return FALSE; } cs.style = WS_VISIBLE | WS_POPUP; cs.dwExStyle = WS_EX_LAYERED | WS_EX_TRANSPARENT; cs.lpszClass = AfxRegisterWndClass(0); return TRUE; }
ポイントは1点。ウィンドウの拡張スタイルをWS_EX_LAYERED | WS_EX_TRANSPARENTとしているところです。
この拡張スタイルの組み合わせの意味は、Microsoftのレイヤードウィンドウ解説ページに書いてあります。
レイヤード ウィンドウが WS_EX_TRANSPARENT 拡張ウィンドウ スタイルを持つ場合、レイヤード ウィンドウの形状は無視され、マウス イベントはレイヤード ウィンドウの下の他のウィンドウに渡されます。というわけで、このウィンドウに対するマウスイベントは、このウィンドウの下にあるウィンドウ、すなわちCXxxFrameに渡されます。このため、CYyyFrameは描画だけに専念できるわけです。
不可思議な点は残りましたが、とりあえずこれで透明ウィンドウを実現することができました。ひとまずめでたしめでたしと言う事で。
投稿者 MASATO : 2004年07月04日 10:30 | トラックバックソースファイルは2つ用意しました。どちらもVisual C++.NET 2003用です。
http://www.sutosoft.com/room/archives/products/heim107src.lzh
本サイトで公開しているHeimdallrというソフトのソースファイルです。
Heimdallrの透明スキンは、本記事の方法で実現されていますので、Heimdallrのソースで確認できます。
こちらソースの透明ウィンドウは様々な機能を持っていますが、ソース全体の量が多く、また(様々なライブラリを用意しなければならないため)ビルド困難です。よって肝心な場所を探すのはちょっと大変です。
http://www.sutosoft.com/room/archives/products/transparent.lzh
本記事のスクリーンショットを撮る為に作った簡単なプログラムのソースファイルです。
ほとんど機能の無い透明ウィンドウですが、ソース全体の量は少なく、ビルドも容易です。
お好きな方をどうぞ。