今回は、Win32APIを使ってアプリケーションのウィンドウを作る方法を、手順に沿って解説していく。
1,ウィンドウクラスを作成する
Win32APIでウィンドウを作るためには、WNDCLASS
構造体を使ってウィンドウクラスを作る必要がある。
ウィンドウクラスとは、今作成しているウィンドウがどんなものかを示したもので、例えば、「マウスカーソルのデザインは何にするか?」とか「ウィンドウのスタイルはどうするか?」等の、ウィンドウの基本的な情報を作成するものだ。
typedef struct tagWNDCLASS { UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; } WNDCLASS, *PWNDCLASS;
実際に、ウィンドウクラスの作成は以下のコードのように書くことになる。参考:ウィンドウクラスの登録
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");
以下は、変数の意味を1つ1つ解説していく。
style
ウィンドウの動きや描写などを指定できるメンバ変数。
winc.style = CS_HREDRAW | CS_VREDRAW;
多くのアプリでは、上記の様に書かれていることが多いが、CS_HREDRAW
とは「Class Style Horizon Redraw」の略で、ウィンドウの横サイズを変更した時にウィンドウを再描写してくれるようになる。
また、CS_VREDRAW
は「Class Style Virtical Redraw」の略で、ウィンドウの縦サイズの再描写をしてくれる。
つまり、CS_HREDRAW | CS_VREDRAW
と書くことで、ウィンドウのサイズを変更した時に縦横関係なく再描写してくれるようになるのだ。
他にも、色々なClass Styleがあるので、詳しくは公式ページを見ると良い。
参考:Window Class Styles (Windows)
lpfnWndProc
lpfnWndProcとは、メッセージを受け取るWndProc関数のポインタを格納するもの。
メッセージとは、「マウスの左クリックをした」とか「ウィンドウを閉じた」とか「キーボードのhキーを押した」等の様に、Windowsに何かしらの情報を送る事を言い、WndProc関数とは、Windowsがメッセージを受け取った時に呼び出される関数と言える。
ちなみに、関数名は自分の好きなように決めれるが、多くのアプリでは~WndProcみたいな関数名が多い。
cbClsExtra
ウィンドウクラスの後ろに余分なメモリを確保するための変数。例えば、cbClsExtra = 3
としたら3byte分のメモリが動的に確保される。
「WinMain関数からメインウィンドウハンドルを手に入れるまでのおさらい」によると、この動的メモリはアプリ共通のポインタを格納したりするのに便利みたいだ。
cbWndExtra
ウィンドウクラスのインスタンスが新たに作られるたびに、メモリを確保するもの。
hInstance
アプリのインスタンスハンドルを格納する変数。基本的には、WinMain関数の引数のhInsntanceを格納することになる。
hIcon
アプリのアイコンを描写するもの。
hIcon = LoadIcon(NULL, IDI_APPLICATION)
のように書くことで、エラーアイコンだったり警告アイコンだったりを表示することができる。
参考:LoadIconA function (winuser.h) | Microsoft Docs
hCursor
カーソルの描写を指定する変数。
アイコンと同じように使う。
参考:LoadCursorA function (winuser.h) | Microsoft Docs
hbrBackground
「handle Bruch BackGroound」の略で、ウィンドウの背景色などを決めれるもの。
hbrbackground = GetStockObject(WHITE_BRUSH)
のように書くことで背景色を決めていく。
参考:GetStockObject function (Windows)
lpszMenuName
作成したメニューの名前を登録する変数。
ただ、個人的にはあまり使わない。
lpszClassName
アプリの名前。基本的にwinc.lpszClassName = TEXT("KITTY");
みたいな感じで登録する。
ウィンドウクラスを登録する
先ほど紹介したWNDCLASS(ウィンドウクラス)を作り終えたら、次はそのウィンドウクラスを登録する必要がある。とは言っても簡単で、RegisterClassEX
と言う関数を使えばよい。
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(!RegisterClassEX(&winc){ return 0; }
RegisterClassEX
は引数にWNDCLASSのポインタを格納して、戻り値は成功したら、そのクラスを識別する一意のATOM(整数みたいなやつ)が返されて、失敗したら0を返す。
また、以前はクラスの登録にはRegisterClass
という関数が使われているが、RegisterClassEX
はウィンドウを小さくした時に表示される小さなアイコンの表示も設定できるので、RegisterClassEX
はRegisterClass
の上位互換と言える。
実際に、マイクロソフトの公式ページにも以下の様に書かれている。
Note The RegisterClass function has been superseded by the RegisterClassEx function. You can still use RegisterClass, however, if you do not need to set the class small icon.
RegisterClass function (Windows)
参考:RegisterClassEx function (Windows)
CreateWindowでウィンドウを表示する
CreateWindow関数は、ウィンドウに関する設定&表示をする関数。
具体的には、以下のように書く。
if (CreateWindow(APP_NAME, APP_NAME, WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 800, 800, NULL, NULL, hInstance, NULL) == NULL) { return 0; }
第1引数にはクラス名、第2引数にはウィンドウタイトルを書く。そして第3引数のWS_OVERLAPPEDWINDOW | WS_VISIBLE
だが、これはウィンドウをどのように表示するかを決めてくれる。
例えば、今回の場合はWS_OVERLAPPEDWINDOW | WS_VISIBLE,
としているが、WS_OVERLAPPEDWINDOW
はWS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIMZEBOX
と言ったオプションをまとめて指定してくれるもの。これを指定することで、ウィンドウの最小ボタン、最大ボタンを表示したり、ウィンドウのサイズを調整できたり、タイトルを表示してくれたり等、アプリを使う時に便利な機能を搭載してくれる。
また、WS_VISIBLE
は初期状態で表示してくれるものとなる。
第4,5引数にはウィンドウをどの位置から表示するか、第6,7引数にはウィンドウのサイズを設定できる。
これらの引数は自分で自由に設定できるが、CW_USEDEFAULT
を使う事で、Windowsが設定してある値を使うこともできる。