check that HWNDs are non-NULL before doing anything with them (part of patch 1866053)
[wxWidgets.git] / include / wx / msw / subwin.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: wx/msw/subwin.h
3 // Purpose: helper for implementing the controls with subwindows
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 2004-12-11
7 // RCS-ID: $Id$
8 // Copyright: (c) 2004 Vadim Zeitlin <vadim@wxwindows.org>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 #ifndef _WX_MSW_SUBWIN_H_
13 #define _WX_MSW_SUBWIN_H_
14
15 #include "wx/msw/private.h"
16
17 // ----------------------------------------------------------------------------
18 // wxSubwindows contains all HWNDs making part of a single wx control
19 // ----------------------------------------------------------------------------
20
21 class WXDLLEXPORT wxSubwindows
22 {
23 public:
24 // the number of subwindows can be specified either as parameter to ctor or
25 // later in Create()
26 wxSubwindows(size_t n = 0) { Init(); if ( n ) Create(n); }
27
28 // allocate enough space for the given number of windows
29 void Create(size_t n)
30 {
31 wxASSERT_MSG( !m_hwnds, _T("Create() called twice?") );
32
33 m_count = n;
34 m_hwnds = (HWND *)calloc(n, sizeof(HWND));
35 m_ids = new wxWindowIDRef[n];
36 }
37
38 // non-virtual dtor, this class is not supposed to be used polymorphically
39 ~wxSubwindows()
40 {
41 for ( size_t n = 0; n < m_count; n++ )
42 {
43 if ( m_hwnds[n] )
44 ::DestroyWindow(m_hwnds[n]);
45 }
46
47 free(m_hwnds);
48 delete [] m_ids;
49 }
50
51 // get the number of subwindows
52 size_t GetCount() const { return m_count; }
53
54 // access a given window
55 HWND& Get(size_t n)
56 {
57 wxASSERT_MSG( n < m_count, _T("subwindow index out of range") );
58
59 return m_hwnds[n];
60 }
61
62 HWND operator[](size_t n) const
63 {
64 return wx_const_cast(wxSubwindows *, this)->Get(n);
65 }
66
67 // initialize the given window: id will be stored in wxWindowIDRef ensuring
68 // that it is not reused while this object exists
69 void Set(size_t n, HWND hwnd, wxWindowID id)
70 {
71 wxASSERT_MSG( n < m_count, _T("subwindow index out of range") );
72
73 m_hwnds[n] = hwnd;
74 m_ids[n] = id;
75 }
76
77 // check if we have this window
78 bool HasWindow(HWND hwnd)
79 {
80 for ( size_t n = 0; n < m_count; n++ )
81 {
82 if ( m_hwnds[n] == hwnd )
83 return true;
84 }
85
86 return false;
87 }
88
89
90 // methods which are forwarded to all subwindows
91 // ---------------------------------------------
92
93 // show/hide everything
94 void Show(bool show)
95 {
96 int sw = show ? SW_SHOW : SW_HIDE;
97 for ( size_t n = 0; n < m_count; n++ )
98 {
99 if ( m_hwnds[n] )
100 ::ShowWindow(m_hwnds[n], sw);
101 }
102 }
103
104 // enable/disable everything
105 void Enable(bool enable)
106 {
107 for ( size_t n = 0; n < m_count; n++ )
108 {
109 if ( m_hwnds[n] )
110 ::EnableWindow(m_hwnds[n], enable);
111 }
112 }
113
114 // set font for all windows
115 void SetFont(const wxFont& font)
116 {
117 HFONT hfont = GetHfontOf(font);
118 wxCHECK_RET( hfont, _T("invalid font") );
119
120 for ( size_t n = 0; n < m_count; n++ )
121 {
122 if ( m_hwnds[n] )
123 {
124 ::SendMessage(m_hwnds[n], WM_SETFONT, (WPARAM)hfont, 0);
125
126 // otherwise the window might not be redrawn correctly
127 ::InvalidateRect(m_hwnds[n], NULL, FALSE /* don't erase bg */);
128 }
129 }
130 }
131
132 // find the bounding box for all windows
133 wxRect GetBoundingBox() const
134 {
135 wxRect r;
136 for ( size_t n = 0; n < m_count; n++ )
137 {
138 if ( m_hwnds[n] )
139 {
140 RECT rc;
141
142 ::GetWindowRect(m_hwnds[n], &rc);
143
144 r.Union(wxRectFromRECT(rc));
145 }
146 }
147
148 return r;
149 }
150
151 private:
152 void Init()
153 {
154 m_count = 0;
155 m_hwnds = NULL;
156 }
157
158 // number of elements in m_hwnds array
159 size_t m_count;
160
161 // the HWNDs we contain
162 HWND *m_hwnds;
163
164 // the IDs of the windows
165 wxWindowIDRef *m_ids;
166
167
168 DECLARE_NO_COPY_CLASS(wxSubwindows)
169 };
170
171 // convenient macro to forward a few methods which are usually propagated to
172 // subwindows to a wxSubwindows object
173 //
174 // parameters should be:
175 // - cname the name of the class implementing these methods
176 // - base the name of its base class
177 // - subwins the name of the member variable of type wxSubwindows *
178 #define WX_FORWARD_STD_METHODS_TO_SUBWINDOWS(cname, base, subwins) \
179 bool cname::ContainsHWND(WXHWND hWnd) const \
180 { \
181 return subwins && subwins->HasWindow((HWND)hWnd); \
182 } \
183 \
184 bool cname::Show(bool show) \
185 { \
186 if ( !base::Show(show) ) \
187 return false; \
188 \
189 if ( subwins ) \
190 subwins->Show(show); \
191 \
192 return true; \
193 } \
194 \
195 bool cname::Enable(bool enable) \
196 { \
197 if ( !base::Enable(enable) ) \
198 return false; \
199 \
200 if ( subwins ) \
201 subwins->Enable(enable); \
202 \
203 return true; \
204 } \
205 \
206 bool cname::SetFont(const wxFont& font) \
207 { \
208 if ( !base::SetFont(font) ) \
209 return false; \
210 \
211 if ( subwins ) \
212 subwins->SetFont(font); \
213 \
214 return true; \
215 }
216
217
218 #endif // _WX_MSW_SUBWIN_H_
219