リソースファイルを見ていきます。 ソースファイル同様、テキストファイルです。
リソースファイルです、 ファイル名は、"win112.rc" です。 "Resource.h" をインクルードします。
#include "Resource.h" #include <windows.h> //---------------------------------- // ダイアログ //---------------------------------- MyAboutBox DIALOGEX 0, 0, 170, 62 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "バージョン情報" FONT 9, "MS UI Gothic" BEGIN LTEXT "よくあるウィンドウズプログラム",IDC_STATIC,42,14,114,8,SS_NOPREFIX LTEXT "Version 1.0",IDC_STATIC,42,26,114,8 DEFPUSHBUTTON "OK",IDOK,113,41,50,14,WS_GROUP END //------------------------- // メニュー //------------------------- MyMenu MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "終了(&X)", IDM_EXIT END POPUP "ヘルプ(&H)" BEGIN MENUITEM "バージョン情報(&A)", IDM_ABOUT END END //------------------------- // アクセラレータ //------------------------- IDC_APP_NAME ACCELERATORS BEGIN "?", IDM_ABOUT, ASCII, ALT "/", IDM_ABOUT, ASCII, ALT END //-------------------- // ストリング テーブル //-------------------- STRINGTABLE DISCARDABLE BEGIN IDC_APP_NAME, "win112" IDS_APP_TITLE, "よくあるウィンドウズプログラム" END
リソースファイルのヘッダファイルです。 ファイル名は、"Resource.h" です。
// // Resource.h //--------------------- // ダイアログ //--------------------- #define IDC_STATIC -1 //--------------------- // メニュー //--------------------- #define IDM_EXIT 200 #define IDM_ABOUT 201 //--------------------- // イメージ //--------------------- #define IDI_APP 300 #define IDI_SMALL 301 //--------------------- // ストリング テーブル //--------------------- #define IDC_APP_NAME 400 #define IDS_APP_TITLE 401
ソースファイルです。 ファイル名は、"win112.cpp" です。
/* よくあるウィンドウズプログラム */ #include <windows.h> #include <tchar.h> #include "Resource.h" #define MAX_LOADSTRING 100 // グローバル変数 HINSTANCE hInst; // 現在のインターフェイス HWND hWnd; // ウィンドウハンドル // ウインドウプロシージャ宣言 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); // アプリケーション開始位置 int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int nCmdShow) { hInst = hInstance; // インスタンスハンドル保存 TCHAR AppName[MAX_LOADSTRING]; // メインウィンドウのクラス名 TCHAR AppTitle[MAX_LOADSTRING]; // タイトル // リソース LoadString(hInst, IDC_APP_NAME, AppName, MAX_LOADSTRING); LoadString(hInst, IDS_APP_TITLE, AppTitle, MAX_LOADSTRING); MSG msg; // MSG構造体 WNDCLASSEX wc; // WNDCLASSEX構造体 HACCEL hAccelTable; // ウィンドウの定義 wc.cbSize = sizeof(WNDCLASSEX); // WNDCLASSEXのサイズ wc.style = CS_HREDRAW | CS_VREDRAW; // 拡張スタイル wc.lpfnWndProc = WndProc; // ウィンドウプロシージャ wc.cbClsExtra = 0; // 追加領域 wc.cbWndExtra = 0; // 追加領域 wc.hInstance = hInst; // インスタンス wc.hIcon = LoadIcon(NULL,IDI_APPLICATION); // アイコン wc.hCursor = LoadCursor(NULL,IDC_ARROW); // カーソル wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); // 背景ブラシ wc.lpszMenuName = L"MyMenu"; // メニュー wc.lpszClassName = AppName; // クラス名 wc.hIconSm = LoadIcon(NULL, IDI_WINLOGO); // 小さなアイコン // ウインドウクラスの登録 if(RegisterClassEx(&wc) == 0) return 0; // ウインドウの作成 hWnd = CreateWindowEx( 0, // 拡張スタイル AppName, // クラス名 AppTitle, // キャプション WS_OVERLAPPEDWINDOW, // スタイル CW_USEDEFAULT, CW_USEDEFAULT, // 位置 CW_USEDEFAULT, CW_USEDEFAULT, // サイズ NULL, // 親ウィンドウのハンドル (HMENU)NULL, // メニュー hInst, // インスタンス NULL); // ウィンドウ作成データ if(hWnd == NULL) return 0; // ウィンドウの表示 ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); hAccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDC_APP_NAME)); // メッセージループ while(GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)){ TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } // ウインドウプロシージャ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { hWnd = hwnd; // ウィンドウハンドル保存 int wmId, wmEvent; switch(msg) { case WM_COMMAND: wmId = LOWORD(wp); wmEvent = HIWORD(wp); // 選択されたメニューの解析: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, L"MyAboutBox", hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; } break; case WM_DESTROY: PostQuitMessage(0); // メッセージループの終了 break; default: return DefWindowProc(hWnd, msg, wp, lp); // 既定のウィンドウプロシージャ } return 0; } // バージョン情報 INT_PTR CALLBACK About(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wp) == IDOK || LOWORD(wp) == IDCANCEL) { EndDialog(hDlg, LOWORD(wp)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; }
実行画面です。
リソースファイルに文字列を置くことができます。 これをストリングテーブルといいます。 BEGIN と END の中に文字列を書きます。
//--------------------
// ストリング テーブル
//--------------------
STRINGTABLE DISCARDABLE
BEGIN
IDC_APP_NAME, "win112"
IDS_APP_TITLE, "よくあるウィンドウズプログラム"
END
たとえば、"win112" を呼び出すには、IDC_APP_NAME に数値をつけます。 これを、ヘッダファイルに書きます。
//--------------------- // ストリング テーブル //--------------------- #define IDC_APP_NAME 400 #define IDS_APP_TITLE 401
プログラム側で、LoadString 関数を使って呼び出せます。
// リソース LoadString(hInst, IDC_APP_NAME, AppName, MAX_LOADSTRING);
話はそれますが、 これを利用して、アプリケーション名とウィンドウのタイトルはリソースファイルに書くことにします。
メインウィンドウにメニューをつけます。
//------------------------- // メニュー //------------------------- MyMenu MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "終了(&X)", IDM_EXIT END POPUP "ヘルプ(&H)" BEGIN MENUITEM "バージョン情報(&A)", IDM_ABOUT END END
メニューをつけるのは簡単です。 WNDCLASSEX 構造体のメンバー lpszMenuName に "MyMenu" と代入するだけです。
WNDCLASSEX wc; // WNDCLASSEX構造体 wc.lpszMenuName = L"MyMenu"; // メニュー
次は、メニューらしく機能させます。 例えば、"終了" を選択するとします。 ヘッダファイルで IDM_EXIT に数値をつけます。
//--------------------- // メニュー //--------------------- #define IDM_EXIT 200 #define IDM_ABOUT 201
メニューを選択すると、WM_COMMAND メッセージが送られてきます。 そこで、どれが押されたかを調べます。 wmId に IDM_EXIT が入っています。 今回は、ウィンドウの×ボタンと同じ動作をさせています。
// ウインドウプロシージャ
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
hWnd = hwnd; // ウィンドウハンドル保存
int wmId, wmEvent;
switch(msg)
{
case WM_COMMAND:
wmId = LOWORD(wp);
wmEvent = HIWORD(wp);
// 選択されたメニューの解析:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, L"MyAboutBox", hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, msg, wp, lp);
}
break;
case WM_DESTROY:
PostQuitMessage(0); // メッセージループの終了
break;
default:
return DefWindowProc(hWnd, msg, wp, lp); // 既定のウィンドウプロシージャ
}
return 0;
}
リソースを使って、メインウィンドウから、別のウィンドウを開くことができます。
もっと複雑なのも作れます。 ここでは、メニューでバージョン情報が選択されて開くウィンドウです。
//---------------------------------- // ダイアログ //---------------------------------- MyAboutBox DIALOGEX 0, 0, 170, 62 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "バージョン情報" FONT 9, "MS UI Gothic" BEGIN LTEXT "よくあるウィンドウズプログラム",IDC_STATIC,42,14,114,8,SS_NOPREFIX LTEXT "Version 1.0",IDC_STATIC,42,26,114,8 DEFPUSHBUTTON "OK",IDOK,113,41,50,14,WS_GROUP END
このウィンドウを開くのは簡単です。 DialogBox 関数を使って、"MyAboutBox" と指定するだけです。
DialogBox(hInst, L"MyAboutBox", hWnd, About);
開いたら、メインウィンドウ同様 OS からメッセージがやってきます。 "About" は、そのメッセージを処理するウインドウプロシージャです。 見たとおり、メインウィンドウの "WndProc" と同じです。
// バージョン情報 INT_PTR CALLBACK About(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wp) == IDOK){ EndDialog(hDlg, LOWORD(wp)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; }
今回は、"OK" ボタンが押されたら閉じるだけです。 EndDialog 関数を使います。
リソースファイルは、テキストエディタで書きます。 しかし、フリーのリソースエディタを使うと楽です。