Win32/64アプリ開発 003 基礎の理解続き

提供:yonewiki
2023年10月19日 (木) 16:33時点におけるYo-net (トーク | 投稿記録)による版 (→‎概要)

Win32/64_アプリケーション開発に戻る。

前の記事:Win32/64アプリ開発 002 基礎の理解

次の記事:Win32/64アプリ開発 004

概要

 前の記事の続きです。


LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
省略
}


 LRESULT型の戻り値や関数規約のCALLBACKとかがついてますが、ウィンドウプロシージャ関数の定義です。関数規約によって特殊な関数としてコンパイラが扱ってくれます。CALLBACKは実際は__stdcallというキーワードになっています。LRESULTはLONG_PTR型を意味していて更に、LONG_PTR型はlong long型が元になっています。ようするに64ビットの整数です。そんなに長いビットが必要な返り値ではないですが、このように定義することになっています。


 Windowsから送られてくるメッセージから4つの引数が受け取ることが出来るようになっています。それぞれの引数について確認しておきます。


■WndProc(HWND, UINT, WPARAM, LPARAM)

第1引数: HWND hWnd

 メッセージを受け取ったウィンドウハンドル番号。どのウィンドウに対して送られてきたものなのかがわかります。


第2引数: UINT msg

 送られてきたメッセージの番号。ものすごい数の種類がありますが、受け取る側は、必要なメッセージだけを見つけて処理する感じになります。


第3引数: WPARAM wParam

 送られてきたメッセージによって異なるパラメータです。メッセージによっては、wParamの上位ビットだけで意味を持っていたり、下位ビットだけで意味を持っていたりもします。


第4引数: LPARAM lParam

 こちらも送られてきたメッセージによって異なるパラメータです。メッセージによっては、lParamの上位ビットだけで意味を持っていたり、下位ビットだけで意味を持っていたりもします。


 次に以下のswitch文について確認しましょう。


    switch (msg){
    case WM_CREATE:
        省略
        break;
    case WM_SIZE:
        省略
        break;
    case WM_DESTROY:
        省略
        break;
    default:
        return (DefWindowProc(hWnd, msg, wParam, lParam));
    }


 これで受け取ったmsg毎の処理に分けています。全てのメッセージ番号には別名がついています。windows.hを読み込んでいれば、様々な定数が定義されています。これまでにも何の気なしにキーワードを使えていたのも、windows.hのおかげです。今回メッセージを受け取って処理をするのは3つのメッセージですので、その3つについて説明します。ここで一気に説明したいところですが、おびただしい数のメッセージがありますので、用途ごとに覚えた方が頭に入りやすいと思うので、目的をもってプログラムをする上で必要になったときに覚えていったほうが良いと思います。


WM_CREATE

 ウィンドウを生成されるような処理が起こった後に呼び出されます。最初のウィンドウ表示のShowWindow関数の後すぐにWM_CREATEが呼ばれるわけではなく、その関数を実行した後にやってくる2個ほどのメッセージが処理されるとウィンドウが表示されます。このあとでWM_CREATEというメッセージが送られてきます。ここでは最初のウィンドウが出来上がった所で次のウィンドウ作成処理を行うような処理を実施しようと思っています。


WM_SIZE

 ウィンドウのサイズ変更を検出する都度送られてくるメッセージです。マウスでウィンドウの縁をつかんで、ドラッグしたときには連続して送られてきます。このとき、lParamの上位32ビットに新しいWindow高さ値、下位32ビットに新しいWindowの横幅値が格納されています。ウィンドウの大きさが変わったので中身の表示も再描画してほしいことがほとんどですから、処理の終わりにはWM_PAINTというメッセージも発行して欲しいので、UpdateWindow関数を実行をすることが多いです。その前に再描画すべき無効領域の指定も必要となります。その辺の細かいところは、後ほど。


WM_DESTROY

 通常はWM_CLOSEメッセージのような閉じるボタンを押した時に送信されるメッセージを受け取って、DestroyWindow関数が呼ばれた時にWM_DESTROYメッセージが送信されます。次にPostQuitMessage関数を実行してWM_QUITメッセージを送るという手順になります。


 このようにメッセージ毎に次々と処理をリレー形式で行うこともあれば、メッセージにあわせてアプリケーション独自の処理を実行したりすることになります。


 メッセージを全部網羅して処理することはできないので、捕まえるメッセージ以外が来たときはswitchのdefault処理で規定値の動きをしてもらう関数DefWindowProc(ウィンドウプロシージャ関数の引数をそのまま4つ設定する)という関数を呼び出すことができます。


 それではひとつづつのメッセージ毎の処理を確認してみましょう。


        HWNDg_hEdit = CreateWindowEx(
            0,
            L"EDIT",  // エディットコントロールのクラス名
            L"Hello, World!",
            WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_HSCROLL | WS_VSCROLL,
            0, 0,  // エディットコントロールの位置(ウィンドウの左上に配置)
            0, 0,  // エディットコントロールのサイズ
            hWnd, NULL, NULL, NULL
        );
        break;


 2回目のCreateWindowEx関数呼び出しです。これで既に描画されたWindowの中にWindowを描画します。但し、ここではシステムの定義済みコントロールのクラス名を第2引数で設定しました。L"EDIT"としています。これでWindowの中にテキスト編集が可能なエディットコントロールが内蔵されます。後は、最初のWindow生成の要領と同じですが、最初はウィンドウの左上隅に大きさ0として、見えないウィンドウとして描画します。第9引数も最初のウィンドウでは親のウィンドウというものが無いのでNULLとしていましたが、最初のWindowのハンドル値が入ってるWndProc関数の引数でもあるhWndを設定しています。グローバル変数にも最初のWindowのハンドル値を格納してありますので、HWNDg_hWndと指定しても同じことです。


 WM_CREATEのメッセージが処理された後、InitializeWindow()関数というものを実行されます。メッセージ処理時の戻り値が-1ならInitializeWindow()関数が実行されることはありません。親ウィンドウを持つCreateWindowsEx関数を呼び出しても、再びWM_CREATEメッセージが投げられることはありません。


 

前の記事:Win32/64アプリ開発 002 基礎の理解

次の記事:Win32/64アプリ開発 004

Win32/64_アプリケーション開発に戻る。