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 とでもしておいてもよい。 ここまでのファイル
を tar と gzip で固めたものを、このページに |