2 * Copyright (c) 2001, Gary R. Van Sickle.
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.
9 * A copy of the GNU General Public License can be found at
12 * Written by Gary R. Van Sickle <g.r.vansickle@worldnet.att.net>
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,
24 ATOM
Window::WindowClassAtom
= 0;
25 HINSTANCE
Window::AppInstance
= NULL
;
27 // FIXME: I know, this is brutal. Mutexing should at least make window creation threadsafe,
28 // but if somebody has any ideas as to how to get rid of it entirely, please tell me / do so.
29 struct REFLECTION_INFO
36 REFLECTION_INFO ReflectionInfo
;
47 // Delete any fonts we created.
49 for (i
= 0; i
< FontCounter
; i
++)
51 DeleteObject (Fonts
[i
]);
55 // FIXME: Maybe do some reference counting and do this Unregister
56 // when there are no more of us left. Not real critical unless
57 // we're in a DLL which we're not right now.
58 //UnregisterClass(WindowClassAtom, InstanceHandle);
62 Window::FirstWindowProcReflector (HWND hwnd
, UINT uMsg
, WPARAM wParam
,
65 // Get our this pointer
66 REFLECTION_INFO
*rip
= &ReflectionInfo
;
70 rip
->FirstCall
= false;
72 // Set the Window handle so the real WindowProc has one to work with.
73 rip
->This
->WindowHandle
= hwnd
;
75 // Set a backreference to this class instance in the HWND.
76 // FIXME: Should really be SetWindowLongPtr(), but it appears to
77 // not be defined yet.
78 SetWindowLong (hwnd
, GWL_USERDATA
, (LONG
) rip
->This
);
80 // Set a new WindowProc now that we have the peliminaries done.
81 // Like subclassing, only not.
82 SetWindowLong (hwnd
, GWL_WNDPROC
, (LONG
) & Window::WindowProcReflector
);
85 return rip
->This
->WindowProc (uMsg
, wParam
, lParam
);
89 Window::WindowProcReflector (HWND hwnd
, UINT uMsg
, WPARAM wParam
,
94 // Get our this pointer
95 // FIXME: Should really be GetWindowLongPtr(), but it appears to
96 // not be defined yet.
97 This
= (Window
*) GetWindowLong (hwnd
, GWL_USERDATA
);
99 return This
->WindowProc (uMsg
, wParam
, lParam
);
102 bool Window::Create (Window
* parent
, DWORD Style
)
104 // First register the window class, if we haven't already
105 if (RegisterWindowClass () == false)
107 // Registration failed
111 // Set up the reflection info, so that the Windows window can find us.
112 ReflectionInfo
.This
= this;
113 ReflectionInfo
.FirstCall
= true;
117 // Create the window instance
118 WindowHandle
= CreateWindow ("MainWindowClass", //MAKEINTATOM(WindowClassAtom), // window class atom (name)
119 "Hello", // no title-bar string yet
122 // Default positions and size
124 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
127 NULL
? (HWND
) NULL
: parent
->GetHWND (),
130 // The application instance
131 GetInstance (), (LPVOID
) NULL
);
133 if (WindowHandle
== NULL
)
142 bool Window::RegisterWindowClass ()
144 if (WindowClassAtom
== 0)
146 // We're not registered yet
150 wc
.cbSize
= sizeof (wc
);
151 // Some sensible style defaults
152 wc
.style
= CS_DBLCLKS
| CS_HREDRAW
| CS_VREDRAW
;
153 // Our default window procedure. This replaces itself
154 // on the first call with the simpler Window::WindowProcReflector().
155 wc
.lpfnWndProc
= Window::FirstWindowProcReflector
;
158 // One pointer to REFLECTION_INFO in the extra window instance bytes
161 wc
.hInstance
= GetInstance ();
162 // Use a bunch of system defaults for the GUI elements
166 wc
.hbrBackground
= (HBRUSH
) (COLOR_BACKGROUND
+ 1);
168 wc
.lpszMenuName
= NULL
;
169 // We'll get a little crazy here with the class name
170 wc
.lpszClassName
= "MainWindowClass";
172 // All set, try to register
173 WindowClassAtom
= RegisterClassEx (&wc
);
175 if (WindowClassAtom
== 0)
182 // We're registered, or already were before the call,
183 // return success in either case.
188 Window::Show (int State
)
190 ::ShowWindow (WindowHandle
, State
);
194 Window::CenterWindow ()
196 RECT WindowRect
, ParentRect
;
197 int WindowWidth
, WindowHeight
;
200 // Get the window rectangle
201 GetWindowRect (GetHWND (), &WindowRect
);
203 if (GetParent () == NULL
)
205 // Center on desktop window
206 GetWindowRect (GetDesktopWindow (), &ParentRect
);
210 // Center on client area of parent
211 GetClientRect (GetParent ()->GetHWND (), &ParentRect
);
214 WindowWidth
= WindowRect
.right
- WindowRect
.left
;
215 WindowHeight
= WindowRect
.bottom
- WindowRect
.top
;
217 // Find center of area we're centering on
218 p
.x
= (ParentRect
.right
- ParentRect
.left
) / 2;
219 p
.y
= (ParentRect
.bottom
- ParentRect
.top
) / 2;
221 // Convert that to screen coords
222 if (GetParent () == NULL
)
224 ClientToScreen (GetDesktopWindow (), &p
);
228 ClientToScreen (GetParent ()->GetHWND (), &p
);
231 // Calculate new top left corner for window
232 p
.x
-= WindowWidth
/ 2;
233 p
.y
-= WindowHeight
/ 2;
235 // And finally move the window
236 MoveWindow (GetHWND (), p
.x
, p
.y
, WindowWidth
, WindowHeight
, TRUE
);
239 LRESULT
Window::WindowProc (UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
244 return DefWindowProc (WindowHandle
, uMsg
, wParam
, lParam
);
250 bool Window::MessageLoop ()
255 while (GetMessage (&msg
, NULL
, 0, 0) != 0
256 && GetMessage (&msg
, (HWND
) NULL
, 0, 0) != -1)
258 if (!IsWindow (WindowHandle
) || !IsDialogMessage (WindowHandle
, &msg
))
260 TranslateMessage (&msg
);
261 DispatchMessage (&msg
);
269 Window::PostMessage (UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
271 ::PostMessage (GetHWND (), uMsg
, wParam
, lParam
);
274 UINT
Window::IsButtonChecked (int nIDButton
) const
276 return::IsDlgButtonChecked (GetHWND (), nIDButton
);
280 Window::SetDlgItemFont (int id
, const TCHAR
* fontname
, int Pointsize
,
281 int Weight
, bool Italic
, bool Underline
,
285 ctrl
= GetDlgItem (id
);
288 // Couldn't get that ID
292 // We need the DC for the point size calculation.
293 HDC hdc
= GetDC (ctrl
);
295 // Create the font. We have to keep it around until the dialog item
296 // goes away - basically until we're destroyed.
299 CreateFont (-MulDiv (Pointsize
, GetDeviceCaps (hdc
, LOGPIXELSY
), 72), 0,
300 0, 0, Weight
, Italic
? TRUE
: FALSE
,
301 Underline
? TRUE
: FALSE
, Strikeout
? TRUE
: FALSE
,
302 ANSI_CHARSET
, OUT_TT_PRECIS
, CLIP_DEFAULT_PRECIS
,
303 PROOF_QUALITY
, DEFAULT_PITCH
| FF_DONTCARE
, fontname
);
306 // Font creation failed
310 // Set the new fint, and redraw any text which was already in the item.
311 SendMessage (ctrl
, WM_SETFONT
, (WPARAM
) hfnt
, TRUE
);
313 // Save it for later.
314 Fonts
[FontCounter
] = hfnt
;
321 Window::SetWindowText (const String
& s
)
323 ::SetWindowText (WindowHandle
, s
.cstr_oneuse ());