ウインドウスタイルをいじってみる
これまた、ひどく今更なネタですが。慣れない方とっては結構興味深い景色が見られるのではないかと。
ウインドウハンドルについて
Windowsでは、Windowsは全て「ウインドウハンドル」というもので管理しています。そして、このウインドウハンドルは、システム内で一意に振られます。そのため、ウインドウハンドルさえ取得できれば任意のプロセスから任意のウインドウのスタイルを変更することが可能となります。
ウインドウハンドルを取得する方法はいくつかあります。
| 関数 |
ヘッダファイル |
効能 |
| GetDesktopWindow() |
Windows.h |
デスクトップのウインドウハンドルを取得します。 |
| GetWindow( HWND hWnd, UINT uCmd) |
Windows.h |
hWndに指定したウインドウに関係するウインドウの、ウインドウハンドルを取得します。 |
| EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam ) |
Windows.h |
画面上の全てのトップレベルウインドウのウインドウハンドルを列挙します。 |
| EnumChildWindows( HWND hWndParent, WNDENUMPROC lpEnumFunc, LPARAM lParam ) |
Windows.h |
hWndParentに指定したウインドウに関係するウインドウのウインドウハンドルを列挙します。 |
| WindowFromPoint( POINT Point ) |
Windows.h |
指定された座標を含むウインドウのウインドウハンドルを取得します。 |
要は戻り値が「HWND」な関数を適当に呼び出してやればいいのです。詳しいことはMSDNライブラリを参照してください。
とりあえず、ここでは「SPY++」というツールを用いて、ウインドウのハンドルを取得する事とします。SPY++はVisualStudioに含まれています。

Spy++の画面
個人的には、この画面より「メッセージオプション」ダイアログ内の「ウインドウ ファインダー ツール」の方が好みです。
ウインドウスタイルの変更
ウインドウハンドルが取得できてしまえば、後は何でもやり放題です。なんか適当にウインドウハンドルを引数に取る関数を呼び出してみましょう。
「画面のプロパティ」ウインドウの壁紙のプレビューを行うところのウインドウハンドルを取得してみる。ここでは「ウインドウ: 0003043C」と書かれたところがウインドウハンドルです。

下記のようなプログラムで、無理矢理ウインドウを閉じたところ。
int main()
{
HWND hWnd = (struct HWND__ *)0x0003043C;
CloseWindow( hWnd );
return 0;
}
閉じると言っても、ここでは「サンタフェ」と書かれたあたりに、小さく灰色になった残骸(?)みたいのが残っています。
さて、次は、目的の「ウインドウスタイルの変更」を行ってみたいと思います。ウインドウスタイルを設定するのは、基本的には「CreateWindow」などでウインドウを構築する時となります。しかし、既存のウインドウのスタイルを変更する方法もあります。それが「SetWindowLong」関数です。
詳しいところはやはりMSDNライブラリを参照して欲しいところですが、とりあえず、少しだけ紹介します。
LONG SetWindowLong(
HWND hWnd, // ウィンドウのハンドル
int nIndex, // 設定する値のオフセット
LONG dwNewLong // 新しい値
);
hWndには、先ほど紹介した方法で取得した、ウインドウハンドルを指定します。
nIndexには、何を変更するのかを指定します。ウインドウスタイルを変更する場合は「GWL_STYLE」を、拡張ウインドウスタイルを変更する場合は「GWL_EXSTYLE」を指定します。
dwNewLongには、変更後の値を指定します。
また、現状の値を取得するためには、以下の関数を使用します。
LONG GetWindowLong(
HWND hWnd, // ウィンドウのハンドル
int nIndex, // 設定する値のオフセット
};
でもって、いたずらを決行致します。
#include <stdio.h>
#include <windows.h>
int main()
{
HWND hWnd = (struct HWND__ *)0x00020038;
long i = GetWindowLong( hWnd, GWL_EXSTYLE );
printf( "0x%08X\n", i );
SetWindowLong( hWnd, GWL_STYLE, i | WS_CAPTION | WS_THICKFRAME | WS_VSCROLL );
return 0;
}
ここで指定しているハンドル「0x00020038」というのは、デスクトップの右隅にある「スタート」ボタンのハンドルです。で、これを実行すると。
こうなります。
まさに、やりたい放題です。
半透明に挑戦
ここで、少し前のことを思い出してみます。Windows2000が発売された当初、話題になった機能の一つに「ウインドウが半透明になる」というのがありました。でも、話題性だけで全くと言っていいほど役に立たないこの機能。ちょっと使ってみたいと思います。
#include <stdio.h>
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <winuser.h>
int main()
{
COLORREF r;
HWND hWnd = (struct HWND__ *)0x00070440;
long i = GetWindowLong( hWnd, GWL_EXSTYLE );
printf( "0x%08X\n", i );
SetWindowLong( hWnd, GWL_EXSTYLE, i | WS_EX_LAYERED );
r = RGB( 255, 255, 255 );
SetLayeredWindowAttributes( hWnd, r, 128, /* LWA_COLORKEY */ LWA_ALPHA );
return 0;
}
そして、これで「マイコンピュータ」を半透明にしてみました。それがこれです。
ウインドウを半透明にするには、「拡張ウインドウスタイル」として「WS_EX_LAYERED」を指定します。そして「SetLayeredWindowAttributes」関数で、半透明の度合いなどを指定します。
BOOL SetLayeredWindowAttributes(
HWND hwnd, // 目的のウィンドウのハンドル
COLORREF crKey, // 透過させる色
BYTE bAlpha, // 半透明の度合い
DWORD dwFlags // アクションフラグ
);
hwndには、目的のウインドウハンドルを指定します。
crKeyには、透過させる色を指定します。
bAlphaには、半透明の度合いを指定します。0にすると完全に透明になり、255を指定すると不透明になります。
dwFlagsには、以下の値を設定します。
- LWA_COLORKEY 透過させる色として「crKey」の値を使用します。
- LWA_ALPHA bAlphaの値を使用して、ウインドウを半透明にします。
記のプログラムで「r」を指定していますが、これは意味がありません。そこで、半透明をやめて、白い部分を透過させたいと思います。そのためには、上記プログラムのコメントアウトされている部分をいじくって、dwFlagsにLWA_COLORKEYを指定するようにします。
すると、こうなります。
このウインドウ、透明の部分をクリックすると、その下に見えているウインドウをクリックしたことになります。つまり、以前の「リュージョン」を指定したのと同じ状態になっています。
ここで、いくつか注意事項があります。
- 半透明にするときは、ターゲットのウインドウは「トップレベルのウインドウ」にしましょう。たとえば、上述のように「マイコンピュータ」を半透明にしたければ「マイコンピュータ」書かれたタイトルバーを持つウインドウをターゲットに指定します。子ウインドウだけを半透明にすることはできないようです。
- コンパイルする際、「#include <windows.h>」の前に「#define _WIN32_WINNT 0x0500」と記述しましょう。そうでないと、必要な宣言が行われません。
- 当然ですが、このプログラムはWindows2000以降でしか動きません。
- 半透明のウインドウは、処理が重くなります。やたらと重いです。気をつけましょう。(重いと言うことを証明してみた。)
- たぶん、VisualStudioの6.0の場合、PlatformSDKが必要になると思います。がんばってダウンロードしましょう。
最後に
スクバーを半透明にしてみた。
また、「SetWindowText」関数を使えば、任意のウインドウのテキストを変更することができます。
|