窓の工作室 〜 Windows アプリを作ろう!〜

〜 第5回 ボタンをつけてみる(2) 〜

ボタンが押されたら何が起こる?

今回も前回からの続きで、ウインドウの上に作ったボタンが押された場合の処理について考えてみようと思います。
前回はベースとなるウインドウ(親ウインドウと呼ばれます)が作成されたというイベントが発生した時にボタンのウインドウを作成するようにしましたが、今回はその作成したボタンが押された場合にどのようなイベントが発生するかについて調べていきます。

ボタンが押された時に発生するイベント

前回に出てきたイベント(正確にはメッセージ)には、親ウインドウが作成された時に発生する WM_CREATE と、親ウインドウが破壊される時に発生する WM_DESTROY の2つがありました。
今回のボタンが押された時に発生するイベントも基本的にはこれらの親戚と考えていいです。

では、とりあえず前回の case WM_CREATE: の処理に続いて以下のような処理を追加してください( case WM_COMMAND から break; までの青色の部分です)。

LRESULT CALLBACK WindowProcedure(...)
{
    static HWND hwndButton = 0;

    switch (message)
    {
           case WM_CREATE:
           hwndButton = CreateWindow("button", "Click Here", 
                        WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                        0, 0, 200, 50, hwnd, (HMENU)1,
                        ((LPCREATESTRUCT)lParam)->hInstance, NULL);
           return 0;
           break;

           case WM_COMMAND:
           if (LOWORD(wParam) == 1 &&
               HIWORD(wParam) == BN_CLICKED &&
               (HWND) lParam == hwndButton) {
               DestroyWindow(hwnd);
           }
           return 0;
           break;

           case WM_DESTROY:
           PostQuitMessage(0);
           :
    }
    return 0;
}

追加できたらコンパイル( Execute -> Compile )をして、タイプミスなどによるエラーがなければ実行( >> Execute << ボタンをクリック)してみてください。
「Click Here」と書かれたボタンを押すと、ウインドウが終了するようになっているはずです。

イベントを誰が発生させたのかを知る

さて、上記の処理は一体どんなことをやっているのでしょうか?
とりあえず1つ1つ見ていくことにしようと思います。

ボタンが押された時にイベントが発生し、それが WindowProcedure() 関数にメッセージとして伝えられる時には WM_COMMAND というものになります。
この WM_COMMAND は別にボタンに限らず、いろいろな場合(スクロールバーを動かした時なども該当するでしょう)に送られてくるメッセージなのです。
と言うことで、何かが起こったのは分かるのですが、それがどこで起こったのかを知る必要があるのです。
それを識別するのが wParamlParam という変数です。いずれも WindowProcedure() 関数に message と共に送られてくる情報です。上の例では省略しているため、お手元の WindowProcedure() の引数を見てください。

まずはどのような種類のウインドウで発生したかを知るのが lParam です。この lParam が前回の CreateWindow() で作成した hwndButton であれば、イベントが作成されたボタンで発生したことが分かるのです。

また今回はボタンが1つだけですが、場合によっては複数のボタンが作成される場合もあります。その場合、CreateWindow() で作られたということだけでは分からないことがあります。
それを知るのが wParam です。これには複数の情報が含まれており、特定の種類のウインドウで何が起こったかを知ることができます。
まず LOWORD を使って得られるものが同じ種類のウインドウを識別するための番号で、これは CreateWindow() の第9引数で (HMENU)1 として定義された番号に該当するものです。
試しに CreateWindow() の (HMENU) の番号か、LOWARD(wParam) で調べている番号のどちらかを 1 から変更してコンパイル・実行をしてみると、ボタンを押してもウインドウが終了しなくなります。番号が一致しないため、処理を実行するイベントではないという判断がなされるのです。

最後に HIWORD で wParam から取得できる情報ですが、これは何をされたかを知るためのものです。今回のボタンではクリックされるくらいしかないのですが、他の種類のウインドウだった場合、いろいろなこと発生する可能性がありますので、その時に活躍することとなります。

ここまで来れば後はウインドウを終了させる処理だけです。これには DestroyWindow() という、まさにその名の示すままという関数を使用します。この引数に終了させたいウインドウを指定すればOKです。
ちなみにここで指定されている hwnd って何者でしょう?しばらく見てなかったので忘れているかもしれませんが、第3回に出てきた WinMain() 関数の中で作られている何もないウインドウ、すなわち今回のボタンが乗っている親ウインドウのことです。
よって、この hwnd を引数にして DestoryWindow() を呼べばウインドウ全体が終了するというわけです。

試しにこの hwnd を今回作ったボタンを表す hwndButton に変更してコンパイル・実行を行なうと、ボタンを押した瞬間にそのボタンだけが消えます(笑)。

と言うことで、前回、今回でボタンを作ってそれが動作するところまでを作成することができました。
さて、次は何をしましょうかね?実はまだボタン関連でやってないことがありますので、そちらをついでにやってしまおうかなと考えています。でも、もし気が変わったらごめんなさいね。

prev next


戻る