_class.lpfnWndProc = wndProc;
SetDefaults();
}
WinClass::WinClass(int resid, hinstance hinst, wndproc wndproc) : WinSimpleClass (resId, hInst) {
_class.lpfnWndProc = wndProc;
SetDefaults();
}
void WinClass::SetDefaults() {
// Provide reasonable default values
_class.cbSize = sizeof (WNDCLASSEX);
_class.style = 0;
_class.lpszClassName = GetName();
_class.hInstance = GetInstance();
_class.hIcon = 0;
_class.hIconSm = 0;
_class.lpszMenuName = 0;
_class.cbClsExtra = 0;
_class.cbWndExtra = 0;
_class.hbrBackground = reinterpret_cast(COLOR_WINDOW + 1);
_class.hCursor = ::LoadCursor(0, IDC_ARROW);
}
void WinClass::SetResIcons(int resid) {
_class.hIcon = reinterpret_cast(:: LoadImage(_class.hInstance, MAKEINTRESOURCE(resId), IMAGE_ICON, :: GetSystemMetrics(sm_cxicon), :: GetSystemMetrics(sm_cyicon), 0));
// Small icon can be loaded from the same resource
_class.hIconSm = reinterpret_cast(:: LoadImage(_class.hInstance, MAKEINTRESOURCE(resId), IMAGE_ICON, :: GetSystemMetrics(sm_cxsmicon), :: GetSystemMetrics(sm_cysmicon), 0));
}
void WinClass::Register() {
if (:: RegisterClassEx(&_class) == 0) throw WinException("Internal error: RegisterClassEx failed.");
}
class TopWinClass: public WinClass{
public:
TopWinClass(int resId, HINSTANCE hInst, WNDPROC wndProc);
};
TopWinClass::TopWinClass(int resid, HINSTANCE hInst, WNDPROC wndProc) : WinClass (resId, hInst, wndProc) {
SetResIcons(resId);
_class.lpszMenuName = MAKEINTRESOURCE(resId);
}
После того, как оконный класс зарегистрирован системой, Вы можете создать столько окон этого класса, сколько пожелаете. Они, конечно, совместно используют ту же самую оконную процедуру, которая была зарегистрирована классом. Как будет показано дальше, мы можем различать между собой разные экземпляры окна внутри этой процедуры.
WinMaker
Класс WinMakerорганизован аналогично WinClass. Его конструктор устанавливает значения по умолчанию, которые могут быть переустановлены вызовом специфических методов. После завершения всех установок, Вы вызываете метод Create, чтобы создать окно, и метод Show, чтобы отобразить его. Обратите внимание, что в тот момент, когда Вы вызываете Create, ваша оконная процедура вызывается с сообщением WM_CREATE.
Верхнее окно создано с использованием класса TopWinMaker, который обеспечивает соответствующий стиль и заголовок.
class WinMaker {
public:
WinMaker(WinClass& winClass);
operator HWND() { return _hwnd; }
void AddCaption(char const * caption) {
_windowName = caption;
}
void AddSysMenu() { _style |= WS_SYSMENU; }
void AddVScrollBar() { _style |= WS_VSCROLL; }
void AddHScrollBar() { _style |= WS_HSCROLL; }
void Create();
void Show(int nCmdShow = SW_SHOWNORMAL);
protected:
WinClass& _class;
HWND _hwnd;
DWORD _exStyle; // extended window style
char const* _windowName; // pointer to window name
DWORD _style; // window style
int _x; // horizontal position of window
int _y; // vertical position of window
int _width; // window width
int _height; // window height
HWND _hWndParent; // handle to parent or owner window
HMENU _hMenu; // handle to menu, or child-window id
void * _data; // pointer to window-creation data
};
WinMaker::WinMaker(WinClass& winclass) : _hwnd(0), _class(winClass), _exStyle(0), // extended window style
_windowName (0), // pointer to window name
_style(WS_OVERLAPPED), // window style
_x(CW_USEDEFAULT), // horizontal position of window
_y(0), // vertical position of window
_width(CW_USEDEFAULT), // window width
_height(0), // window height
_hWndParent(0), // handle to parent or owner window
_hMenu(0), // handle to menu, or child-window id
_data(0) // pointer to window-creation data
{ }
void WinMaker::Create() {
_hwnd = :: CreateWindowEx(_exStyle, _class.GetName(), _windowName, _style, _x, _y, _width, _height, _hWndParent, _hMenu, _class.GetInstance(), _data);
if (_hwnd == 0) throw WinException ("Internal error: Window Creation Failed.");
}
void WinMaker::Show(int nCmdShow) {
::ShowWindow(_hwnd, nCmdShow);
::UpdateWindow(_hwnd);
}
// Makes top overlapped window with caption
TopWinMaker::TopWinMaker((WinClass& winclass, char const* caption) : WinMaker(winClass) {
_style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
_windowName = caption;
}
Классы общего назначения
Прежде, чем идти дальше, рассмотрим некоторые простые классы общего назначения. WinException — нечто, что мы хотим использовать для исключений во время сбоев Windows API. Он заботится о восстановлении кода ошибки Windows. (Между прочим, имеется простой способ преобразовать код ошибки в строку функцией API FormatMessage.)
Класс ResStringпросто инкапсулирует строку, хранимую в строковых ресурсах вашего приложения.
// The exception class: stores the message and the error code class
WinException{
public:
WinException(char* msg) : _err(:: GetLastError()), _msg(msg) {}
Читать дальше