2 * Copyright 2003 Martin Fuchs
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 // Martin Fuchs, 23.07.2003
34 typedef set<HWND> WindowSet;
38 Classes are declared using "struct", not "class" because the default
39 access mode is "public". This way we can list the member functions in a
40 natural order without explicitly specifying any access mode at the begin
42 First are public constructors and destructor, then public member functions.
43 After that we list protected member varibables and functions. If needed,
44 private implemenation varibales and functions are positioned at the end.
49 Class Window is the base class for several C++ window wrapper classes.
50 Window objects are allocated from the heap. They are automatically freed
51 when the window gets destroyed.
53 struct Window : public WindowHandle
59 typedef map<HWND,Window*> WindowMap;
61 typedef Window* (*CREATORFUNC)(HWND, const void*);
62 typedef Window* (*CREATORFUNC_NO_INFO)(HWND);
64 static HWND Create(CREATORFUNC creator, DWORD dwExStyle,
65 LPCTSTR lpClassName, LPCTSTR lpWindowName,
66 DWORD dwStyle, int x, int y, int w, int h,
67 HWND hwndParent=0, HMENU hMenu=0, LPVOID lpParam=0);
69 static HWND Create(CREATORFUNC creator, const void* info,
70 DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName,
71 DWORD dwStyle, int x, int y, int w, int h,
72 HWND hwndParent=0, HMENU hMenu=0, LPVOID lpParam=0);
74 static Window* create_mdi_child(HWND hmdiclient, const MDICREATESTRUCT& mcs, CREATORFUNC creator, const void* info=NULL);
76 static LRESULT CALLBACK WindowWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
78 static Window* get_window(HWND hwnd);
80 template<typename CLASS> static CLASS* get_window(HWND hwnd) {return static_cast<CLASS*>(get_window(hwnd));}
81 #define GET_WINDOW(CLASS, hwnd) Window::get_window<CLASS>(hwnd)
84 static void register_pretranslate(HWND hwnd);
85 static void unregister_pretranslate(HWND hwnd);
86 static BOOL pretranslate_msg(LPMSG pmsg);
88 static void register_dialog(HWND hwnd);
89 static void unregister_dialog(HWND hwnd);
90 static BOOL dispatch_dialog_msg(LPMSG pmsg);
92 static int MessageLoop();
95 LRESULT SendParent(UINT nmsg, WPARAM wparam=0, LPARAM lparam=0);
96 LRESULT PostParent(UINT nmsg, WPARAM wparam=0, LPARAM lparam=0);
98 static void CancelModes(HWND hwnd=0);
102 virtual LRESULT Init(LPCREATESTRUCT pcs); // WM_CREATE processing
103 virtual LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
104 virtual int Command(int id, int code); // WM_COMMAND processing
105 virtual int Notify(int id, NMHDR* pnmh); // WM_NOTIFY processing
108 static WindowMap s_wnd_map;
110 static const void* s_new_info;
111 static CREATORFUNC s_window_creator;
114 struct StaticWindowData {
115 CritSect _map_crit_sect;
116 CritSect _create_crit_sect;
119 static StaticWindowData& GetStaticWindowData();
122 // MDI child creation
123 static HHOOK s_hcbtHook;
124 static LRESULT CALLBACK CBTHookProc(int code, WPARAM wparam, LPARAM lparam);
126 static WindowSet s_pretranslate_windows;
127 static WindowSet s_dialogs;
132 template<typename CLASS> struct GetWindowHelper
134 static CLASS* get_window(HWND hwnd) {
135 return static_cast<CLASS*>(Window::get_window(hwnd));
138 #define GET_WINDOW(CLASS, hwnd) GetWindowHelper<CLASS>::get_window(hwnd)
142 template<typename CLASS> struct TypeCheck
144 static CLASS* dyn_cast(Window* wnd)
145 {return dynamic_cast<CLASS*>(wnd);}
148 #define WINDOW_DYNAMIC_CAST(CLASS, hwnd) \
149 TypeCheck<CLASS>::dyn_cast(Window::get_window(hwnd))
153 SubclassedWindow is used to wrap already existing window handles
154 into C++ Window objects. To construct a object, use the "new" operator
155 to put it in the heap. It is automatically freed, when the window
158 struct SubclassedWindow : public Window
160 typedef Window super;
162 SubclassedWindow(HWND);
167 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
171 template<typename WND_CLASS> struct WindowCreator
173 static WND_CLASS* window_creator(HWND hwnd)
175 return new WND_CLASS(hwnd);
179 #define WINDOW_CREATOR(WND_CLASS) \
180 (Window::CREATORFUNC) WindowCreator<WND_CLASS>::window_creator
183 template<typename WND_CLASS, typename INFO_CLASS> struct WindowCreatorInfo
185 static WND_CLASS* window_creator(HWND hwnd, const void* info)
187 return new WND_CLASS(hwnd, *static_cast<const INFO_CLASS*>(info));
191 #define WINDOW_CREATOR_INFO(WND_CLASS, INFO_CLASS) \
192 (Window::CREATORFUNC) WindowCreatorInfo<WND_CLASS, INFO_CLASS>::window_creator
196 WindowClass is a neat wrapper for RegisterClassEx().
197 Just construct a WindowClass object, override the attributes you want
198 to change, then call Register() or simply request the ATOM value to
199 register the window class. You don't have to worry calling Register()
200 more than once. It checks if, the class has already been registered.
202 struct WindowClass : public WNDCLASSEX
204 WindowClass(LPCTSTR classname, UINT style=0, WNDPROC wndproc=Window::WindowWndProc);
209 _atomClass = RegisterClassEx(this);
214 operator ATOM() {return Register();}
216 // return LPCTSTR for the CreateWindowEx() parameter
217 operator LPCTSTR() {return (LPCTSTR)(int)Register();}
223 /// window class with gray background color
224 struct BtnWindowClass : public WindowClass
226 BtnWindowClass(LPCTSTR classname, UINT style=0, WNDPROC wndproc=Window::WindowWndProc)
227 : WindowClass(classname, style, wndproc)
229 hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
233 /// window class with specified icon from resources
234 struct IconWindowClass : public WindowClass
236 IconWindowClass(LPCTSTR classname, UINT nid, UINT style=0, WNDPROC wndproc=Window::WindowWndProc);
240 // private message constants
241 #define PM_DISPATCH_COMMAND (WM_APP+0x00)
242 #define PM_TRANSLATE_MSG (WM_APP+0x01)
245 #define SPLIT_WIDTH 5
246 #define DEFAULT_SPLIT_POS 300
247 #define COLOR_SPLITBAR LTGRAY_BRUSH
250 /// menu info structure for MDI child windows
257 #define PM_FRM_GET_MENUINFO (WM_APP+0x02)
259 #define Frame_GetMenuInfo(hwnd) ((MenuInfo*)SNDMSG(hwnd, PM_FRM_GET_MENUINFO, 0, 0))
263 Class ChildWindow represents MDI child windows.
264 It is used with class MainFrame.
266 struct ChildWindow : public Window
268 typedef Window super;
270 ChildWindow(HWND hwnd);
272 static ChildWindow* create(HWND hmdiclient, const RECT& rect,
273 CREATORFUNC creator, LPCTSTR classname, LPCTSTR title=NULL, const void* info=NULL);
276 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
278 virtual void resize_children(int cx, int cy);
283 WindowHandle _left_hwnd;
284 WindowHandle _right_hwnd;
285 int _focus_pane; // 0: left 1: right
293 PreTranslateWindow is used to register windows to be called by Window::pretranslate_msg().
294 This way you get PM_TRANSLATE_MSG messages before the message loop dispatches messages.
295 You can then for example use TranslateAccelerator() to implement key shortcuts.
297 struct PreTranslateWindow : public Window
299 typedef Window super;
301 PreTranslateWindow(HWND);
302 ~PreTranslateWindow();
307 The class Dialog implements modeless dialogs, which are managed by
308 Window::dispatch_dialog_msg() in Window::MessageLoop().
309 A Dialog object should be constructed by calling Window::Create()
310 and specifying the class using the WINDOW_CREATOR() macro.
312 struct Dialog : public Window
314 typedef Window super;
322 This class constructs button controls.
323 The button will remain existent when the C++ Button object is destroyed.
324 There is no conjunction between C++ object and windows control life time.
326 struct Button : public WindowHandle
328 Button(HWND parent, LPCTSTR text, int left, int top, int width, int height,
329 int id, DWORD flags=WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON, DWORD exStyle=0);
334 This class constructs static controls.
335 The control will remain existent when the C++ object is destroyed.
336 There is no conjunction between C++ object and windows control life time.
338 struct Static : public WindowHandle
340 Static(HWND parent, LPCTSTR text, int left, int top, int width, int height,
341 int id, DWORD flags=WS_VISIBLE|WS_CHILD|SS_SIMPLE, DWORD ex_flags=0);
346 // control color message routing for ColorStatic and HyperlinkCtrl
348 #define PM_DISPATCH_CTLCOLOR (WM_APP+0x07)
350 template<typename BASE> struct CtlColorParent : public BASE
354 CtlColorParent(HWND hwnd)
357 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
363 case WM_CTLCOLORSCROLLBAR:
364 case WM_CTLCOLORSTATIC: {
365 HWND hctl = (HWND) lparam;
366 return SendMessage(hctl, PM_DISPATCH_CTLCOLOR, wparam, nmsg);
370 return super::WndProc(nmsg, wparam, lparam);
377 // owner draw message routing for ColorButton and PictureButton
379 #define PM_DISPATCH_DRAWITEM (WM_APP+0x08)
381 template<typename BASE> struct OwnerDrawParent : public BASE
385 OwnerDrawParent(HWND hwnd)
388 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
392 if (wparam) { // should there be drawn a control?
393 HWND hctl = GetDlgItem(_hwnd, wparam);
396 return SendMessage(hctl, PM_DISPATCH_DRAWITEM, wparam, lparam);
397 } /*else // or is it a menu entry?
403 return super::WndProc(nmsg, wparam, lparam);
410 Subclass button controls to draw them by using PM_DISPATCH_DRAWITEM
411 The owning window should use the OwnerDrawParent template to route owner draw messages to the buttons.
413 struct OwnerdrawnButton : public SubclassedWindow
415 typedef SubclassedWindow super;
417 OwnerdrawnButton(HWND hwnd)
421 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
423 void DrawGrayText(LPDRAWITEMSTRUCT dis, LPRECT pRect, LPCTSTR text, int dt_flags);
425 virtual void DrawItem(LPDRAWITEMSTRUCT dis) = 0;
430 Subclass button controls to paint colored text labels.
431 The owning window should use the OwnerDrawParent template to route owner draw messages to the buttons.
434 struct ColorButton : public OwnerdrawnButton
436 typedef OwnerdrawnButton super;
438 ColorButton(HWND hwnd, COLORREF textColor)
439 : super(hwnd), _textColor(textColor) {}
442 virtual void DrawItem(LPDRAWITEMSTRUCT dis);
450 Subclass button controls to paint pictures left to the labels.
451 The buttons should have set the style bit BS_OWNERDRAW.
452 The owning window should use the OwnerDrawParent template to route owner draw messages to the buttons.
454 struct PictureButton : public OwnerdrawnButton
456 typedef OwnerdrawnButton super;
458 PictureButton(HWND hwnd, HICON hIcon, HBRUSH hbrush=GetSysColorBrush(COLOR_BTNFACE), bool flat=false)
459 : super(hwnd), _hIcon(hIcon), _hBrush(hbrush), _flat(flat)
464 virtual void DrawItem(LPDRAWITEMSTRUCT dis);
472 struct ToolTip : public WindowHandle
474 typedef WindowHandle super;
478 void activate(BOOL active=TRUE)
480 SendMessage(_hwnd, TTM_ACTIVATE, active, 0);
483 void add(HWND hparent, HWND htool, LPCTSTR txt=LPSTR_TEXTCALLBACK)
486 sizeof(TOOLINFO), TTF_SUBCLASS|TTF_IDISHWND/*|TTF_TRANSPARENT*/, hparent, (UINT)htool, {0,0,0,0}, 0, 0, 0
488 ti.lpszText = (LPTSTR) txt;
490 SendMessage(_hwnd, TTM_ADDTOOL, 0, (LPARAM)&ti);