Page001

Application class の作成

Program の規模が大きくなると、module化が必要である。ここでは C++ を使っているので、class化を考える。まずは、application 全体にわたる object を保持する class を考える。

Resource file の導入

前節の概要を見てわかるように、application が起動すると、system から instance の handle が渡される。ここで考える class の第一の目的は、この handle の隠蔽である。

この instance handle は application と結び付けられた resource との橋渡しも行ってくれる。特に言語など、環境依存の部分は resource に押し込めると、開発や保守がやりやすくなる。まずは、resouce file を用意しよう。

とりあえず必要なのは、前節で define 文を使って固定している Window class の名前と、title の文字列である。Resource file では STRINGTABLE を使って与える。また、割り当てには identifier 番号を付ける必要があるので、その番号を記した file を resource.h として用意する(このあたりは Microsoft Visual Studio を模す)。番号は、16 bit 整数であればよい(はずである)が、後でicon や menu なども割り付けるので、適当な大きい数にしておく。

まずは resouce.h

// resource.h

#ifndef RESOURCE_H_INCLUDED
#define RESOURCE_H_INCLUDED

#define IDS_MY_WINCLASS		1025
#define IDS_MY_APPTITLE		1026

#endif	// RESOURCE_H_INCLUDED

次に、resource file として、myapp.rc を用意する。

// myapp.rc

#include "resource.h"

// String Table
STRINGTABLE
BEGIN
	IDS_MY_WINCLASS	"MyAppWin"
	IDS_MY_APPTITLE	"My Application"
END

MinGW での resource file の compile には windres を用いる。

windres myapp.rc -o res.o

CMyApp class の導入

さて、CMyApp class であるが、constructor で Window class名や title 文字列を取得した後、Window class の登録まで行うものとしよう。

ここで、WndProc の取扱いが問題になる。汎用 Window class を作ることも考えられるが、この application では基底となる window は一つとし、CMyApp class で取り扱うものとしよう。

また、基底となる window の生成、及び message loop は CMyApp class に Run() という関数を用意して、これを呼び出すものとしよう。Contructor でいきなり window まで作ってしまうことも考えられるが、戻り値が必要なことや、初期化段階でのエラーと実行段階でのエラーを区別してよいた方がよかろうということから、ここでは Run() 関数を用意する。

まずは myapp.h

// myapp.h

#ifndef MYAPP_H_INCLUDED
#define MYAPP_H_INCLUDED

class CMyApp
{
private:
	static const int MAX_LOAD_STRING = 256;
	static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

public:
	CMyApp(HINSTANCE hInstance, HINSTANCE hPrevInstance);
	~CMyApp();
	int Run(int nCmdShow);

public:
	HINSTANCE m_hInstance;

private:
	TCHAR m_szWinClass[(MAX_LOAD_STRING+1)];
	TCHAR m_szAppTitle[(MAX_LOAD_STRING+1)];
};

#endif	// MYAPP_H_INCLUDED

続いて、myapp.cpp

#include <windows.h>
#include <tchar.h>
#include "resource.h"
#include "myapp.h"

CMyApp::CMyApp(HINSTANCE hInstance, HINSTANCE hPrevInstance)
{
	// Save the instance handle
	m_hInstance = hInstance;

	// Load the strings
	int nChar;
	nChar = LoadString(hInstance, IDS_MY_WINCLASS, m_szWinClass, MAX_LOAD_STRING);
	m_szWinClass[nChar] = 0;
	nChar = LoadString(hInstance, IDS_MY_APPTITLE, m_szAppTitle, MAX_LOAD_STRING);
	m_szAppTitle[nChar] = 0;

	// Register the Window Class
	if(hPrevInstance == 0)
	{
		WNDCLASSEX wcex;
		wcex.cbSize = sizeof(WNDCLASSEX);
		wcex.style = CS_HREDRAW | CS_VREDRAW;
		wcex.lpfnWndProc = WndProc;
		wcex.cbClsExtra = 0;
		wcex.cbWndExtra = 0;
		wcex.hInstance = hInstance;
		wcex.hIcon = LoadIcon(0, IDI_APPLICATION);
		wcex.hCursor = LoadCursor(0, IDC_ARROW);
		wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
		wcex.lpszMenuName = 0;
		wcex.lpszClassName = m_szWinClass;
		wcex.hIconSm = LoadIcon(0, IDI_APPLICATION);
		RegisterClassEx(&wcex);
	}
}

CMyApp::~CMyApp()
{
}

LRESULT CALLBACK 
CMyApp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

int
CMyApp::Run(int nCmdShow)
{
	// Create Window
	HWND hWnd = CreateWindow(m_szWinClass, m_szAppTitle, WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, m_hInstance, 0);
	if(!hWnd)
		return 0;
	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);
	
	// Enter Message Loop
	MSG msg;
	while(GetMessage(&msg, 0, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return (int)msg.wParam;
}

Main program

これで一応 CMyApp class ができたので、前節の myapp01.cpp を myapp02.cpp として書き換えてみる。

#include <windows.h>
#include <tchar.h>
#include "myapp.h"

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpCmdLine, int nCmdShow)
{
	// Create my application
	CMyApp app(hInstance, hPrevInstance);
	return app.Run(nCmdShow);
}

Compile と link

Compile と link は

windres myapp.res -o res.o
g++ -Wall -mwindows myapp02.cpp myapp.cpp res.o -o myapp02.exe

である。makefile を作る手もあるが、この程度であれば、上記内容を build.bat とでもしておいてもよい。

ここまでのファイル

  • myapp02.cpp
  • resource.h
  • myapp.res
  • myapp.cpp
  • myapp.h
  • build.bat

を tar と gzip で固めたものを、このページに filemyapp02.tgz として添付しておく。


添付ファイル: filemyapp02.tgz 16379件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2007-08-02 (木) 17:05:23 (88d)