以下のような背景が透明なウィンドウの作り方の続きです。前回はこちら
このウィンドウは、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
本記事のスクリーンショットを撮る為に作った簡単なプログラムのソースファイルです。
ほとんど機能の無い透明ウィンドウですが、ソース全体の量は少なく、ビルドも容易です。
お好きな方をどうぞ。