ウィンドウの初期化
ウィンドウ生成時に発生するメッセージ
ウィンドウを生成した直後に、ウィンドウ内にコンテンツを表示するために必要な初期化処理が必要になります。ボタンやリストボックスなどの子コントロールの配置や、画像などの外部リソースを読み込むといった処理は、ウィンドウ生成後の初期化行程で行い、以降はウィンドウが破棄されるまで維持します。
CreateWindow() 関数または CreateWindowEx() 関数を使ってウィンドウを生成するとき、ウィンドウプロシージャには WM_CREATE メッセージが送信されます。WM_CREATE メッセージはウィンドウが表示される前に、ウィンドウの生成を続けるかどうかを問い合わせています。WM_CREATE メッセージに対して 0 を返せばウィンドウの生成を続け、-1 を返せばウィンドウを破棄することを表します。ウィンドウが WM_CREATE によって破棄された場合 CreateWindow() 関数は失敗し NULL を返します。
ウィンドウ生成時の情報は WM_CREATE メッセージの場合 lParam パラメータに 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 構造体のメンバに格納されています。
#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はウィンドウプロシージャで WM_CREATE メッセージを処理します。CreateWindow() 関数または CreateWindowEx() 関数によってウィンドウが生成されようとすると WM_CREATE メッセージが発行され SampleWindowProc() 関数に送出されます。このタイミングでは、まだ画面にウィンドウは表示されません。
WM_CREATE メッセージを受けると InitializeWindow() 関数を呼び出し、その結果をメッセージの戻り値としています。InitializeWindow() 関数ではメッセージボックスを表示し、ウィンドウの生成を続けるかどうかを確認します。このとき「いいえ」ボタンを押すと -1 を返し、ウィンドウの生成を拒否します。この場合、WM_CREATE メッセージを発行した CreateWindow() 関数または CreateWindowEx() 関数は失敗します。