]> cygwin.com Git - cygwin-apps/setup.git/blob - window.cc
2003-10-23 Jerry D. Hedden <jerry@hedden.us>
[cygwin-apps/setup.git] / window.cc
1 /*
2 * Copyright (c) 2001, 2002, 2003 Gary R. Van Sickle.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by Gary R. Van Sickle <g.r.vansickle@worldnet.att.net>
13 *
14 */
15
16 // This is the implementation of the Window class. It serves both as a window class
17 // in its own right and as a base class for other window-like classes (e.g. PropertyPage,
18 // PropSheet).
19
20 #include <windows.h>
21 #include "window.h"
22 #include "String++.h"
23 #include "RECTWrapper.h"
24
25 ATOM Window::WindowClassAtom = 0;
26 HINSTANCE Window::AppInstance = NULL;
27
28 Window::Window ()
29 {
30 WindowHandle = NULL;
31 Parent = NULL;
32 FontCounter = 0;
33 }
34
35 Window::~Window ()
36 {
37 // Delete any fonts we created.
38 int i;
39 for (i = 0; i < FontCounter; i++)
40 {
41 DeleteObject (Fonts[i]);
42 }
43 FontCounter = 0;
44
45 // FIXME: Maybe do some reference counting and do this Unregister
46 // when there are no more of us left. Not real critical unless
47 // we're in a DLL which we're not right now.
48 //UnregisterClass(WindowClassAtom, InstanceHandle);
49 }
50
51 LRESULT CALLBACK
52 Window::FirstWindowProcReflector (HWND hwnd, UINT uMsg, WPARAM wParam,
53 LPARAM lParam)
54 {
55 Window *wnd = NULL;
56
57 if(uMsg == WM_NCCREATE)
58 {
59 // This is the first message a window gets (so MSDN says anyway).
60 // Take this opportunity to "link" the HWND to the 'this' ptr, steering
61 // messages to the class instance's WindowProc().
62 wnd = reinterpret_cast<Window *>(((LPCREATESTRUCT)lParam)->lpCreateParams);
63
64 // Set a backreference to this class instance in the HWND.
65 SetWindowLongPtr (hwnd, GWL_USERDATA, reinterpret_cast<LONG_PTR>(wnd));
66
67 // Set a new WindowProc now that we have the peliminaries done.
68 // We could instead simply do the contents of Window::WindowProcReflector
69 // in the 'else' clause below, but this way we eliminate an unnecessary 'if/else' on
70 // every message. Yeah, it's probably not worth the trouble.
71 SetWindowLongPtr (hwnd, GWL_WNDPROC, (LONG_PTR) & Window::WindowProcReflector);
72 // Finally, store the window handle in the class.
73 wnd->WindowHandle = hwnd;
74 }
75 else
76 {
77 // Should never get here.
78 abort();
79 }
80
81 return wnd->WindowProc (uMsg, wParam, lParam);
82 }
83
84 LRESULT CALLBACK
85 Window::WindowProcReflector (HWND hwnd, UINT uMsg, WPARAM wParam,
86 LPARAM lParam)
87 {
88 Window *This;
89
90 // Get our this pointer
91 This = reinterpret_cast<Window *>(GetWindowLongPtr (hwnd, GWL_USERDATA));
92
93 return This->WindowProc (uMsg, wParam, lParam);
94 }
95
96 bool
97 Window::Create (Window * parent, DWORD Style)
98 {
99 // First register the window class, if we haven't already
100 if (registerWindowClass () == false)
101 {
102 // Registration failed
103 return false;
104 }
105
106 // Save our parent, we'll probably need it eventually.
107 Parent = parent;
108
109 // Create the window instance
110 WindowHandle = CreateWindowEx (
111 // Extended Style
112 0,
113 "MainWindowClass", //MAKEINTATOM(WindowClassAtom), // window class atom (name)
114 "Hello", // no title-bar string yet
115 // Style bits
116 Style,
117 // Default positions and size
118 CW_USEDEFAULT,
119 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
120 // Parent Window
121 parent ==
122 NULL ? (HWND) NULL : parent->GetHWND (),
123 // use class menu
124 (HMENU) NULL,
125 // The application instance
126 GetInstance (),
127 // The this ptr, which we'll use to set up the WindowProc reflection.
128 (LPVOID) this);
129
130 if (WindowHandle == NULL)
131 {
132 // Failed
133 return false;
134 }
135
136 return true;
137 }
138
139 bool
140 Window::registerWindowClass ()
141 {
142 if (WindowClassAtom == 0)
143 {
144 // We're not registered yet
145 WNDCLASSEX
146 wc;
147
148 wc.cbSize = sizeof (wc);
149 // Some sensible style defaults
150 wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
151 // Our default window procedure. This replaces itself
152 // on the first call with the simpler Window::WindowProcReflector().
153 wc.lpfnWndProc = Window::FirstWindowProcReflector;
154 // No class bytes
155 wc.cbClsExtra = 0;
156 // One pointer to REFLECTION_INFO in the extra window instance bytes
157 wc.cbWndExtra = 4;
158 // The app instance
159 wc.hInstance = GetInstance ();
160 // Use a bunch of system defaults for the GUI elements
161 wc.hIcon = NULL;
162 wc.hIconSm = NULL;
163 wc.hCursor = NULL;
164 wc.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);
165 // No menu
166 wc.lpszMenuName = NULL;
167 // We'll get a little crazy here with the class name
168 wc.lpszClassName = "MainWindowClass";
169
170 // All set, try to register
171 WindowClassAtom = RegisterClassEx (&wc);
172
173 if (WindowClassAtom == 0)
174 {
175 // Failed
176 return false;
177 }
178 }
179
180 // We're registered, or already were before the call,
181 // return success in either case.
182 return true;
183 }
184
185 void
186 Window::Show (int State)
187 {
188 ::ShowWindow (WindowHandle, State);
189 }
190
191 RECT
192 Window::GetWindowRect() const
193 {
194 RECT retval;
195 ::GetWindowRect(WindowHandle, &retval);
196 return retval;
197 }
198
199 RECT
200 Window::GetClientRect() const
201 {
202 RECT retval;
203 ::GetClientRect(WindowHandle, &retval);
204 return retval;
205 }
206
207 bool
208 Window::MoveWindow(long x, long y, long w, long h, bool Repaint)
209 {
210 return ::MoveWindow (WindowHandle, x, y, w, h, Repaint);
211 }
212
213 bool
214 Window::MoveWindow(const RECTWrapper &r, bool Repaint)
215 {
216 return ::MoveWindow (WindowHandle, r.left, r.top, r.width(), r.height(), Repaint);
217 }
218
219 void
220 Window::CenterWindow ()
221 {
222 RECT WindowRect, ParentRect;
223 int WindowWidth, WindowHeight;
224 POINT p;
225
226 // Get the window rectangle
227 WindowRect = GetWindowRect ();
228
229 if (GetParent () == NULL)
230 {
231 // Center on desktop window
232 ::GetWindowRect (GetDesktopWindow (), &ParentRect);
233 }
234 else
235 {
236 // Center on client area of parent
237 ::GetClientRect (GetParent ()->GetHWND (), &ParentRect);
238 }
239
240 WindowWidth = WindowRect.right - WindowRect.left;
241 WindowHeight = WindowRect.bottom - WindowRect.top;
242
243 // Find center of area we're centering on
244 p.x = (ParentRect.right - ParentRect.left) / 2;
245 p.y = (ParentRect.bottom - ParentRect.top) / 2;
246
247 // Convert that to screen coords
248 if (GetParent () == NULL)
249 {
250 ClientToScreen (GetDesktopWindow (), &p);
251 }
252 else
253 {
254 ClientToScreen (GetParent ()->GetHWND (), &p);
255 }
256
257 // Calculate new top left corner for window
258 p.x -= WindowWidth / 2;
259 p.y -= WindowHeight / 2;
260
261 // And finally move the window
262 MoveWindow (p.x, p.y, WindowWidth, WindowHeight);
263 }
264
265 LRESULT
266 Window::WindowProc (UINT uMsg, WPARAM wParam, LPARAM lParam)
267 {
268 return DefWindowProc (WindowHandle, uMsg, wParam, lParam);
269 }
270
271 bool
272 Window::MessageLoop ()
273 {
274 MSG
275 msg;
276
277 while (GetMessage (&msg, NULL, 0, 0) != 0
278 && GetMessage (&msg, (HWND) NULL, 0, 0) != -1)
279 {
280 if (!IsWindow (WindowHandle) || !IsDialogMessage (WindowHandle, &msg))
281 {
282 TranslateMessage (&msg);
283 DispatchMessage (&msg);
284 }
285 }
286
287 return true;
288 }
289
290 void
291 Window::PostMessage (UINT uMsg, WPARAM wParam, LPARAM lParam)
292 {
293 ::PostMessage (GetHWND (), uMsg, wParam, lParam);
294 }
295
296 UINT
297 Window::IsButtonChecked (int nIDButton) const
298 {
299 return ::IsDlgButtonChecked (GetHWND (), nIDButton);
300 }
301
302 bool
303 Window::SetDlgItemFont (int id, const TCHAR * fontname, int Pointsize,
304 int Weight, bool Italic, bool Underline,
305 bool Strikeout)
306 {
307 HWND ctrl;
308
309 ctrl = GetDlgItem (id);
310 if (ctrl == NULL)
311 {
312 // Couldn't get that ID
313 return false;
314 }
315
316 // We need the DC for the point size calculation.
317 HDC hdc = GetDC (ctrl);
318
319 // Create the font. We have to keep it around until the dialog item
320 // goes away - basically until we're destroyed.
321 HFONT hfnt;
322 hfnt =
323 CreateFont (-MulDiv (Pointsize, GetDeviceCaps (hdc, LOGPIXELSY), 72), 0,
324 0, 0, Weight, Italic ? TRUE : FALSE,
325 Underline ? TRUE : FALSE, Strikeout ? TRUE : FALSE,
326 ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
327 PROOF_QUALITY, DEFAULT_PITCH | FF_DONTCARE, fontname);
328 if (hfnt == NULL)
329 {
330 // Font creation failed
331 return false;
332 }
333
334 // Set the new font, and redraw any text which was already in the item.
335 SendMessage (ctrl, WM_SETFONT, (WPARAM) hfnt, TRUE);
336
337 // Save it for later.
338 Fonts[FontCounter] = hfnt;
339 FontCounter++;
340
341 return true;
342 }
343
344 void
345 Window::SetWindowText (const String & s)
346 {
347 ::SetWindowText (WindowHandle, s.cstr_oneuse ());
348 }
349
350 RECT
351 Window::ScreenToClient(const RECT &r) const
352 {
353 POINT tl;
354 POINT br;
355
356 tl.y = r.top;
357 tl.x = r.left;
358 ::ScreenToClient(GetHWND(), &tl);
359 br.y = r.bottom;
360 br.x = r.right;
361 ::ScreenToClient(GetHWND(), &br);
362
363 RECT ret;
364
365 ret.top = tl.y;
366 ret.left = tl.x;
367 ret.bottom = br.y;
368 ret.right = br.x;
369
370 return ret;
371 }
372
This page took 0.052424 seconds and 5 git commands to generate.