メインウィンドウ

リソースファイルを見ていきます。 ソースファイル同様、テキストファイルです。

リソース

リソースファイルです、 ファイル名は、"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 関数を使います。

リソースファイルは、テキストエディタで書きます。 しかし、フリーのリソースエディタを使うと楽です。


[前] [目次] [次]