【win32 アプリケーションの動作についての解説。】

先ほどの関数、WinMain および WndProc であるが、ここで解説を行う事にする。

まずは、WinMain である。
WinMain 関数でやるべき事は4つある。それらを列挙すると。

    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX); 
    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = (WNDPROC)WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
    wcex.hCursor        = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = NULL;
    wcex.lpszClassName    = "mission1";
    wcex.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);
    RegisterClassEx(&wcex);

まず、上記の部分ここは、ウィンドウクラスの登録を行っている。
あまり重要な事は含まれていないが、注目は、wcex.lpfnWndProc へ 後述の関数WndProc を登録している事くらいであろうか。

詳しくはWin32 API についてのリファレンスで、構造体 WNDCLASSEX および 関数 RegisterClassEx についての項を参照されたい。


次に、ウインドウを作る部分。

    HWND hWnd;
    hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,wcex.lpszClassName,"Mission1",
                WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
                CW_USEDEFAULT,0,640,480,NULL,NULL,hInstance,NULL);
    if( !hWnd )
        return FALSE;

    RECT    bounds,client;
    GetWindowRect(hWnd,&bounds);
    GetClientRect(hWnd,&client);
    MoveWindow(hWnd,bounds.left,bounds.top,
        640 * 2 - client.right,
        480 * 2 - client.bottom,
        false );

    ShowWindow( hWnd, nCmdShow );
    UpdateWindow( hWnd );

詳しくはWin32 API に関してのリファレンスを参照してもらいたい。

簡単には、 を行っている。

GetWindowRect/GetClientRect/MoveWindow もWin32 API 関数である。

ここでは具体的にはウィンドウのサイズ調整を行っている。

CreateWindowEx 関数でサイズを指定しているが、これはあくまで ウィンドウの枠を含めた外側のサイズである。
ゲーム的にはウィンドウの内側(描画可能部分)のサイズを指定したいのであり、 実際にできたウィンドウのサイズを取得して、 足りない分を拡大している。


次はメインループ部分

    MSG        msg;
    while(true){
        if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
            if(msg.message == WM_QUIT)
                break;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }else{
        }
    }

この部分は基本的には無限ループになっている。

PeekMessage・TranslateMessage・DispatchMessage については、 Win32 API に関するリファレンスを参照してもらいたい。

簡単に説明すると、

Win32 システムより終了メッセージ(WM_QUIT)を受け取ると、メインループを抜ける ようにしている。

最後に、終了処理。

    return msg.wParam;

解説の要もあるまいが、 この終了処理は、WM_QUIT メッセージを受け取った時、 WM_QUIT とともに受け取ったパラメータ wParam を 返値としてリターンしている。
それだけである。


さて、次にWndProc これは、ウインドウクラスとともに登録されており、
メインループ内の DispatchMessage 関数より呼び出されるコールバック
関数である。

LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
    switch (message){
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return    0;
}

やっている事はきわめて単純である。
PostQuitMessage・DefWindowProc は、Win32 が提供している API なので、API 関連のリファレンスを参照して欲しい。

簡易に解説すると、

以上で説明は終わり。
本題に戻りましょう。

戻る