メニューやら、ダイアログボックスを作るにはメインになる プログラムの他に、リソース・スクリプトといわれるものを書かなくてはいけません。 今回は、簡単なメニューの作り方を解説します。
と、いうことになります。まずリソース・スクリプトの書き方ですが たいていのコンパイラではメニュー・エディタとかそれに類したものが ついているはずです。これを使ってスクリプトを作ってもよいでしょう。 VC++の場合、少し問題もあります。ある程度エディタに作らせておいて あとで手動で修正してもかまいません。 リソース・スクリプトの拡張子はrcです。1.リソース・スクリプトを書く 2.ヘッダー・ファイルを書く 3.ソース・ファイルの修正
スクリプトの書き方はこんな感じです。 ヘッダーファイルは次のように書きます// sample02.rc #include <windows.h> #include "sample02.h" //IDM_ENDの値を定義する // メニュー SAMPLE02 MENU PRELOAD FIXED BEGIN MENUITEM "終了" IDM_END END
ここで、IDM_ENDというのは、筆者が勝手に付けた名前です。 シンボルコードといいます。メニュー関係は「IDM_何とか」 というように名前を付けるとわかりやすいですね。 リソーススクリプトは// sample02.h #define IDM_END 100
というようになります。メモリオプションはメニューの名前 MENU メモリオプション BEGIN MENUITEM "実際に表示されるメニュー項目" シンポルコード END
この位知っていれば十分でしょう。PRELOAD プログラム起動時にメモリにロードされる DISCARDABLE 不要になったらメモリから廃棄される FIXED メモリ上で固定 MOVEABLE メモリ上で移動可能
さて、VC++4.2ではこのリソーススクリプトを
プロジェクトに挿入する必要があります。
「挿入」「プロジェクトへファイルを追加」を選択して
sample02.rcを追加して下さい。
さて、次はソース・ファイルの修正です。 ウィンドウクラスの定義のところで
myProg.lpszMenuName = "SAMPLE02";
のようにメニュー名を指定して下さい。 これだけで、ビルドするとメニュー付きの ウィンドウができるはずです。ただし、メニューは 機能しません。(当たり前ですが・・)
次に、プロシージャを修正します。 メニュー項目がクリックされるとWindowsは WM_COMMAND メッセージを発生します。これを プロシージャのところで捕まえてやればよいですね。
WM_COMMANDメッセージを捕まえたらwParamの下位ワードを調べます。 ここに、IDM_何とかがあります。この場合捕まえるシンボルは 「IDM_END」なのでこれを捕まえます。捕まえたら SendMessage関数でWM_CLOSEメッセージを送り出します。 このメッセージがDefWindowProc関数にわたるとDestroyWindow関数 が呼び出されウィンドウが破棄されます。 このへんの所は、あとでもう少し詳しく解説する予定です。 今のところは、終了するときのパターンであると覚えておきましょう。 さて、このソースファイルにもIDM_ENDが登場するので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; } break; case WM_DESTROY: PostQuitMessage(0); break; case WM_PAINT: ShowMyText(hWnd); break; default: return(DefWindowProc(hWnd, msg, wParam, lParam)); } return (0L); }
#include "sample02.h"
が必要です。
では、プログラムを実行してみましょう。// sample02.cpp #include <windows.h> #include <string.h> #include "sample02.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void ShowMyText(HWND); char szClassNme[] = "ウィンドウクラス・ネーム"; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInst, LPSTR lpszCmdLine, int nCmdShow) { HWND hWnd; MSG msg; WNDCLASS myProg; 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 ="SAMPLE02"; myProg.lpszClassName =szClassNme; if (!RegisterClass(&myProg)) return FALSE; } hWnd = CreateWindow(szClassNme, "猫でもわかるプログラミング", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (msg.wParam); } 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; } break; case WM_DESTROY: PostQuitMessage(0); break; case WM_PAINT: ShowMyText(hWnd); break; default: return(DefWindowProc(hWnd, msg, wParam, lParam)); } return (0L); } void ShowMyText(HWND hWnd) { HDC hdc; char *str_org = "left=%d top=%d right=%d bottom=%d"; char strx[256]; PAINTSTRUCT paint; RECT rt; LPCSTR str = "猫でもわかるプログラミング\n粂井康孝 制作\n" "わかりやすくてためになる!"; GetClientRect(hWnd, &rt); wsprintf((LPSTR)strx, (LPCSTR)str_org, rt.left, rt.top, rt.right, rt.bottom); rt.top += 40; rt.bottom -= 40; rt.right -= 40; rt.left += 40; hdc = BeginPaint(hWnd, &paint); SetTextColor(hdc, RGB(255, 0, 0)); TextOut(hdc, 10, 10, (LPSTR)strx, strlen(strx)); SetTextColor(hdc, RGB(0, 0, 255)); DrawText(hdc, str, -1, &rt, DT_WORDBREAK); ValidateRect(hWnd, NULL); EndPaint(hWnd, &paint); return; }
はい。メニューがつきましたね。「終了」をクリックすると
ちゃんと?終了します。
Update Mar/22/1997 By Y.Kumei