メインウィンドウのためのクラスをもう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 の別名となっています。