ホーム 主筆 その他ソフト その他情報 Syuhitu.org English

Windows関連

スクリーンセーバー作成法

半透明ウインドウの性能

bootfont.bin

キャビネット形式

ウインドウスタイルをいじる

Java製ソフトをServiceに登録する

イベントログにメッセージを出力する

コントロールパネルにアイコンを追加する

スクリプトによる拡張1

スクリプトによる拡張2

ガジェットの作成

大容量メモリ

メモリ搭載量の下限に挑む

スパースファイルにする

表示されるアイコンの種類を調べてみた

メモリマップIOとエラー処理

ファイルを作る順番と速度の関係

Cryptography API: Next Generationを使う

Windows 10のアクセントカラー

iSCSIディスクにバックアップを取る

サーバプロセスを分離して実装する

サーバプロセスを分離して実装する - F#

レジストリに大量に書き込む

Solaris関連

OpenGL

Solaris設定

ディレクトリの読み込み

主筆プラグイン開発

マルチスレッドでの開発

door

音を出す

Blade100の正しい虐め方

パッケージの作成

画像入出力

BMPファイル

ICOファイル

ANIファイル

JPEGファイル

減色アルゴリズム

減色アルゴリズムの並列化

その他アルゴリズムなど

自由軸回転

Base64

文字列操作

CPU利用率の取得

正規表現ライブラリ

メタボールを作る

メタボールを作る2

正規表現とNFA・DFA

C言語の構文解析

液晶ディスプレイを解体してみた

iSCSIの理論と実装

単一フォルダにファイルを沢山作る

USB-HUBのカスケード接続

SafeIntの性能

VHDファイルのフォーマット

USBメモリに書き込み続けてみた

ウインドウスタイルをいじってみる

2004年5月7日公開

これまた、ひどく今更なネタですが。慣れない方とっては結構興味深い景色が見られるのではないかと。

ウインドウハンドルについて

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に含まれています。

個人的には、この画面より「メッセージオプション」ダイアログ内の「ウインドウ ファインダー ツール」の方が好みです。

ウインドウスタイルの変更

ウインドウハンドルが取得できてしまえば、後は何でもやり放題です。なんか適当にウインドウハンドルを引数に取る関数を呼び出してみましょう。

 

「画面のプロパティ」ウインドウの壁紙のプレビューを行うところのウインドウハンドルを取得してみる。ここでは「ウインドウ: 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が必要になると思います。がんばってダウンロードしましょう。

最後に

いくつかくだらないことをやってみました。

(1)タスクバーを半透明にしてみました。

なお、この画面はあくまでもWindows 2000です。間違ってもVistaや7ではありません。

(2)ウインドウのテキストを変えてみました。

何がどう変更されたのかは、ご自分の目で確認してください。


連絡先 - サイトマップ - 更新履歴
Copyright (C)  2000 - 2016 nabiki_t All Rights Reserved.