メインウィンドウのためのクラスをもう1つ作ります。
ファイル名は、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 の別名となっています。