第7章 もう少し複雑なメニュー


前回は最も簡単なメニューの例を示しました。 今回は、もう少し複雑なメニューを示します。 まず、リソース・スクリプトを次のように書き換えましょう。

#include "windows.h" #include "sample03.h" ////////////////////////////////////////////// // // Menu (sample03.rc) // SAMPLE03 MENU DISCARDABLE BEGIN POPUP "ファイル" BEGIN MENUITEM "終了",IDM_END MENUITEM "テスト",IDM_TEST END POPUP "ヘルプ" BEGIN MENUITEM "About",IDM_ABOUT END END

どこが変わったかというとPOPUPというのが増えました。 これは、何かというと読んで字のごとくポップアップメニューです。 普通のアプリケーションでは「ファイル」を選択すると 第2段階のメニューが出ますね。そしてそのメニューから 「終了」などを選びます。この時「ファイル」をポップアップ項目といいます。 ポップアップ項目には、IDコードはありません。ポップアップ項目を 選択しても直接コマンドを実行しないからです。 それから、BEGINとENDを{と}で置き換えても問題ありません。

#include "windows.h" #include "sample03.h" ////////////////////////////////////////////// // // Menu (sample03.rc) // SAMPLE03 MENU DISCARDABLE { POPUP "ファイル" { MENUITEM "終了",IDM_END MENUITEM "テスト",IDM_TEST } POPUP "ヘルプ" { MENUITEM "About",IDM_ABOUT } END

というようにしても同じことです。好きな方で書いて下さい。 と、言っても自分でリソース・スクリプトを書くことはほとんどないと思われます。 メニューくらいならいいのですがダイアログボックスのリソース・スクリプトは とても手書きでは面倒です。 筆者はずっと以前「MS-DOSの次は必ずOS/2の時代がやってくる。 Windowsは過渡的なものである。OS/2をジェット機にたとえるならば Windowsはプロペラ飛行機でしょう」 という雑誌の記事を鵜呑みにして一生懸命OS/2のプログラミングを 勉強したものです。ところがその頃はリソース・スクリプトは全くの手作業 でした。グラフ用紙にダイアログボックスを書いて、座標を求めるという 有様です。うんざりして途中で挫折してしまいました。 でも、今考えてみるとOS/2(当時の)のプログラミングと WindowsのSDKによるプログラミングはかなり似ています。 あ、よけいなことを書いてしまいました。

IDM_TESTとIDM_ABOUTが追加になったのでヘッダーファイルにも シンボル名とシンボル値を追加して下さい。

// sample03.h #define IDM_END 100 #define IDM_TEST 200 #define IDM_ABOUT 300

次に、プロシージャ部分も変更になりますね。 ここでは、「テスト」とか「About」が選択されても 単にメッセージボックスを表示するだけとします。

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_COMMAND: switch(LOWORD(wParam)) { case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0L); break; case IDM_TEST: MessageBox(hWnd, (LPCSTR)"テストが押されました", (LPCSTR)"test", MB_OK); break; case IDM_ABOUT: MessageBox(hWnd, (LPCSTR)"ABOUTが押されました", (LPCSTR)"About", MB_OK); break; } break; //このbreakを忘れやすい!! case WM_DESTROY: PostQuitMessage(0); break; case WM_PAINT: ShowMyText(hWnd); break; default: return(DefWindowProc(hWnd, msg, wParam, lParam)); } return (0L); }

ここで、うっかり間違えるのが case WM_COMMANDの最後のbreakの書き忘れです。 (case WM_DESTROY:の1つ前の行)これを忘れると たとえばIDM_TESTが選ばれて、メッセージボックスが表示されたあと 続けてWM_DESTROYのところが実行されてプログラムが 終了してしまいます。実につまらないことですが これがなかなかわからないバグとなります。 こんな間違いをするのは筆者だけかな・・・

MessageBox関数についてはすでに、 C言語編第57章で書きましたが 復習のためもう一度プロトタイプを書きます。

int MessageBox( HWND hWnd, // handle of owner window LPCTSTR lpText, // address of text in message box LPCTSTR lpCaption, // address of title of message box UINT uType // style of message box );

uTypeのところはアイコンを表示したりいろいろなことができるのですが また、後の章で解説します。

それと、メニューの名前もMENU03に変えたのでWinMain関数も 少し変更になりますね。

if (!hPreInst) { myProg.style =CS_HREDRAW | CS_VREDRAW; myProg.lpfnWndProc =WndProc; myProg.cbClsExtra =0; myProg.cbWndExtra =0; myProg.hInstance =hInstance; myProg.hIcon =NULL; myProg.hCursor =LoadCursor(NULL, IDC_ARROW); myProg.hbrBackground =GetStockObject(WHITE_BRUSH); myProg.lpszMenuName ="SAMPLE03"; myProg.lpszClassName =szClassNme; if (!RegisterClass(&myProg)) return FALSE; }


第2階層のメニューが表示されるようになりましたね。 では、問題ですが終了を選択してもいきなりプログラムが 終了してしまうのではなく、「終了してもよいかどうか」 をたずねてくるメッセージボックスを出すにはどうしたらよいでしょうか。 回答は、次章で行います。


[SDK Index] [総合Index] [Previous Chapter] [Next Chapter]

Update Mar/27/1997 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。