This commit was manufactured by cvs2svn to create branch 'captive'.
[reactos.git] / subsys / system / explorer / utility / window.h
1 /*
2  * Copyright 2003 Martin Fuchs
3  *
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.
8  *
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.
13  *
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
17  */
18
19
20  //
21  // Explorer clone
22  //
23  // window.h
24  //
25  // Martin Fuchs, 23.07.2003
26  //
27
28
29 #include <map>
30 #include <set>
31 #include <list>
32
33
34 typedef set<HWND> WindowSet;
35
36
37  /*
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
41         of the definition.
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.
45  */
46
47
48  /**
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.
52  */
53 struct Window : public WindowHandle
54 {
55         Window(HWND hwnd);
56         virtual ~Window();
57
58
59         typedef map<HWND,Window*> WindowMap;
60
61         typedef Window* (*CREATORFUNC)(HWND, const void*);
62         typedef Window* (*CREATORFUNC_NO_INFO)(HWND);
63
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);
68
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);
73
74         static Window* create_mdi_child(HWND hmdiclient, const MDICREATESTRUCT& mcs, CREATORFUNC creator, const void* info=NULL);
75
76         static LRESULT CALLBACK WindowWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
77
78         static Window* get_window(HWND hwnd);
79 #ifndef _MSC_VER
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)
82 #endif
83
84         static void register_pretranslate(HWND hwnd);
85         static void unregister_pretranslate(HWND hwnd);
86         static BOOL     pretranslate_msg(LPMSG pmsg);
87
88         static void     register_dialog(HWND hwnd);
89         static void     unregister_dialog(HWND hwnd);
90         static BOOL     dispatch_dialog_msg(LPMSG pmsg);
91
92         static int      MessageLoop();
93
94
95         LRESULT SendParent(UINT nmsg, WPARAM wparam=0, LPARAM lparam=0);
96         LRESULT PostParent(UINT nmsg, WPARAM wparam=0, LPARAM lparam=0);
97
98         static void CancelModes(HWND hwnd=0);
99
100
101 protected:
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
106
107
108         static WindowMap        s_wnd_map;
109
110         static const void*      s_new_info;
111         static CREATORFUNC      s_window_creator;
112
113
114         struct StaticWindowData {
115                 CritSect        _map_crit_sect;
116                 CritSect        _create_crit_sect;
117         };
118
119         static StaticWindowData& GetStaticWindowData();
120
121
122          // MDI child creation
123         static HHOOK s_hcbtHook;
124         static LRESULT CALLBACK CBTHookProc(int code, WPARAM wparam, LPARAM lparam);
125
126         static WindowSet s_pretranslate_windows;
127         static WindowSet s_dialogs;
128 };
129
130
131 #ifdef _MSC_VER
132 template<typename CLASS> struct GetWindowHelper
133 {
134         static CLASS* get_window(HWND hwnd) {
135                 return static_cast<CLASS*>(Window::get_window(hwnd));
136         }
137 };
138 #define GET_WINDOW(CLASS, hwnd) GetWindowHelper<CLASS>::get_window(hwnd)
139 #endif
140
141
142 template<typename CLASS> struct TypeCheck
143 {
144         static CLASS* dyn_cast(Window* wnd)
145                 {return dynamic_cast<CLASS*>(wnd);}
146 };
147
148 #define WINDOW_DYNAMIC_CAST(CLASS, hwnd) \
149         TypeCheck<CLASS>::dyn_cast(Window::get_window(hwnd))
150
151
152  /**
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
156         gets destroyed.
157  */
158 struct SubclassedWindow : public Window
159 {
160         typedef Window super;
161
162         SubclassedWindow(HWND);
163
164 protected:
165         WNDPROC _orgWndProc;
166
167         LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
168 };
169
170
171 template<typename WND_CLASS> struct WindowCreator
172 {
173         static WND_CLASS* window_creator(HWND hwnd)
174         {
175                 return new WND_CLASS(hwnd);
176         }
177 };
178
179 #define WINDOW_CREATOR(WND_CLASS) \
180         (Window::CREATORFUNC) WindowCreator<WND_CLASS>::window_creator
181
182
183 template<typename WND_CLASS, typename INFO_CLASS> struct WindowCreatorInfo
184 {
185         static WND_CLASS* window_creator(HWND hwnd, const void* info)
186         {
187                 return new WND_CLASS(hwnd, *static_cast<const INFO_CLASS*>(info));
188         }
189 };
190
191 #define WINDOW_CREATOR_INFO(WND_CLASS, INFO_CLASS) \
192         (Window::CREATORFUNC) WindowCreatorInfo<WND_CLASS, INFO_CLASS>::window_creator
193
194
195  /**
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.
201  */
202 struct WindowClass : public WNDCLASSEX
203 {
204         WindowClass(LPCTSTR classname, UINT style=0, WNDPROC wndproc=Window::WindowWndProc);
205
206         ATOM Register()
207         {
208                 if (!_atomClass)
209                         _atomClass = RegisterClassEx(this);
210
211                 return _atomClass;
212         }
213
214         operator ATOM() {return Register();}
215
216          // return LPCTSTR for the CreateWindowEx() parameter
217         operator LPCTSTR() {return (LPCTSTR)(int)Register();}
218
219 protected:
220         ATOM    _atomClass;
221 };
222
223  /// window class with gray background color
224 struct BtnWindowClass : public WindowClass
225 {
226         BtnWindowClass(LPCTSTR classname, UINT style=0, WNDPROC wndproc=Window::WindowWndProc)
227          :      WindowClass(classname, style, wndproc)
228         {
229                 hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
230         }
231 };
232
233  /// window class with specified icon from resources
234 struct IconWindowClass : public WindowClass
235 {
236         IconWindowClass(LPCTSTR classname, UINT nid, UINT style=0, WNDPROC wndproc=Window::WindowWndProc);
237 };
238
239
240  // private message constants
241 #define PM_DISPATCH_COMMAND             (WM_APP+0x00)
242 #define PM_TRANSLATE_MSG                (WM_APP+0x01)
243
244
245 #define SPLIT_WIDTH             5
246 #define DEFAULT_SPLIT_POS       300
247 #define COLOR_SPLITBAR          LTGRAY_BRUSH
248
249
250  /// menu info structure for MDI child windows
251 struct MenuInfo
252 {
253         HMENU   _hMenuView;
254         HMENU   _hMenuOptions;
255 };
256
257 #define PM_FRM_GET_MENUINFO             (WM_APP+0x02)
258
259 #define Frame_GetMenuInfo(hwnd) ((MenuInfo*)SNDMSG(hwnd, PM_FRM_GET_MENUINFO, 0, 0))
260
261
262  /**
263         Class ChildWindow represents MDI child windows.
264         It is used with class MainFrame.
265  */
266 struct ChildWindow : public Window
267 {
268         typedef Window super;
269
270         ChildWindow(HWND hwnd);
271
272         static ChildWindow* create(HWND hmdiclient, const RECT& rect,
273                                 CREATORFUNC creator, LPCTSTR classname, LPCTSTR title=NULL, const void* info=NULL);
274
275 protected:
276         LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
277
278         virtual void resize_children(int cx, int cy);
279
280 protected:
281         MenuInfo*_menu_info;
282
283         WindowHandle _left_hwnd;
284         WindowHandle _right_hwnd;
285         int     _focus_pane;            // 0: left      1: right
286
287         int     _split_pos;
288         int             _last_split;
289 };
290
291
292  /**
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.
296  */
297 struct PreTranslateWindow : public Window
298 {
299         typedef Window super;
300
301         PreTranslateWindow(HWND);
302         ~PreTranslateWindow();
303 };
304
305
306  /**
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.
311  */
312 struct Dialog : public Window
313 {
314         typedef Window super;
315
316         Dialog(HWND);
317         ~Dialog();
318 };
319
320
321  /**
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.
325  */
326 struct Button : public WindowHandle
327 {
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);
330 };
331
332
333  /**
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.
337  */
338 struct Static : public WindowHandle
339 {
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);
342 };
343
344
345 /*
346  // control color message routing for ColorStatic and HyperlinkCtrl
347
348 #define PM_DISPATCH_CTLCOLOR    (WM_APP+0x07)
349
350 template<typename BASE> struct CtlColorParent : public BASE
351 {
352         typedef BASE super;
353
354         CtlColorParent(HWND hwnd)
355          : super(hwnd) {}
356
357         LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
358         {
359                 switch(nmsg) {
360                   case WM_CTLCOLOR:
361                   case WM_CTLCOLORBTN:
362                   case WM_CTLCOLORDLG:
363                   case WM_CTLCOLORSCROLLBAR:
364                   case WM_CTLCOLORSTATIC: {
365                         HWND hctl = (HWND) lparam;
366                         return SendMessage(hctl, PM_DISPATCH_CTLCOLOR, wparam, nmsg);
367                   }
368
369                   default:
370                         return super::WndProc(nmsg, wparam, lparam);
371                 }
372         }
373 };
374 */
375
376
377  // owner draw message routing for ColorButton and PictureButton 
378
379 #define PM_DISPATCH_DRAWITEM    (WM_APP+0x08)
380
381 template<typename BASE> struct OwnerDrawParent : public BASE
382 {
383         typedef BASE super;
384
385         OwnerDrawParent(HWND hwnd)
386          : super(hwnd) {}
387
388         LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
389         {
390                 switch(nmsg) {
391                   case WM_DRAWITEM:
392                         if (wparam) {   // should there be drawn a control?
393                                 HWND hctl = GetDlgItem(_hwnd, wparam);
394
395                                 if (hctl)
396                                         return SendMessage(hctl, PM_DISPATCH_DRAWITEM, wparam, lparam);
397                         } /*else                // or is it a menu entry?
398                                 ; */
399
400                         return 0;
401
402                   default:
403                         return super::WndProc(nmsg, wparam, lparam);
404                 }
405         }
406 };
407
408
409  /**
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.
412  */
413 struct OwnerdrawnButton : public SubclassedWindow
414 {
415         typedef SubclassedWindow super;
416
417         OwnerdrawnButton(HWND hwnd)
418          :      super(hwnd) {}
419
420 protected:
421         LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
422
423         void    DrawGrayText(LPDRAWITEMSTRUCT dis, LPRECT pRect, LPCTSTR text, int dt_flags);
424
425         virtual void DrawItem(LPDRAWITEMSTRUCT dis) = 0;
426 };
427
428
429  /**
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.
432  */
433 /* not yet used
434 struct ColorButton : public OwnerdrawnButton
435 {
436         typedef OwnerdrawnButton super;
437
438         ColorButton(HWND hwnd, COLORREF textColor)
439          :      super(hwnd), _textColor(textColor) {}
440
441 protected:
442         virtual void DrawItem(LPDRAWITEMSTRUCT dis);
443
444         COLORREF _textColor;
445 };
446 */
447
448
449  /**
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.
453  */
454 struct PictureButton : public OwnerdrawnButton
455 {
456         typedef OwnerdrawnButton super;
457
458         PictureButton(HWND hwnd, HICON hIcon, HBRUSH hbrush=GetSysColorBrush(COLOR_BTNFACE), bool flat=false)
459          :      super(hwnd), _hIcon(hIcon), _hBrush(hbrush), _flat(flat)
460         {
461         }
462
463 protected:
464         virtual void DrawItem(LPDRAWITEMSTRUCT dis);
465
466         HICON   _hIcon;
467         HBRUSH  _hBrush;
468         bool    _flat;
469 };
470
471
472 struct ToolTip : public WindowHandle
473 {
474         typedef WindowHandle super;
475
476         ToolTip(HWND owner);
477
478         void activate(BOOL active=TRUE)
479         {
480                 SendMessage(_hwnd, TTM_ACTIVATE, active, 0);
481         }
482
483         void add(HWND hparent, HWND htool, LPCTSTR txt=LPSTR_TEXTCALLBACK)
484         {
485                 TOOLINFO ti = {
486                         sizeof(TOOLINFO), TTF_SUBCLASS|TTF_IDISHWND/*|TTF_TRANSPARENT*/, hparent, (UINT)htool, {0,0,0,0}, 0, 0, 0
487                 };
488                 ti.lpszText = (LPTSTR) txt;
489
490                 SendMessage(_hwnd, TTM_ADDTOOL, 0, (LPARAM)&ti);
491         }
492 };