メインウィンドウ

メインウィンドウのためのクラスをもう1つ作ります。

MyCreateStruct クラス (MyCreateStruct.h)

ファイル名は、MyCreateStruct.h です。 クラスの名前は、MyCreateStruct とします。

#pragma once


//
//	MyCreateStruct クラス(CREATESTRUCT構造体)
//		MyCreateStruct.h
//


class MyCreateStruct : public CREATESTRUCT{
public:
	HWND hwnd;	// 自分のウィンドウハンドルハンドル
	
	// コンストラクタ
	MyCreateStruct(){
		dwExStyle = 0;					// 拡張スタイル
		lpszClass = L"win00";			// クラス名
		lpszName = L"caption";		// キャプション
		style = WS_OVERLAPPEDWINDOW;	// スタイル
		x = CW_USEDEFAULT;				// 位置
		y = CW_USEDEFAULT;               
		cx = CW_USEDEFAULT;				// サイズ
		cy = CW_USEDEFAULT;              
		hwndParent = NULL;		// 親ウィンドウのハンドル
		hMenu = NULL;					// メニュー
		hInstance = hInst;				// インスタンス
		lpCreateParams = NULL;			// ウィンドウ作成データ
	}
	// メソッド
	void Name(LPCTSTR str){
		lpszClass = str;
	}
	void Text(LPCTSTR st){
		lpszName = st;
	}
	void Location(int x1, int y1){
		x = x1;
		y = y1;
	}
	void Size(int width, int height){
	 	cx = width;
		cy = height;
	}
	void Style(int stl){ style = stl; }
	void AddStyle(int stl){ style |= stl; }
	void DelStyle(int stl){ style &= ~stl; }
	void SysMenu(BOOL a, BOOL b = TRUE, BOOL c = TRUE){		// 最大化、最小化ボタン
		if(a == FALSE){
			style &= ~WS_MINIMIZEBOX;
		}else{
			style |= WS_MINIMIZEBOX;
		}

		if(b == FALSE){
			style &= ~WS_MAXIMIZEBOX;
		}else{
			style |= WS_MAXIMIZEBOX;
		}
		
		if(c == FALSE){
			style &= ~WS_SYSMENU;
		}else{
			style |= WS_SYSMENU;
		}
		style |= a | b | c;
	}
	HWND Create(){

		hwnd = CreateWindowEx(
			dwExStyle, lpszClass, lpszName, style, x, y,
			cx, cy, hwndParent, hMenu, hInstance, lpCreateParams);
		Font.Create();
		Font.Add(hwnd);

		return hwnd;
	}
};

解説

CREATESTRUCT構造体というのがあります。 これは、次のように定義されています。

typedef struct tagCREATESTRUCT {
   LPVOID lpCreateParams;
   HANDLE hInstance;
   HMENU hMenu;
   HWND hwndParent;
   int cy;
   int cx;
   int y;
   int x;
   LONG style;
   LPCSTR lpszName;
   LPCSTR lpszClass;
   DWORD dwExStyle;
} CREATESTRUCT;

CreateWindowEx関数の引数と同じです。 これを使えば、"よくあるウィンドウズプログラム"の CreateWindowEx 関数の所は次のように書けます。

	CREATESTRUCT cs;	// CREATESTRUCT構造体
	
	cs.dwExStyle = 0;					// 拡張スタイル
	cs.lpszClass = szWndClass;	// クラス名
	cs.lpszName = TEXT("caption");		// キャプション
	cs.style = WS_OVERLAPPEDWINDOW;	// スタイル
	cs.x = CW_USEDEFAULT;				// 位置
	cs.y = CW_USEDEFAULT;               
	cs.cx = CW_USEDEFAULT;				// サイズ
	cs.cy = CW_USEDEFAULT;              
	cs.hwndParent = NULL;		// 親ウィンドウのハンドル
	cs.hMenu = NULL;					// メニュー
	cs.hInstance = hInst;				// インスタンス
	cs.lpCreateParams = NULL;			// ウィンドウ作成データ

	// ウインドウの作成
	hWnd = CreateWindowEx(
		cs.dwExStyle, cs.lpszClass, cs.lpszName, cs.style, cs.x, cs.y,
		cs.cx, cs.cy, cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);

そこで、CREATESTRUCT構造体を継承して、MyCreateStruct クラスを作成しました。 コンストラクタを使っています。 hInst はグローバル変数です。 クラス名とキャプションの値を代入するメソッドを作ります。 親ウィンドウはないから NULL です。 位置やサイズは、Windows に任せるなら CW_USEDEFAULT のままですが、メソッドを作ります。 スタイルのためのメソッドも作ります。これは説明が必要ですが他の機会にします。

参照渡し

さて、話がそれますが、参照渡しを説明します。 CreateWindowEx関数の引数ですが、次のようにする事を考えます。

	// ウインドウの作成
	hWnd = CreateWindowEx(cs);

C言語では、同じ名前の関数を作れません。 しかし、C++ では、引数が異なれば複数作ることができます。 ですから、次のように作れます。

HWND CreateWindowEx(CREATESTRUCT cs){
	cs.hWnd = CreateWindowEx(
		cs.dwExStyle, cs.lpszClass, cs.lpszName, cs.style, cs.x, cs.y,
		cs.cx, cs.cy, cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);
	return cs.hWnd;
}

ところで、このように書いたとき、値渡しされます。 ですから、cs.hWnd の値は変わりません。 また、コードからはわかりませんが、引数が構造体のとき、実行時に不利だと言われます。 複数のメンバーの値を渡すからだそうです。 ですから、参照渡しにします。 やり方は簡単です。 & を加えるだけです。

HWND CreateWindowEx(CREATESTRUCT& cs){
	cs.hWnd = CreateWindowEx(
		cs.dwExStyle, cs.lpszClass, cs.lpszName, cs.style, cs.x, cs.y,
		cs.cx, cs.cy, cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);
	return cs.hWnd;
}

普通ならポインタを使います。 この場合、参照渡しとは、変数の値を渡すのではなく、メモリ上で、変数の使っているアドレスを渡すことで変数の値を渡す方法です。

しかし、今回使ったのは C++ の別名という方法です。 これで参照渡しができます。 次の例で説明します。

int i;
int& j = i;

j = 1;

変数 i は普通に宣言しています。 変数 j は、int& と宣言しています。 これで、j は、メモリ上で i の使っている場所を指します。 ですから、j に1を代入していますが、i の値も1になります。 ゆえに、j は i の別名となっています。


[前] [目次] [次]