window.cc revision 706f2543
1/* 2 * Copyright (c) 2005 Alexander Gottwald 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 * 22 * Except as contained in this notice, the name(s) of the above copyright 23 * holders shall not be used in advertising or otherwise to promote the sale, 24 * use or other dealings in this Software without prior written authorization. 25 */ 26 27#include "window.h" 28#include "util.h" 29#include <stdio.h> 30#include <stdexcept> 31 32CWindow::CWindowClass CWindow::windowClass("CWINDOWCLASS", DefWindowProc); 33 34CWindow::CWindowClass::CWindowClass(const char *_name, WNDPROC _wndproc) : 35 wndproc(_wndproc), atom(0), classname(_name) 36{ 37 Register(); 38} 39 40CWindow::CWindowClass::~CWindowClass() 41{ 42 UnregisterClass(classname.c_str(), GetModuleHandle(NULL)); 43} 44 45void CWindow::CWindowClass::Register() 46{ 47 WNDCLASSEX wndclass; 48 memset(&wndclass, 0, sizeof(wndclass)); 49 wndclass.cbSize = sizeof(wndclass); 50 wndclass.style = 0; 51 wndclass.lpfnWndProc = wndproc; 52 wndclass.cbClsExtra = 0; 53 wndclass.cbWndExtra = 0; 54 wndclass.hInstance = GetModuleHandle(NULL); 55 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 56 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); 57 wndclass.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE); 58 wndclass.lpszMenuName = NULL; 59 wndclass.lpszClassName = classname.c_str(); 60 wndclass.hIconSm = NULL; 61 atom = RegisterClassEx(&wndclass); 62 if (atom == 0) 63 throw win32_error("RegisterClassEx failed"); 64} 65 66CWindow::CWindow(const char *_title) : title(_title), hwnd(NULL), parent(NULL), bounds(), owndproc(NULL), showing(FALSE) 67{ 68 style = WS_CHILD; 69 exstyle = 0; 70} 71 72HWND CWindow::CreateWindowHandle() 73{ 74 HWND ret = CreateWindowEx( 75 exstyle, 76 GetClassName(), 77 title.c_str(), 78 style, 79 bounds.left, 80 bounds.top, 81 bounds.width, 82 bounds.height, 83 parent, 84 NULL, 85 GetModuleHandle(NULL), 86 0 87 ); 88 if (ret == NULL) 89 throw win32_error("CreateWindowEx failed"); 90 return ret; 91} 92 93void CWindow::Create() 94{ 95 if (hwnd != NULL) 96 return; 97 hwnd = CreateWindowHandle(); 98 if (hwnd == NULL) 99 throw win32_error("Could not create window"); 100 101 // Reset the error code 102 DWORD err = 0; 103 SetLastError(err); 104 105 // Attach the object reference to the window handle 106 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this); 107 err = GetLastError(); 108 if (err != 0) 109 throw win32_error("SetWindowLongPtr failed",err); 110 111 // Set the window proc 112 owndproc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)WindowProc); 113 err = GetLastError(); 114 if (err != 0) 115 throw win32_error("SetWindowLongPtr failed",err); 116} 117 118const char *CWindow::GetClassName() 119{ 120 return windowClass.GetClassName(); 121} 122 123LRESULT CALLBACK CWindow::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 124{ 125 MessageDebug::debug(hwnd, uMsg, wParam, lParam, __FUNCTION__); 126 CWindow* window = (CWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA); 127 if (window != NULL) 128 return window->Dispatch(hwnd, uMsg, wParam, lParam); 129 return DefWindowProc(hwnd, uMsg, wParam, lParam); 130} 131 132LRESULT CWindow::Dispatch(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 133{ 134 switch (uMsg) 135 { 136 case WM_SIZE: 137 bounds.width = LOWORD(lParam); 138 bounds.height = LOWORD(lParam); 139 break; 140 case WM_MOVE: 141 bounds.left = LOWORD(lParam); 142 bounds.top = LOWORD(lParam); 143 break; 144 case WM_DESTROY: 145 showing = FALSE; 146 break; 147 } 148 if (owndproc) 149 return CallWindowProc(owndproc, hwnd, uMsg, wParam, lParam); 150 else 151 return DefWindowProc(hwnd, uMsg, wParam, lParam); 152} 153 154void CWindow::Show() 155{ 156 if (hwnd == NULL) 157 Create(); 158 ShowWindow(hwnd, SW_SHOWNORMAL); 159} 160 161int CWindow::ShowModal() 162{ 163 MSG msg; 164 BOOL bRet; 165 showing = TRUE; 166 Show(); 167 168 while( showing && (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0) 169 { 170 if (bRet == -1) 171 { 172 // handle the error and possibly exit 173 } 174 else 175 { 176 TranslateMessage(&msg); 177 DispatchMessage(&msg); 178 } 179 } 180 return 0; 181} 182 183void CWindow::SetLeft(int left) 184{ 185 bounds.left = left; 186 if (hwnd) 187 if (!SetWindowPos(hwnd, NULL, 188 bounds.left, bounds.top, 189 0, 0, 190 SWP_NOZORDER | SWP_NOSIZE)) 191 throw win32_error("SetWindowPos failed"); 192} 193 194void CWindow::SetTop(int top) 195{ 196 bounds.top = top; 197 if (hwnd) 198 if (!SetWindowPos(hwnd, NULL, 199 bounds.left, bounds.top, 200 0, 0, 201 SWP_NOZORDER | SWP_NOSIZE)) 202 throw win32_error("SetWindowPos failed"); 203} 204 205void CWindow::SetWidth(int width) 206{ 207 bounds.width = width; 208 if (hwnd) 209 if (!SetWindowPos(hwnd, NULL, 210 0, 0, 211 bounds.width, bounds.height, 212 SWP_NOZORDER | SWP_NOMOVE)) 213 throw win32_error("SetWindowPos failed"); 214} 215void CWindow::SetHeight(int height) 216{ 217 bounds.height = height; 218 if (hwnd) 219 if (!SetWindowPos(hwnd, NULL, 220 0, 0, 221 bounds.width, bounds.height, 222 SWP_NOZORDER | SWP_NOMOVE)) 223 throw win32_error("SetWindowPos failed"); 224} 225 226void CWindow::SetBounds(int left, int top, int width, int height) 227{ 228 bounds = CBoundary(left, top, width, height); 229 if (hwnd) 230 if (!SetWindowPos(hwnd, NULL, 231 bounds.left, bounds.top, 232 bounds.width, bounds.height, 233 SWP_NOZORDER)) 234 throw win32_error("SetWindowPos failed"); 235} 236 237void CWindow::SetBounds(const RECT &rect) 238{ 239 bounds = rect; 240 if (hwnd) 241 if (!SetWindowPos(hwnd, NULL, 242 bounds.left, bounds.top, 243 bounds.width, bounds.height, 244 SWP_NOZORDER)) 245 throw win32_error("SetWindowPos failed"); 246} 247 248HWND CWindow::GetHandle() 249{ 250 if (hwnd == NULL) 251 Create(); 252 return hwnd; 253} 254 255void CWindow::SetParent(CWindow *window) 256{ 257 parent = window->GetHandle(); 258 if (hwnd != NULL) 259 if (::SetParent(hwnd, parent) == NULL) 260 throw win32_error("SetParent failed"); 261 262} 263 264void CWindow::SetStyle(DWORD style) 265{ 266 this->style = style; 267 SetLastError(0); 268 if (hwnd) 269 SetWindowLong(hwnd, GWL_STYLE, style); 270 int err = GetLastError(); 271 if (err != 0) 272 throw win32_error("SetWindowLong failed", err); 273} 274 275void CWindow::SetExStyle(DWORD exstyle) 276{ 277 this->exstyle = exstyle; 278 SetLastError(0); 279 if (hwnd) 280 SetWindowLong(hwnd, GWL_EXSTYLE, exstyle); 281 int err = GetLastError(); 282 if (err != 0) 283 throw win32_error("SetWindowWLong failed", err); 284} 285