Win32 App Creating a Window - yoshimune/LearningDirectX11 GitHub Wiki

This page refers to 【Creating a Window

Window Classes

window class はいくつかのウィンドウが共通する可能性のある一連の動作を定義します。例えば、ボタングループでそれぞれのボタンがボタンクリックで似たような動作をする、などです。もちろん、ボタンは完全に同一ではありません。各ボタンは、それぞれのテキストを保持し、それぞれの座標を持っています。それぞれのウィンドウで固有のデータは insatance data と呼ばれます。

全てのウィンドウはウィンドウクラスと関連付けられていないといけません。たとえ、プログラムが一つのインスタンスのみを作成する場合でも同様です。理解する上で重要なのはウィンドウクラスC++で言うところの"class"と異なるものだということです。むしろ、OSによって内部的に使用されるデータ構造です。ウィンドウクラスは実行中にシステムに登録されます。新しいウィンドウクラスを登録する場合は、WNDCLASS構造体を入力します。

// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";

WNDCLASS wc = {};

wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
  • lpfnWndProc はアプリケーション定義関数が_window procedure_またはWindowProcを呼び出すためのポインタです。_window procedure_はほとんどのウィンドウの動作を定義します。_window procedure_については後で詳述します。
  • hInstance はアプリケーションインスタンスのハンドルです。wWinMainの引数から取得してください。
  • lpszClassName はウィンドウクラスを識別する文字列です。

クラス名は現在のプロセスに対してローカルとなっています。よって名前はプロセス内でユニークになっている必要があります。しかし、標準のWindowsコントロールにもクラスがあります。もし、このコントロールのうちいくつかを使用する場合、コントロールクラス名がコンフリクトしないように名前を取り上げる必要があります。例えば、ボタンを制御するウィンドウクラスは"Button"です。

WNDCLASS 構造体は、ここでは表示されていない別のメンバーを持っています。今回はそれらのメンバーには0をセットしています。MSDNのドキュメントにこの構造体の詳細が説明されています。

次に、WNDCLASS構造体のアドレスをRegisterClass関数に渡します。この関数はウィンドウクラスをOSに登録します。

RegisterClass(&wc);

Creating the Window

新しいウィンドウインスタンスを作成するために、CreateWindowEx関数を呼び出します。

//Create the window.

HWND hwnd = CreateWindowEx(
	0,								// Optional window styles.
	CLASS_NAME,						// Window class
	L"Learn to Program Windows",	// Window text
	WS_OVERLAPPEDWINDOW,			// Window style

	// Size and position
	CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

	NULL,		// Parent Window
	NULL,		// Menu
	hInstance,	// Instance handle
	NULL		// Additional application data
);

if (hwnd == NULL)
{
	return 0;
}

各パラメータの詳細はMSDNのドキュメントを参考にしてください。ここでは簡単な紹介に留めます。

  • 最初の引数は、ウィンドウにいくつかのオプションビヘイビア(例えば、透明なウィンドウ)を指定できます。この引数に0をセットするとデフォルトのビヘイビアになります。
  • CLASS_NAME はウィンドウクラスの名前です。
  • ウインドウテキストは異なる形式のウィンドウから異なる方法で使用されます。もしウィンドウがタイトルバーを持つ場合、テキストはタイトルバーで表示されます。
  • ウインドウスタイルは、ウインドウのいくつかのルック・アンド・フィールを定義するフラグをセットします。定数WS_OVERLAPPEDWINDOWは実際にはいくつかのビット単位のORと組み合わせたフラグです。これらのフラグと合わせてウインドウタイトルバー、ボーダー、システムメニュー、最小化最大化ボタンを提供します。このフラグの設定は、トップレベルアプリケーションでは最も一般的な形式になっています。
  • ポジションとサイズは、デフォルトの定数CW_USEDEFAULTを指定しています。
  • 次の引数は新しいウィンドウのParentWindow(もしくはOwnerWindow)を設定します。子ウィンドウを作る場合は設定します。トップレベルウィンドウの場合はNULLを指定します。
  • アプリケーションウィンドウでは、次の引数がウィンドウのメニューを定義します。この例ではメニューは使用しません。よって値はNULLです
  • _hInstance_はインスタンスハンドルです。参照:WinMain: The Application Entry Point
  • 最後の引数は**void* **形式の任意のポインタです。この値をwindow procedureへデータ構造を渡すために使うことができます。使い方の例:Managing Application State

CreateWindowEx は新しいウィンドウのハンドルか0を返します(関数がエラーを起こした場合は0を返す)。ウィンドウの表示するにはShowWindowへウィンドウハンドルを渡します。

ShowWindow(hwnd, nCmdShow);

hwnd パラメーターはCreateWindowExから返されたウィンドウハンドルです。nCmdShow パラメータはウィンドウの最小化・最大化に使用することができます。OSはこの値をwWinMain関数を通してプログラムに渡します。

これはウインドウを作成する完全なコードです。WindowProcを関数記述より先に宣言することを覚えておいてください。

// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";

WNDCLASS wc = {};

wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;

RegisterClass(&wc);

//Create the window.

HWND hwnd = CreateWindowEx(
	0,								// Optional window styles.
	CLASS_NAME,						// Window class
	L"Learn to Program Windows",	// Window text
	WS_OVERLAPPEDWINDOW,			// Window style

	// Size and position
	CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

	NULL,		// Parent Window
	NULL,		// Menu
	hInstance,	// Instance handle
	NULL		// Additional application data
);

if (hwnd == NULL)
{
	return 0;
}

ShowWindow(hwnd, nCmdShow);

まとめ

ウィンドウを表示する方法

  1. ウィンドウクラスを作成・登録する
  2. ウィンドウのインスタンスを作成する
  3. ウィンドウのインスタンスを表示する

ウィンドウは作成されました。ウィンドウにはなんのコンテンツも含まれていません。実際のGUIアプリケーションでは、ユーザーとOSからのイベントに反応を返します。次のセクションでは、ウィンドウメッセージがこの種の対話性を提供する方法について説明します。

Next:Win32 App Window Messages