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 で固めたものを、このページに |