7:ウィンドウの作り方
ウィンドウを作成するにはWin32APIの「CreateWindow」関数を呼び出せばOKです。しかし、その前にどのようなウィンドウを作りたいかをシステムに伝えなくてはいけません。そのシステムに伝えるための命令が「RegisterClass」です。登録するための情報は多くあるため、あらかじめ構造体に格納した後で、RegisterClassへと送り込みます。#include <tchar.h>
#include <windows.h>
int APIENTRY _tWinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpszCmdLine, int nCmdShow)
{
WNDCLASS wc; // 登録する情報を格納する構造体
wc.cbClsExtra = 0; // 構造体のサイズを拡張するバイト数(通常は0)
wc.cbWndExtra = 0; // ウィンドウのサイズを拡張するバイト数(通常は0)
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
// ウィンドウの背景を塗りつぶすためのブラシ。
// ここではシステムが用意している白一色で塗りつぶすブラシを割り当てている。
wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
// ウィンドウ上にマウスカーソルがきたときのマウスの形状
// ここではシステム標準の矢印形カーソルを登録している。
wc.hIcon = NULL;
// ウィンドウの左上に表示されるアイコン。
// 今回はNULL値を指定してアイコンを登録しない状態にしているが、
// LoadImage関数を使ってオリジナルアイコンを呼び出してもよい。
wc.hInstance = hInstance;
// ウィンドウを作るためのインスタンス(≒プログラムの)ハンドルを指定する。
// 通常はWinMainが呼び出されたときに格納されているhInstanceで問題ない。
wc.lpfnWndProc = ---;
// ウィンドウから通知されたイベントを処理するための関数を指定。
// 後で解説していくので、ここではいったん省略。
wc.lpszClassName = _T("Game");
// 登録するウィンドウのクラス名。
// この文字列を元に、Windowsがウィンドウの検索を行ったりできる。
wc.lpszMenuName = NULL;
// メニューのリソースID。
// 今回はメニューは作成しないのでNULL値。
wc.style = NULL;
//ウィンドウクラスのスタイル。
// 特に指定するものはないのでNULL値にしている。
// ウィンドウクラスの登録
if(RegisterClass(&wc) == NULL){
// ウィンドウクラスの登録に失敗したら、
// ウィンドウの作成が不可能なので、ここにて終了。
return 0;
}
return 0;
}
#include <tchar.h>
#include <windows.h>
int APIENTRY _tWinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpszCmdLine, int nCmdShow)
{
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = ---; //後で解説
wc.lpszClassName = _T("Game");
wc.lpszMenuName = NULL;
wc.style = NULL;
// ウィンドウクラスの登録
if(RegisterClass(&wc) == NULL){
return 0;
}
HWND hWnd = CreateWindow(
wc.lpszClassName, // 登録したクラス名
_T("クラスまみれのゲームプログラミング入門"),
// ウィンドウに表示するタイトル
WS_OVERLAPPEDWINDOW,
// ウィンドウのスタイル
// (タイトルバー、システムメニュー、最小化ボタンを使用)
CW_USEDEFAULT, // ウィンドウのx位置(システム標準値を使用)
CW_USEDEFAULT, // ウィンドウのy位置(システム標準値を使用)
640, // ウィンドウの幅
480, // ウィンドウの高さ
NULL,
// 親ウィンドウのハンドル
// このプログラムに親ウィンドウは存在しないのでNULLを渡します
NULL,
// メニューハンドル
// このプログラムにメニューは存在しないのでNULLを渡します
hInstance, // インスタンスハンドル
NULL
// ウィンドウ作成時のイベントへ渡すデータのポインタ
// 渡すデータはないのでNULLを指定します
);
// ウィンドウを表示します
// hWnd : 表示するウィンドウのハンドル
// nCmdShow : 最初のウィンドウの状態
// ここではショートカットなどから報告された
// 初期ウィンドウ状態の指定を利用しています
ShowWindow(hWnd, nCmdShow);
return 0;
}
#include <tchar.h>
#include <windows.h>
//ウィンドウイベントを処理する関数
// hWnd : イベントが発生したウィンドウのハンドル
// msg : 発生したイベントの内容
// wParam : イベントから通知されたデータ(イベントにより内容は異なります)
// lParam : イベントから通知されたデータ(イベントにより内容は異なります)
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_DESTROY:
// ウィンドウが閉じられたときにこの部分が実行される
PostQuitMessage(NULL);
// プログラムの終了をシステムに通知する関数です
// カッコ内の数値は終了イベント(WM_QUIT)に
// 通知したいデータを格納します
// (今回は通知するデータはないのでNULL)
break;
default:
// 作成するプログラムに必要のないイベントであれば
// システムにイベント処理を丸投げする命令で対処する
return (DefWindowProc(hWnd, msg, wParam, lParam));
}
return (0);
}
int APIENTRY _tWinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpszCmdLine, int nCmdShow)
{
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc; //イベント処理関数を連結
wc.lpszClassName = _T("Game");
wc.lpszMenuName = NULL;
wc.style = NULL;
if(RegisterClass(&wc) == NULL){
return 0;
}
HWND hWnd = CreateWindow(
wc.lpszClassName,
_T("クラスまみれのゲームプログラミング入門"),
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
NULL, NULL, hInstance, NULL );
ShowWindow(hWnd, nCmdShow);
return 0;
}
#include <tchar.h>
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_DESTROY:
PostQuitMessage(NULL);
break;
default:
return (DefWindowProc(hWnd, msg, wParam, lParam));
}
return (0);
}
int APIENTRY _tWinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpszCmdLine, int nCmdShow)
{
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc; //イベント処理関数を連結
wc.lpszClassName = _T("Game");
wc.lpszMenuName = NULL;
wc.style = NULL;
if(RegisterClass(&wc) == NULL){
return 0;
}
HWND hWnd = CreateWindow(
wc.lpszClassName,
_T("クラスまみれのゲームプログラミング入門"),
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
NULL, NULL, hInstance, NULL );
ShowWindow(hWnd, nCmdShow);
// ウィンドウが閉じられるまで永久にループさせます
MSG msg;
while(TRUE){
// ウィンドウに通達されようとしているイベントを取得
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
// 終了イベントだったならループを抜けます
if(msg.message == WM_QUIT) break;
// 仮想キーメッセージを文字メッセージへ変換します
TranslateMessage(&msg);
// 実際にウィンドウへイベントを通達
DispatchMessage(&msg);
}else{
// イベントが発生していなかったのなら
// ここで空き時間に行いたい処理内容を記述
Sleep(10);
}
}
return 0;
}
最近のOSはウィンドウのデザインがバラエティに富んでいるため、ウィンドウの枠のサイズを取得するだけでは完全ではないこともあります。そのためここではウィンドウ領域とクライアント領域の差分よりウィンドウサイズを調整しています。
HWND hWnd = CreateWindow(
wc.lpszClassName,
_T("クラスまみれのゲームプログラミング入門"),
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT,
640, 480, NULL, NULL, hInstance, NULL );
RECT r1, r2;
GetClientRect(mainWnd, &r1);
GetWindowRect(mainWnd, &r2);
MoveWindow(mainWnd, r2.left, r2.top,
640 + ((r2.right - r2.left) - (r1.right - r1.left)),
480 + ((r2.bottom - r2.top) - (r1.bottom - r1.top)), FALSE);