2.2 アプリの見栄えアップ Menuへ戻る

  前回のソースはコンパイルできたでしょうか,では前回のソースの解説です.と
言うのを期待しているかもしれませんが,それはしません.Windowsにおいてすべて
を理解しながらプログラミングを学ぶ事は不可能です.

  なぜなら難解すぎるのです.それでは前にすすめません.莫大なる謎をかかえなが
らひたすら進むというのが Windowsプログラムの基本だと考えます.しかもワタクシ
あのプログラムをキチント説明できる自信はありません.

  あのソースは全てのプログラムの雛形として通用するものです.よってあのソー
スに味付けしていくことでプログラムを作っていくのがベストです.どうしても前の
プログラムの部分部分の意味が知りたければ Win32プログラミング入門か何かを読め
ば書いてあるでしょうが,まず何を言っているのかわからない事は保証します.

  よってこのまま作っていきます.さて,今回VCの5.0がリリースされ,4.0
の環境がなくなってしまいました.よって Developer Studio の操作方法がキチント
解説できなくなりました.一応分かるように書くつもりですが,適当に解釈して下さ
い.それでは見栄えアップの第一段階としてアイコンを書く!です.

  [挿入]から[リソース]とし,アイコンのリソースを追加してください.そして
クールなアイコンを書きましょう.....出来ましたか?次にリソースファイルを
保存して下さい.名前は適当に付けましょう.そして[プロジェクト]に[ファイル
を追加]として今保存したリソースを追加しましょう.リソースとはまあ簡単に言え
ば,材料という事で,アプリケーションの材料という事でしょうか.

  では,その作ったクール?なアイコンをプログラムに登録する必要があります.
まず前回のソースの #include  の次の行に

#include "resource.h"

  の一行を追加してください.リソースを使用する場合に,その内容の定義を書いて
あるのが "resource.h" です.ちなみにリソースの内容を変更するのには左にあるプ
ロジェクトワークスペースウインドウの下にあるタブのリソースをクリックし,そし
て編集したいリソースをダブルクリックすれば編集ウインドウが開きます.

  次に挿入したリソースに名前を付ける必要があります.上記の様に編集ウインドウ
を開いてください.アイコンが表示されている場所の白い部分をダブルクリックする
とプロパティウインドウが出るので,リソースIDを IDR_MAINFRAME としてください.
名前はどうでもいいのですが,違う名前を付けた場合,以降の文章も適宜読み替えて
下さい.

  その後,

    wc.hIcon = LoadIcon((HINSTANCE)NULL, IDI_APPLICATION);

  となっていた部分を

    wc.hIcon = LoadIcon((HINSTANCE)hInstance, MAKEINTRESOURCE(IDR_MAINFRAME));

  と編集してください.まず,wc ですが,前の部分に

WNDCLASS wc;

  として WNDCLASS型の構造体として宣言しています.そして,構造体の中身である
hIcon に今作ったアイコンを指定するのです.

     LoadIcon((HINSTANCE)hInstance, MAKEINTRESOURCE(IDR_MAINFRAME));

  の部分が何をやっているかは,どうでもいいのです.大事なのは「こうすれば,
どうなる」ということです.この WNDCLASS 構造体に自分の作りたいプログラムの
情報を代入し,次の部分に書いた RegisterClass 関数によってWindowsに登録して
いるのです.

  では,一度コンパイルしてみましょう.どうですか?アイコンは変わったでしょう
か?次にプログラムのタイトルを付けましょう.ここでは Win32 Study とします.
これを決定するのは CreateWindow 関数 の第二引数です.

    hwnd = CreateWindow("TEST", "TARO++", WS_OVERLAPPEDWINDOW,・・・・・・
                                ^^^^^^^^
  となっているところを "Win32 Study"としましょう.これでタイトルが変更され
ます.この CreateWindow は名前の通りウインドウを作成します.そして,作られる
ウインドウに関するいろいろな情報を引数として持ちます.詳しいことはヘルプの
中に書いてありますが,英語だし,様々な情報が書いてあり,わからないでしょう.

  では,さらに改良を進めましょう.いつも適当な大きさで出てくるのは腹立たしい
ので作成されるウインドウの大きさを指定してやりましょう.これは CreateWindow の
第6引数に横幅,第7引数に縦の幅を指定すれば実現できます.では次の様に書き換
えて下さい.ここでは特別意味はないですが 640*480 にします.ちなみに,
変更する前の値は CW_USEDEFAULT となっているのですが,この意味は Windows の気
分に任せるよ,という意味です.

    hwnd = CreateWindow("TEST", "Win32 Study", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,        /*  ←ここを変更  */
        (HWND)NULL, (HMENU)NULL, hInstance, (LPVOID)NULL);

  さて,変更した所の前の第4,5引数に CW_USEDEFAULT とあるのに気づいたでしょ
うか?ここはウインドウの出る位置を決める引数です.ここでは Windows の気分に
任せるとしてありますが,「画面左上に出したい」と思うのならば 0,0 と書き換
えると実現できます.

  次なる野望はメニューを作る!です.プロジェクトワークスペースウィンドウの
リソースを表示させて,そこで右クリックすれば「挿入」というメニューがあるので
そこからメニューリソースを追加してください.そして四角く灰色になっている部分
をダブルクリックし,キャプションという部分に ファイル(&F) キャプションというのは
表示される内容という風に覚えてください.

  そして,ファイル となっている部分をクリックし,その子メニューとなる部分を作り
ます,先ほどと同様に四角く灰色になっている部分をダブルクリックし,また,キャ
プションの所に文字列を書きます.ここでは終了メニューを作るため,終了(&X) と
書いてやりましょう.今度はさっきと違ってメニューIDというのを指定してやらなけ
ればなりません. ID とある部分に IDR_MAINFRAME と書いてください.

  先ほどから & をつけてアルファベットを書いていますが,表示ではアンダーライン
のついたアルファベットとなり,キーボードで操作する時用のショートカットとなり
ます.なくても構いませんが,優秀なプログラマはキーボードで使用される場合も考慮
すべきです.

  さて,メニューリソースが出来た所で,それを WNDCLASS にセットし,Windows に
メニューがあるよ,という事を示さなければなりません.さっきと同じように,
WNDCLASS 構造体の lpszMenuName メンバにセットします.そのため

    wc.lpszMenuName = MAKEINTRESOURCE(IDR_MAINFRAME);

  という風に書き直してください.ではコンパイルしてみましょう.メニューが追加
されているのを確認しましたか?でもおかしな事に気づいたでしょう.終了という
メニューを選んでも終了しません.当たり前です.何も処理を書いていないのですか
ら,何も動作しません.

  では,どこに書けばいいのか?という事ですが,メニューを選ぶという動作によって
Windows から メニューが押されたよ,というメッセージが送られてきます.それを
処理する事によって動作を組み込みます.では,Windowsから送られてきたメッセージ
をどこで処理するのか?というのも前回はなしました通り,WndProc です.このWndProc
を見てください.引数に message というのがありますね.ここに送られてきたメッセ
ージが入っているのです.

  では,lParam や wParam についても話しをします.実はメッセージというのは
message だけではなく,lParam や wParam も含めて考えてください.lParam や wParam
とは何なのかというと,単にメッセージだけだと情報が少なすぎます.マウスがクリッ
クされた.というメッセージでは情報が足りません.どこを?といった付加情報が必ず
必要です.そういった付加情報に使われるのが lParam や wParam です.型は WPARAM
型と LPARAM 型 という風になっていますが,単なる 32ビット整数型です.

  では,実際にメニューがどうなっているのかを考えます.送られてくるメッセージは
WM_COMMAND というメッセージで,wParam の下位16ビットに選ばれたメッセージの
中身が入っています.では実装してみましょう.WndProc の switch(message) 以下に
message が WM_COMMAND の場合についての処理を書きましょう.実はすでに書いてある
WM_DESTROY は終了する時に送られてくるメッセージなので,そこと同じ事を書いてや
れば,終了できます.では switch の中に次の case 文を挿入してください.

    case WM_COMMAND:
        switch( LOWORD(wParam) ) /* LOWORD(wParam)は下位を取り出すマクロ */
        {
            case IDM_APP_EXIT:
                PostQuitMessage(0);
                break;
        }
        break;

  できましたでしょうか? LOWORD マクロは 32ビットの引数の中で下位16ビットを
取り出すためのマクロです.マクロとは何かについては詳しく説明しませんが,関数
と同じ様に考えてください.

  とりあえず,急ぎ足で中身を Windowsアプリ の様に近づける方法を説明しました.
かなりチンプンカンプンかもしれません.いろいろと値を変えたり,独自に実験して
みたりと色々といじってください.わからない事が起こると思いますので,どしどし
質問して下さい.では次回は 描画 に関することをやります.さようなら