WisdomSoft - for your serial experiences.

ウィンドウの初期化

CreateWindow() 関数または CreateWindowEx() 関数を使ってウィンドウを生成すると、ウィンドウが表示される前に WM_CREATE メッセージがウィンドプロシージャに送られます。このメッセージを処理することで、ウィンドウ起動時に初期化を行えます。

ウィンドウ生成時に発生するメッセージ

ウィンドウを生成した直後に、ウィンドウ内にコンテンツを表示するために必要な初期化処理が必要になります。ボタンやリストボックスなどの子コントロールの配置や、画像などの外部リソースを読み込むといった処理は、ウィンドウ生成後の初期化行程で行い、以降はウィンドウが破棄されるまで維持します。

CreateWindow() 関数または CreateWindowEx() 関数を使ってウィンドウを生成するとき、ウィンドウプロシージャには WM_CREATE メッセージが送信されます。WM_CREATE メッセージはウィンドウが表示される前に、ウィンドウの生成を続けるかどうかを問い合わせています。WM_CREATE メッセージに対して 0 を返せばウィンドウの生成を続け、-1 を返せばウィンドウを破棄することを表します。ウィンドウが WM_CREATE によって破棄された場合 CreateWindow() 関数は失敗し NULL を返します。

ウィンドウ生成時の情報は WM_CREATE メッセージの場合 lParam パラメータに CREATESTRUCT 構造体へのポインタが格納されています。

CREATESTRUCT 構造体
typedef struct tagCREATESTRUCT { 
    LPVOID    lpCreateParams; 
    HINSTANCE hInstance; 
    HMENU     hMenu; 
    HWND      hwndParent; 
    int       cy; 
    int       cx; 
    int       y; 
    int       x; 
    LONG      style; 
    LPCTSTR   lpszName; 
    LPCTSTR   lpszClass; 
    DWORD     dwExStyle; 
} CREATESTRUCT;

この構造体は dwExStyle メンバから逆順に CreateWindowEx() 関数のパラメータに一致します。ウィンドウを生成した CreateWindow() 関数または CreateWindowEx() 関数の引数に指定された値が、そのまま CREATESTRUCT 構造体のメンバに格納されています。

コード1
#include <windows.h>
#define WINDOWS_CLASS_NAME TEXT("WisdomSoft.Sample.Window")

int InitializeWindow(CREATESTRUCT* createWindowArgs)
{
	TCHAR message[1024];
	int messageResult;
	wsprintf(message,
		TEXT("ウィンドウクラス:%s\nタイトル:%s\nウィンドウを生成しますか?"),
		createWindowArgs->lpszClass, createWindowArgs->lpszName
	);

	messageResult = MessageBox(NULL, message, TEXT("確認"), MB_YESNO | MB_ICONINFORMATION);

	if (messageResult == IDNO)
		return -1;
	return 0;
}

LRESULT CALLBACK SampleWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch(uMsg) 
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_CREATE:
		return InitializeWindow((CREATESTRUCT*)lParam);
	default:
		return DefWindowProc(hwnd , uMsg , wParam , lParam);
	}

	return 0;
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	HWND window;
	WNDCLASSEX wcx;
	int returnCode = 0;

	wcx.cbSize = sizeof(WNDCLASSEX);
	wcx.style = CS_HREDRAW | CS_VREDRAW;
	wcx.lpfnWndProc = SampleWindowProc;
	wcx.cbClsExtra = 0;
	wcx.cbWndExtra = 0;
	wcx.hInstance = hInstance;
	wcx.hIcon =  NULL;
	wcx.hCursor = NULL;
	wcx.hbrBackground = (HBRUSH)COLOR_BACKGROUND + 1;
	wcx.lpszMenuName = NULL;
	wcx.lpszClassName = WINDOWS_CLASS_NAME;
	wcx.hIconSm = NULL;

	if (!RegisterClassEx(&wcx)) 
	{
		OutputDebugString(TEXT("Error: ウィンドウクラスの登録ができません。\n"));
		return 0;
	}

	window = CreateWindowEx(
		WS_EX_LEFT, WINDOWS_CLASS_NAME, TEXT("Window Title"),
		WS_OVERLAPPEDWINDOW | WS_VISIBLE,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, NULL, hInstance ,NULL
	);
	if (!window)
	{
		OutputDebugString(TEXT("Error: ウィンドウが作成できません。\n"));
		return 0;
	}
	
	while(TRUE)
	{
		MSG msg;
		int r = GetMessage(&msg, NULL, 0, 0);
		if (r > 0) DispatchMessage(&msg);
		else if(r == -1)
		{
			OutputDebugString(TEXT("Error: メッセージの取得に失敗しました。\n"));
			break;
		}
		else
		{
			returnCode = msg.wParam;
			break;
		}
	}

	return returnCode;
}
実行結果
コード1 実行結果

コード1はウィンドウプロシージャで WM_CREATE メッセージを処理します。CreateWindow() 関数または CreateWindowEx() 関数によってウィンドウが生成されようとすると WM_CREATE メッセージが発行され SampleWindowProc() 関数に送出されます。このタイミングでは、まだ画面にウィンドウは表示されません。

WM_CREATE メッセージを受けると InitializeWindow() 関数を呼び出し、その結果をメッセージの戻り値としています。InitializeWindow() 関数ではメッセージボックスを表示し、ウィンドウの生成を続けるかどうかを確認します。このとき「いいえ」ボタンを押すと -1 を返し、ウィンドウの生成を拒否します。この場合、WM_CREATE メッセージを発行した CreateWindow() 関数または CreateWindowEx() 関数は失敗します。