1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // License Agreement:
4 //
5 // The following are Copyright � 2007, Casey Langen
6 //
7 // Sources and Binaries of: win32cpp
8 //
9 // All rights reserved.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are met:
13 //
14 //    * Redistributions of source code must retain the above copyright notice,
15 //      this list of conditions and the following disclaimer.
16 //
17 //    * Redistributions in binary form must reproduce the above copyright
18 //      notice, this list of conditions and the following disclaimer in the
19 //      documentation and/or other materials provided with the distribution.
20 //
21 //    * Neither the name of the author nor the names of other contributors may
22 //      be used to endorse or promote products derived from this software
23 //      without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 // POSSIBILITY OF SUCH DAMAGE.
36 //
37 //////////////////////////////////////////////////////////////////////////////
38 
39 #pragma once
40 
41 //////////////////////////////////////////////////////////////////////////////
42 // Forward declare
43 namespace win32cpp {
44     struct Color;
45 }
46 //////////////////////////////////////////////////////////////////////////////
47 
48 
49 #include <win32cpp/Win32Config.hpp>
50 #include <win32cpp/Types.hpp>
51 #include <win32cpp/Exception.hpp>
52 #include <win32cpp/Font.hpp>
53 #include <win32cpp/Menu.hpp>
54 #include <win32cpp/WindowPadding.hpp>
55 
56 #include <vector>
57 #include <map>
58 #include <set>
59 
60 //////////////////////////////////////////////////////////////////////////////
61 
62 namespace win32cpp {
63 
64 //////////////////////////////////////////////////////////////////////////////
65 
66 class Window;
67 
68 ///\brief Flags used for control layout
69 enum LayoutFlags
70 {
71     LayoutFillParent = -1,      /*!< */
72     LayoutWrapContent = -2,     /*!< */
73     LayoutWrapWrap = -3,        /*!< */
74     LayoutFillWrap = -4,        /*!< */
75     LayoutWrapFill = -5,        /*!< */
76     LayoutFillFill = -6         /*!< */
77 };
78 
79 ///\brief Specifies the alignment of a Layout's child
80 enum LayoutAlignFlag
81 {
82     LayoutAlignLeft = 0,     /*!< */
83     LayoutAlignRight = 1,    /*!< */
84     LayoutAlignCenter = 2,   /*!< */
85     LayoutAlignTop = 0,      /*!< */
86     LayoutAlignBottom = 1,   /*!< */
87     LayoutAlignMiddle = 2,   /*!< */
88 };
89 
90 ///\brief Flags used for mouse related events emitted by Window.
91 enum MouseEventFlags
92 {
93     MouseShiftKey = MK_SHIFT,       /*!< */
94     MouseCtrlKey = MK_CONTROL,      /*!< */
95     MouseLeftButton = MK_LBUTTON,   /*!< */
96     MouseMiddleButton = MK_MBUTTON, /*!< */
97     MouseRightButton = MK_RBUTTON,  /*!< */
98     MouseX1Button = MK_XBUTTON1,    /*!< */
99     MouseX2Button = MK_XBUTTON2     /*!< */
100 };
101 
102 /*! */ typedef DWORD VirtualKeyCode;
103 /*! */ typedef DWORD KeyEventFlags;
104 
105 /*! */ typedef sigslot::signal1<Window*> DestroyedEvent;
106 /*! */ typedef sigslot::signal1<Window*> CreatedEvent;
107 /*! */ typedef sigslot::signal2<Window*, Point> MovedEvent;
108 /*! */ typedef sigslot::signal2<Window*, Size> ResizedEvent;
109 /*! */ typedef sigslot::signal1<Window*> MouseEnterEvent;
110 /*! */ typedef sigslot::signal1<Window*> MouseExitEvent;
111 /*! */ typedef sigslot::signal3<Window*, MouseEventFlags, Point> MouseMovedEvent;
112 /*! */ typedef sigslot::signal3<Window*, MouseEventFlags, Point> MouseButtonEvent;
113 /*! */ typedef sigslot::signal1<Window*> ThemeChangedEvent;
114 /*! */ typedef sigslot::signal1<Window* /*this*/> FocusEvent;
115 /*! */ typedef sigslot::signal2<Window* /*old*/, Window* /*new*/> ParentChangedEvent;
116 /*! */ typedef sigslot::signal1<unsigned int> TimerEvent;
117 /*! */ typedef sigslot::signal3<Window*, VirtualKeyCode, KeyEventFlags> KeyEvent;
118 /*! */ typedef sigslot::signal2<Window*, bool> VisibilityChangedEvent;
119 /*! */ typedef sigslot::signal1<Window*> LayoutParamsChangedEvent;
120 
121 ///\brief
122 ///Window is the abstract base class for all controls.
123 ///
124 ///Based on sigslot signals, Window follows the observer/notifier pattern
125 ///and is able to "emit" notifications to listeners that are not
126 ///necessarily GUI objects. This promotes use of the model/view/controller
127 ///design pattern, which is highly recommended. Window also attempts to
128 ///automatically double buffer all drawing, so controls don't flicker when
129 ///they are moved or resized. This is accomplished using the MemoryDC
130 ///and RedrawLock classes.
131 ///
132 ///The Window class also provides "stable" mouse events for derived
133 ///classes, including consistant cursor enter and exit notifications.
134 /*abstract*/ class Window: public EventHandler
135 {
136 public: // types
137     ///\brief
138     ///This exception will be thrown if Initialize() is called on a
139     ///Window that has already been created.
140     class WindowAlreadyCreatedException: public Exception { };
141     ///\brief
142     ///This exception may be thrown if operations are attempted on a
143     ///Window that has not been created.
144     class WindowNotCreatedException: public Exception { };
145     ///\brief
146     ///This exception is thrown if a Window fails to be created.
147     class WindowCreationFailedException: public Exception { };
148     ///\brief
149     ///This exception is thrown if a Window parameter is NULL where it shouldn't be.
150     class WindowIsNullException: public Exception { };
151     ///\brief
152     ///This exception is thrown if an invalid (negative) LayoutWeight is specified.
153     class InvalidLayoutWeightException: public Exception { };
154     ///\brief
155     ///This exception is thrown if invalid layout flags are specified.
156     class InvalidLayoutFlagsException: public Exception { };
157 
158 protected: // types
159     typedef WNDPROC WindowProcFunc;
160     typedef std::vector<Window*> WindowList;
161     typedef std::map<HWND, Window*> HandleToWindowMap;
162     typedef sigslot::_signal_base<sigslot::SIGSLOT_DEFAULT_MT_POLICY> SignalBase;
163     typedef std::set<SignalBase*> SignalList;
164     typedef std::unique_ptr<Color> ColorRef;
165 
166     enum FocusDirection
167     {
168         FocusForward,
169         FocusBackward
170     };
171 
172 public:     // events
173     ///\brief Emitted when the WM_DESTROY message is received.
174     DestroyedEvent              Destroyed;
175     ///\brief Emitted when the Window is created. This is not necessarily
176     ///at construction time, as Windows are lazily created.
177     CreatedEvent                Created;
178     ///\brief Emitted when the Window is repositioned.
179     MovedEvent                  Moved;
180     ///\brief Emitted when the Window is resized.
181     ResizedEvent                Resized;
182     ///\brief Emitted when the cursor is moved over the Window.
183     MouseMovedEvent             MouseMoved;
184     ///\brief Emitted when a mouse button has been pressed over the Window.
185     MouseButtonEvent            MouseButtonDown;
186     ///\brief Emitted when a mouse button has been released over the Window.
187     MouseButtonEvent            MouseButtonUp;
188     ///\brief Emitted when a mouse button has been double clicked over the Window.
189     MouseButtonEvent            MouseButtonDoubleClicked;
190     ///\brief Emitted when the cursor has entered the Window.
191     MouseEnterEvent             MouseEnter;
192     ///\brief Emitted when the cursor has left the Window.
193     MouseExitEvent              MouseExit;
194     ///\brief Emitted when the desktop theme has changed.
195     ThemeChangedEvent           ThemeChanged;
196     ///\brief Emitted when the Window has gained focus.
197     FocusEvent                  GainedFocus;
198     ///\brief Emitted when the Window has lost focus.
199     FocusEvent                  LostFocus;
200     ///\brief Emitted when the Window's parent has changed.
201     ParentChangedEvent          ParentChanged;
202     ///\brief Emitted when a timer gets a timeout.
203     TimerEvent                  TimerTimeout;
204     ///\brief Emitted when a key on the keyboard is pressed down.
205     KeyEvent                    KeyDown;
206     ///\brief Emitted when a key on the keyboard is released.
207     KeyEvent                    KeyUp;
208     ///\brief Emitted when a key on the keyboard is pressed.
209     KeyEvent                    Char;
210     ///\brief Emitted when a control has requested to focus the next control. This
211     ///generally shouldn't be handled explicitly unless absolutely necessary.
212     FocusEvent                  RequestFocusNext;
213     ///\brief Emitted when a control has requested to focus the previous control. This
214     ///generally shouldn't be handled explicitly unless absolutely necessary.
215     FocusEvent                  RequestFocusPrev;
216     ///\brief Emitted when a Window's visibility has changed
217     VisibilityChangedEvent      VisibilityChanged;
218     ///\brief Emitted when a Window's layout parameters have changed.
219     LayoutParamsChangedEvent    LayoutParametersChanged;
220 
221 public: // ctor, dtor
222     /*ctor*/            Window();
223     /*ctor*/            Window(LayoutFlags layoutFlags);
224     /*dtor*/ virtual    ~Window();
225 
226 public: // methods
227     void            Initialize(Window* parent = NULL);
228     bool            Show(int showCommand);
229     bool            MoveTo(int x, int y);
230     bool            MoveRelativeTo(int x, int y);
231     bool            MoveTo(const Point& location);
232     bool            Resize(int width, int height);
233     bool            Resize(const Size& size);
234     bool            SetRectangle(const Rect& rectangle);
235     bool            Enable(bool enable);
236     uistring        Caption() const;
237     bool            SetCaption(const uistring& caption);
238     Rect            ClientRect() const;
239     Rect            WindowRect() const;
240     Size            WindowSize() const;
241     virtual Size    ClientSize() const;
242     Point           Location() const;
243     Point           CursorPosition() const;
244     LRESULT         SendMessage(UINT message, WPARAM wParam, LPARAM lParam);
245     bool            PostMessage(UINT message, WPARAM wParam, LPARAM lParam);
246     HWND            Handle() const;
247     virtual bool    Destroy();
248     Window*         Parent() const;
249     void            Redraw() const;
250     void            SetFont(FontRef font);
251     FontRef         Font() const;
252     void            SetMenu(MenuRef menu);
253     MenuRef         Menu();
254     void            SetVisible(bool visible = true);
255     bool            Visible();
256     void            SetBackgroundColor(const Color& color);
257     Color           BackgroundColor() const;
258     bool            SetFocus();
259     bool            TabStop();
260     void            SetTabStop(bool enabled);
261     LayoutFlags     LayoutWidth() const;
262     LayoutFlags     LayoutHeight() const;
263     LayoutAlignFlag LayoutAlignment() const;
264     void            SetLayoutFlags(LayoutFlags widthFlag, LayoutFlags heightFlag);
265     void            SetLayoutFlags(LayoutFlags flags);
266     void            SetLayoutAlignment(LayoutAlignFlag alignment);
267     float           LayoutWeight() const;
268     void            SetLayoutWeight(float weight);
269 
270     static Window*  SubclassedWindowFromHWND(HWND hwnd);
271 
272 public: // operators
operator bool()273     operator bool() { return (this->windowHandle != NULL); }
274 
275 protected: // methods
276     // pure virtuals
277     virtual HWND        Create(Window* parent = NULL) = 0;
278 
279     // subclassing, mouse capture
280     static void         SubclassWindowProc(Window* window);
281     static void         UnSubclassWindowProc(Window* window);
282     static bool         IsWindowSubclassed(Window* window);
283     static Window*      WindowUnderCursor(HWND* targetHwnd = NULL);
284     static void         BeginCapture(Window* window);
285     static void         EndCapture(Window* window);
286     static void         SetParent(Window* child, Window* newParent);
287     static void         ForceMeasureItem(const Window* window);
288     static Window*      Capture();
289 
290     // win32 event wrappers (template pattern, effective c++ item 35)
291     void    OnDestroyedBase();
292     void    OnCreatedBase();
293     void    OnMovedBase(const Point& location);
294     void    OnResizedBase(const Size& newSize);
295     void    OnMouseMovedBase(MouseEventFlags flags, const Point& location);
296     void    OnMouseButtonDownBase(MouseEventFlags flags, const Point& location);
297     void    OnMouseButtonUpBase(MouseEventFlags flags, const Point& location);
298     void    OnMouseButtonDoubleClickedBase(MouseEventFlags flags, const Point& location);
299     void    OnMouseEnterBase();
300     void    OnMouseExitBase();
301     void    OnGainedFocusBase();
302     void    OnLostFocusBase();
303     void    OnThemeChangedBase();
304     void    OnParentChangedBase(Window* oldParent, Window* newParent);
305     bool    OnKeyDownBase(VirtualKeyCode keyCode, KeyEventFlags flags);
306     bool    OnKeyUpBase(VirtualKeyCode keyCode, KeyEventFlags flags);
307     bool    OnCharBase(VirtualKeyCode keyCode, KeyEventFlags flags);
308     void    OnVisibilityChangedBase(bool visible);
309     void    OnLayoutParametersChangedBase();
310 
311     // win32 event wrappers (virtual methods, for derived class use)
OnDestroyed()312     virtual void    OnDestroyed() { }
OnCreated()313     virtual void    OnCreated() { }
OnMoved(const Point & location)314     virtual void    OnMoved(const Point& location) { }
OnResized(const Size & newSize)315     virtual void    OnResized(const Size& newSize) { }
OnMouseMoved(MouseEventFlags flags,const Point & location)316     virtual void    OnMouseMoved(MouseEventFlags flags, const Point& location) { }
OnMouseButtonDown(MouseEventFlags flags,const Point & location)317     virtual void    OnMouseButtonDown(MouseEventFlags flags, const Point& location) { }
OnMouseButtonUp(MouseEventFlags flags,const Point & location)318     virtual void    OnMouseButtonUp(MouseEventFlags flags, const Point& location) { }
OnMouseButtonDoubleClicked(MouseEventFlags flags,const Point & location)319     virtual void    OnMouseButtonDoubleClicked(MouseEventFlags flags, const Point& location) { }
OnMouseEnter()320     virtual void    OnMouseEnter() { }
OnMouseExit()321     virtual void    OnMouseExit() { }
OnGainedFocus()322     virtual void    OnGainedFocus() { }
OnLostFocus()323     virtual void    OnLostFocus() { }
324     virtual void    OnThemeChanged();
OnFontChanged()325     virtual void    OnFontChanged() { }
OnMeasureItem(MEASUREITEMSTRUCT * measureItemStruct)326     virtual void    OnMeasureItem(MEASUREITEMSTRUCT* measureItemStruct) { }
OnParentChanged(Window * oldParent,Window * newParent)327     virtual void    OnParentChanged(Window* oldParent, Window* newParent) { }
OnCaptionChanged()328     virtual void    OnCaptionChanged() { }
OnLayoutParametersChanged()329     virtual void    OnLayoutParametersChanged() { }
OnKeyDown(VirtualKeyCode keyCode,KeyEventFlags flags)330     virtual bool    OnKeyDown(VirtualKeyCode keyCode, KeyEventFlags flags) { return false; }
OnKeyUp(VirtualKeyCode keyCode,KeyEventFlags flags)331     virtual bool    OnKeyUp(VirtualKeyCode keyCode, KeyEventFlags flags) { return false; }
OnChar(VirtualKeyCode keyCode,KeyEventFlags flags)332     virtual bool    OnChar(VirtualKeyCode keyCode, KeyEventFlags flags) { return false; }
333     virtual void    OnEraseBackground(HDC hdc);
334     virtual void    OnPaint();
335     virtual void    OnRequestFocusPrev();
336     virtual void    OnRequestFocusNext();
337     virtual HBRUSH  OnControlColor(HDC hdc);
OnVisibilityChanged(bool visible)338     virtual void    OnVisibilityChanged(bool visible) { }
339 
DrawItem(DRAWITEMSTRUCT & item)340     virtual LRESULT DrawItem(DRAWITEMSTRUCT& item) { return 0; }
341 
342     // window proc related
343     virtual LRESULT             PreWindowProcBase(UINT message, WPARAM wParam, LPARAM lParam, bool& discardMessage);
344     virtual LRESULT             PreWindowProc(UINT message, WPARAM wParam, LPARAM lParam, bool& discardMessage);
345     void                        PostWindowProcBase(UINT message, WPARAM wParam, LPARAM lParam);
346     virtual void                PostWindowProc(UINT message, WPARAM wParam, LPARAM lParam);
347     virtual LRESULT             WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
348     LRESULT                     DefaultWindowProc(UINT message, WPARAM wParam, LPARAM lParam);
349     static LRESULT CALLBACK     StaticWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
350 
351     // misc
352     virtual void    PaintToHDC(HDC hdc, const Rect& rect);
353     void            SuppressSignal(SignalBase& signal);
354     static bool     WindowHasParent(Window* window);
355     static bool     WindowIsValid(Window* window);
356 
357 private:
358     void InitializeInstance();
359 
360 protected: // instance data
361     WindowProcFunc defaultWindowProc;
362     HWND windowHandle;
363     HBRUSH backgroundBrush;
364     FontRef font;
365     MenuRef menu;
366     ColorRef backgroundColor;
367     bool usesDefaultFont;
368     SignalList suppressedSignals;
369     bool tabStop;
370     LayoutAlignFlag layoutAlignment;
371     LayoutFlags layoutWidth, layoutHeight;
372     float layoutWeight;
373 
374 protected: // class data
375     static HandleToWindowMap sHandleToWindowMap;
376     static WindowList sAllChildWindows;
377     static FontRef sDefaultFont;
378     static FocusDirection sFocusDirection;
379 };
380 
381 //////////////////////////////////////////////////////////////////////////////
382 
383 } // win32cpp
384