/* * Copyright (c) 2005 Alexander Gottwald * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name(s) of the above copyright * holders shall not be used in advertising or otherwise to promote the sale, * use or other dealings in this Software without prior written authorization. */ #include "window.h" #include "util.h" #include #include CWindow::CWindowClass CWindow::windowClass("CWINDOWCLASS", DefWindowProc); CWindow::CWindowClass::CWindowClass(const char *_name, WNDPROC _wndproc) : wndproc(_wndproc), atom(0), classname(_name) { Register(); } CWindow::CWindowClass::~CWindowClass() { UnregisterClass(classname.c_str(), GetModuleHandle(NULL)); } void CWindow::CWindowClass::Register() { WNDCLASSEX wndclass; memset(&wndclass, 0, sizeof(wndclass)); wndclass.cbSize = sizeof(wndclass); wndclass.style = 0; wndclass.lpfnWndProc = wndproc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = GetModuleHandle(NULL); wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = classname.c_str(); wndclass.hIconSm = NULL; atom = RegisterClassEx(&wndclass); if (atom == 0) throw win32_error("RegisterClassEx failed"); } CWindow::CWindow(const char *_title) : title(_title), hwnd(NULL), parent(NULL), bounds(), owndproc(NULL), showing(FALSE) { style = WS_CHILD; exstyle = 0; } HWND CWindow::CreateWindowHandle() { HWND ret = CreateWindowEx( exstyle, GetClassName(), title.c_str(), style, bounds.left, bounds.top, bounds.width, bounds.height, parent, NULL, GetModuleHandle(NULL), 0 ); if (ret == NULL) throw win32_error("CreateWindowEx failed"); return ret; } void CWindow::Create() { if (hwnd != NULL) return; hwnd = CreateWindowHandle(); if (hwnd == NULL) throw win32_error("Could not create window"); // Reset the error code DWORD err = 0; SetLastError(err); // Attach the object reference to the window handle SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this); err = GetLastError(); if (err != 0) throw win32_error("SetWindowLongPtr failed",err); // Set the window proc owndproc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)WindowProc); err = GetLastError(); if (err != 0) throw win32_error("SetWindowLongPtr failed",err); } const char *CWindow::GetClassName() { return windowClass.GetClassName(); } LRESULT CALLBACK CWindow::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { MessageDebug::debug(hwnd, uMsg, wParam, lParam, __FUNCTION__); CWindow* window = (CWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if (window != NULL) return window->Dispatch(hwnd, uMsg, wParam, lParam); return DefWindowProc(hwnd, uMsg, wParam, lParam); } LRESULT CWindow::Dispatch(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_SIZE: bounds.width = LOWORD(lParam); bounds.height = LOWORD(lParam); break; case WM_MOVE: bounds.left = LOWORD(lParam); bounds.top = LOWORD(lParam); break; case WM_DESTROY: showing = FALSE; break; } if (owndproc) return CallWindowProc(owndproc, hwnd, uMsg, wParam, lParam); else return DefWindowProc(hwnd, uMsg, wParam, lParam); } void CWindow::Show() { if (hwnd == NULL) Create(); ShowWindow(hwnd, SW_SHOWNORMAL); } int CWindow::ShowModal() { MSG msg; BOOL bRet; showing = TRUE; Show(); while( showing && (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0) { if (bRet == -1) { // handle the error and possibly exit } else { TranslateMessage(&msg); DispatchMessage(&msg); } } return 0; } void CWindow::SetLeft(int left) { bounds.left = left; if (hwnd) if (!SetWindowPos(hwnd, NULL, bounds.left, bounds.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE)) throw win32_error("SetWindowPos failed"); } void CWindow::SetTop(int top) { bounds.top = top; if (hwnd) if (!SetWindowPos(hwnd, NULL, bounds.left, bounds.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE)) throw win32_error("SetWindowPos failed"); } void CWindow::SetWidth(int width) { bounds.width = width; if (hwnd) if (!SetWindowPos(hwnd, NULL, 0, 0, bounds.width, bounds.height, SWP_NOZORDER | SWP_NOMOVE)) throw win32_error("SetWindowPos failed"); } void CWindow::SetHeight(int height) { bounds.height = height; if (hwnd) if (!SetWindowPos(hwnd, NULL, 0, 0, bounds.width, bounds.height, SWP_NOZORDER | SWP_NOMOVE)) throw win32_error("SetWindowPos failed"); } void CWindow::SetBounds(int left, int top, int width, int height) { bounds = CBoundary(left, top, width, height); if (hwnd) if (!SetWindowPos(hwnd, NULL, bounds.left, bounds.top, bounds.width, bounds.height, SWP_NOZORDER)) throw win32_error("SetWindowPos failed"); } void CWindow::SetBounds(const RECT &rect) { bounds = rect; if (hwnd) if (!SetWindowPos(hwnd, NULL, bounds.left, bounds.top, bounds.width, bounds.height, SWP_NOZORDER)) throw win32_error("SetWindowPos failed"); } HWND CWindow::GetHandle() { if (hwnd == NULL) Create(); return hwnd; } void CWindow::SetParent(CWindow *window) { parent = window->GetHandle(); if (hwnd != NULL) if (::SetParent(hwnd, parent) == NULL) throw win32_error("SetParent failed"); } void CWindow::SetStyle(DWORD style) { this->style = style; SetLastError(0); if (hwnd) SetWindowLong(hwnd, GWL_STYLE, style); int err = GetLastError(); if (err != 0) throw win32_error("SetWindowLong failed", err); } void CWindow::SetExStyle(DWORD exstyle) { this->exstyle = exstyle; SetLastError(0); if (hwnd) SetWindowLong(hwnd, GWL_EXSTYLE, exstyle); int err = GetLastError(); if (err != 0) throw win32_error("SetWindowWLong failed", err); }