ウィンドウクラスの登録
カスタムウィンドウクラス
前回は、すでに定義されているウィンドウクラスを用いてウィンドウを生成しました
しかし、通常はボタンやラベルだけのウィンドウなど使いません
ここでは、一般的に見られるアプリケーションウィンドウを作成してみましょう
ウィンドウの定義で重要なもう一つの項目がウィンドウクラスでした
ウィンドウクラスは、大まかなウィンドウの汎用的な設定を行います
まず、ウィンドウクラスの登録にはWNDCLASS構造体型変数を用います
typedef struct _WNDCLASS {
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HANDLE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
} WNDCLASS;
これが WNDCLASS の定義です
私たちはこの型の変数を宣言し、初期化しなければいけないのです
style には、ウィンドウクラスの基本スタイルを表す定数を指定します
この場は、よく使われる CS_HREDRAW と CS_VREDRAWを用いましょう
CS_HREDRAW は水平に、CS_VREDRAW は垂直に、ウィンドウサイズが変更されると
ウィンドウの内容を再描画します
WNDPROC 型とは、ウィンドウプロシージャと呼ばれる関数のポインタ型です
lpfnWndProc にウィンドウプロシージャを設定します
ウィンドウプロシージャとは、ウィンドウで発生したイベントを処理する関数なのですが
これに関してはまだ説明していないので、デフォルトの DefWindowProc()を渡します
この関数は、ウィンドウの移動などの基本的な動作をサポートします
LRESULT DefWindowProc(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);
今は、この関数について知る必要はありません
この関数を呼び出すのはプログラマではなくウィンドウズなのです(後記)
この場では、イベントが発生した時にこの関数を呼び出すように
ウィンドウクラスに、この関数のポインタを渡しているのだということを理解してください
次の二つの引数 cbClsExtra と cbWndExtra は
クラス構造体、ウィンドウ構造体の追加領域をバイト単位で予約するものです
通常はその必要がないので、多くの場合ここは 0 を指定します
hInstance には、インスタンスハンドルを渡します
hIcon には、タスクバーやタイトルバーに表示されるアイコンのビットマップを指定します
HICON 型は、アイコンのハンドルです
アイコンのビットマップを渡すにはLoadIcon()関数を使用します
HICON LoadIcon(HINSTANCE hInstance , LPCTSTR lpIconName);
hInstance には、アイコンのリソースが入っているモジュールのインスタンスを指定しますが
システム定義のアイコンの場合は NULL にします
lpIconName は、アイコンの名前を指定します
第一引数が NULL の場合は、用意されているアイコンの定数を渡します
IDI_APPLICATION が、アプリケーションのアイコンを表します
hCursor は、ウィンドウのクライアントエリア上のマウスカーソルを指定します
HCURSOR 型 とは、カーソルのハンドルです
定義済みのカーソルは LoadCursor() 関数で取得します
HCURSOR LoadCursor(HINSTANCE hInstance , LPCTSTR lpCursorName);
hInstance はカーソルのリソースが入っているモジュールのインスタンスを指定します
アイコン同様に、システム定義のカーソルの場合は NULL を指定します
lpCursorName には、カーソルの名前を指定します
第一引数が NULL であれば、定義されているマウスカーソルの定数を指定します
hbrBackground は、クライアントエリアの背景色を指定します
ここで渡すのは HBRUSH 型の、ブラシのハンドルです
ブラシとは、グラフィックスの概念なので詳しくは後記します
ブラシのハンドルはGetStockObject()関数を使用します
この関数は、定義済みのブラシやフォントのハンドルを取得できます
HGDIOBJ GetStockObject( int fnObject );
fnObject に、取得したいハンドルの定数を指定します
この関数はブラシのほかにも、ペン、パレットといったハンドルも取得できます
グラフィックス関係の説明の時に、さらに詳しく解説します
白いブラシはWHITE_BRUSHを指定します
この関数の戻り値は HBRUSH ではありません
HGDIOBJ 型 は、グラフィック関連のハンドルです
先ほど説明した通り、この関数はペンやフォントのハンドルも返します
要求する型、HBRUSH にキャストすれば問題ありません(しなくても良いです)
lpszMenuName には、クラスメニューを指定しますが
今回のプログラムにメニューはないので、ここは NULL としましょう
最後の lpszClassName は、このウィンドウクラスの名前です
CreateWindow() 関数の第一引数で指定しましたね
これで、WNDCLASS 型変数の初期化ができますね
しかし、この時点ではまだウィンドウクラスは登録されていません
次に、ここで初期化した変数をRegisterClass()関数に渡します
この関数にウィンドウクラスを渡して、はじめて登録されます
ATOM RegisterClass(CONST WNDCLASS *lpwcx);
lpwcx に、WNDCLASS型の変数のポインタを渡します
成功すると登録されたクラスを一意的に識別するアトムというものが返ります
アトムについて、この場では説明しません
ただ、失敗すると 0 が返って来るので、基本的にエラーチェックしましょう
#include<windows.h>
int WINAPI WinMain(
HINSTANCE hInstance ,
HINSTANCE hPrevInstance ,
PSTR lpCmdLine ,
int nCmdShow ) {
HWND hwnd;
WNDCLASS winc;
winc.style = CS_HREDRAW | CS_VREDRAW;
winc.lpfnWndProc = DefWindowProc;
winc.cbClsExtra = winc.cbWndExtra = 0;
winc.hInstance = hInstance;
winc.hIcon = LoadIcon(NULL , IDI_APPLICATION);
winc.hCursor = LoadCursor(NULL , IDC_ARROW);
winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
winc.lpszMenuName = NULL;
winc.lpszClassName = TEXT("KITTY");
if (!RegisterClass(&winc)) return 0;
hwnd = CreateWindow(
TEXT("KITTY") , TEXT("Kitty on your lap") ,
WS_OVERLAPPEDWINDOW ,
100 , 100 , 200 , 200 , NULL , NULL ,
hInstance , NULL
);
if (hwnd == NULL) return 0;
ShowWindow(hwnd , SW_SHOW);
MessageBox(NULL , TEXT("Kitty on your lap") ,
TEXT("Kitty") , MB_ICONINFORMATION);
return 0;
}
いかがなものでしょうか
道のりは険しかったですが、それっぽいウィンドウが完成しました
DefWindowProc() のおかげで、ウィンドウの移動や最大化といった
ウィンドウが持つ最低限の動作もサポートされています
このような長いコードや、多くの型や関数を記憶しているプログラマはいません
通常は、こうしたソースを使いまわしているのです(コピー&ペースト)
DefWindowProc()
LRESULT DefWindowProc(HWND hWnd , UINT Msg , WPARAM wParam , LPARAM lParam);
デフォルトウィンドウプロシージャを呼び出します
デフォルトウィンドウプロシージャは、ウィンドウが持つ基本的なふるまいをサポートします
hWnd - メッセージを受け取ったウィンドウのハンドルを指定します
Msg - メッセージを指定します
wParam - メッセージの追加情報を指定します
lParam - メッセージの追加情報を指定します
戻り値 - メッセージ処理の結果が返ります。意味はメッセージにより異なります
LoadIcon()
HICON LoadIcon(HINSTANCE hInstance , LPCTSTR lpIconName);
インスタンスに関連付けられた実行ファイルからアイコンリソースをロードします
hInstance - ロードするインスタンスを指定します。システム定義の場合は NULL
lpIconName - ロードするアイコンをあらわす文字列を指定します
戻り値 - ロードされたアイコンのハンドルを返します。失敗した時は NULL
定数 | 解説
|
---|
システム定義のアイコン
|
---|
IDI_APPLICATION | アプリケーションアイコン
|
IDI_ASTERISK | アスタリスクのアイコン (吹き出しの中に i の文字)
|
IDI_EXCLAMATION | 感嘆符のアイコン
|
IDI_HAND | ストップ印のアイコン
|
IDI_QUESTION | 疑問符のアイコン
|
IDI_WINLOGO | Windows ロゴアイコン
|
LoadCursor()
HCURSOR LoadCursor(HINSTANCE hInstance , LPCTSTR lpCursorName);
hInstance - ロードするインスタンスを指定します。システム定義の場合は NULL
lpIconName - ロードするカーソルをあらわす文字列を指定します
戻り値 - ロードされたカーソルのハンドルを返します。失敗した時は NULL
インスタンスに関連付けられた実行ファイルからカーソルリソースをロードします
定数 | 解説
|
---|
システム定義のマウスカーソル
|
---|
IDC_APPSTARTING | 標準矢印カーソルおよび小型砂時計カーソル
|
IDC_ARROW | 標準矢印カーソル
|
IDC_CROSS | 十字カーソル
|
IDC_IBEAM | アイビーム (縦線) カーソル
|
IDC_ICON | 現在は使われません
|
IDC_NO | 禁止カーソル
|
IDC_SIZE | 現在は使われません
|
IDC_SIZEALL | 4 方向矢印カーソル
|
IDC_SIZENESW | 斜め左下がりの両方向矢印カーソル
|
IDC_SIZENS | 上下両方向矢印カーソル
|
IDC_SIZENWSE | 斜め右下がりの両方向矢印カーソル
|
IDC_SIZEWE | 左右両方向矢印カーソル
|
IDC_UPARROW | 垂直の矢印カーソル
|
IDC_WAIT | 砂時計カーソル
|
GetStockObject()
HGDIOBJ GetStockObject( int fnObject );
定義済みのペン、ブラシ、フォント、パレットのいずれかのハンドルを取得します
fnObject - 要求するハンドルの定数を指定します
戻り値 - 成功すると要求したハンドルが、失敗すると NULL が返ります
定数 | 解説
|
---|
ストックオブジェクト
|
---|
BLACK_BRUSH | 黒のブラシ
|
DKGRAY_BRUSH | 濃い灰色のブラシ
|
GRAY_BRUSH | 灰色のブラシ
|
HOLLOW_BRUSH | 中空のブラシ (NULL_BRUSH と同じ)
|
LTGRAY_BRUSH | 明るい灰色のブラシ
|
NULL_BRUSH | 空のブラシ (HOLLOW_BRUSH と同じ)
|
WHITE_BRUSH | 白のブラシ
|
BLACK_PEN | 黒のペン
|
NULL_PEN | 空のペン
|
WHITE_PEN | 白のペン
|
ANSI_FIXED_FONT | Windows 文字セットの固定幅システムフォント
|
ANSI_VAR_FONT | Windows 文字セットの可変幅システムフォント
|
DEVICE_DEFAULT_FONT | Windows NT のみ : デバイス依存のフォント
|
DEFAULT_GUI_FONT | Windows 95 のみ : ユーザーインターフェイス用のデフォルトフォント (メニューやダイアログボックスなどで使われる)
|
OEM_FIXED_FONT | OEM 文字セットの固定幅フォント
|
SYSTEM_FONT | システムフォント デフォルトでメニューやダイアログボックスなどで使われる可変幅フォント
|
SYSTEM_FIXED_FONT | 古い Windows との互換性で残されている 現在は使わない
|
DEFAULT_PALETTE | デフォルトのカラーパレット (システムパレット内のスタティックカラーで構成されます。)
|
RegisterClass()
ATOM RegisterClass(CONST WNDCLASS *lpwcx);
ウィンドウクラスを登録します
lpwcx - ウィンドウクラスのポインタを指定します
戻り値 - 成功すると登録されたクラスを一意的に識別するアトムが、失敗すると0が返ります