]> git.saurik.com Git - wxWidgets.git/blob - src/msw/control.cpp
1beeb2b8d266e7305f3b3d375b8e06c342280bc0
[wxWidgets.git] / src / msw / control.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/control.cpp
3 // Purpose: wxControl class
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "control.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #if wxUSE_CONTROLS
24
25 #ifndef WX_PRECOMP
26 #include "wx/event.h"
27 #include "wx/app.h"
28 #include "wx/dcclient.h"
29 #include "wx/log.h"
30 #endif
31
32 #include "wx/control.h"
33
34 #include "wx/msw/private.h"
35
36 #if defined(__WIN95__) && !((defined(__GNUWIN32_OLD__) || defined(__TWIN32__)) && !defined(__CYGWIN10__))
37 #include <commctrl.h>
38 #endif
39
40 IMPLEMENT_ABSTRACT_CLASS(wxControl, wxWindow)
41
42 BEGIN_EVENT_TABLE(wxControl, wxWindow)
43 EVT_ERASE_BACKGROUND(wxControl::OnEraseBackground)
44 END_EVENT_TABLE()
45
46 // Item members
47 wxControl::wxControl()
48 {
49 #if WXWIN_COMPATIBILITY
50 m_callback = 0;
51 #endif // WXWIN_COMPATIBILITY
52 }
53
54 wxControl::~wxControl()
55 {
56 m_isBeingDeleted = TRUE;
57 }
58
59
60 bool wxControl::Create(wxWindow *parent,
61 wxWindowID id,
62 const wxPoint& pos,
63 const wxSize& size,
64 long style,
65 const wxValidator& validator,
66 const wxString& name)
67 {
68 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
69 return FALSE;
70
71 #if wxUSE_VALIDATORS
72 SetValidator(validator);
73 #endif
74
75 return TRUE;
76 }
77
78 bool wxControl::MSWCreateControl(const wxChar *classname,
79 const wxString& label,
80 const wxPoint& pos,
81 const wxSize& size,
82 long style,
83 bool visible)
84 {
85 WXDWORD exstyle;
86 WXDWORD msStyle = MSWGetStyle(style, &exstyle);
87
88 return MSWCreateControl(classname, msStyle, pos, size, label, exstyle, visible);
89 }
90
91 bool wxControl::MSWCreateControl(const wxChar *classname,
92 WXDWORD style,
93 const wxPoint& pos,
94 const wxSize& size,
95 const wxString& label,
96 WXDWORD exstyle,
97 bool visible)
98 {
99 // want3D tells us whether or not the style specified a 3D border.
100 // If so, under WIN16 we can use Ctl3D to give it an appropriate style.
101 // Sometimes want3D is used to indicate that the non-extended style should have
102 // WS_BORDER.
103 bool want3D = TRUE;
104
105 // if no extended style given, determine it ourselves
106 if ( exstyle == (WXDWORD)-1 )
107 {
108 exstyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D);
109 }
110
111 // all controls should have these styles (wxWindows creates all controls
112 // visible by default)
113 style |= WS_CHILD;
114
115 // sometimes, controls will defer showing the window until
116 // all configuration, sizing, and positioning is completed
117 if (!visible)
118 {
119 m_isShown = FALSE;
120 }
121 else
122 {
123 style |= WS_VISIBLE;
124 }
125
126 int x = pos.x == -1 ? 0 : pos.x,
127 y = pos.y == -1 ? 0 : pos.y,
128 w = size.x == -1 ? 0 : size.x,
129 h = size.y == -1 ? 0 : size.y;
130
131 m_hWnd = (WXHWND)::CreateWindowEx
132 (
133 exstyle, // extended style
134 classname, // the kind of control to create
135 label, // the window name
136 style, // the window style
137 x, y, w, h, // the window position and size
138 GetHwndOf(GetParent()), // parent
139 (HMENU)GetId(), // child id
140 wxGetInstance(), // app instance
141 NULL // creation parameters
142 );
143
144 if ( !m_hWnd )
145 {
146 wxLogDebug(wxT("Failed to create a control of class '%s'"), classname);
147 wxFAIL_MSG(_T("something is very wrong"));
148
149 return FALSE;
150 }
151
152 #if wxUSE_CTL3D
153 if ( want3D )
154 {
155 Ctl3dSubclassCtl(GetHwnd());
156 m_useCtl3D = TRUE;
157 }
158 #endif // wxUSE_CTL3D
159
160 // install wxWindows window proc for this window
161 SubclassWin(m_hWnd);
162
163 // controls use the same font and colours as their parent dialog by default
164 InheritAttributes();
165
166 // set the size now if no initial size specified
167 if ( w == 0 || h == 0 )
168 {
169 SetBestSize(size);
170 }
171
172 return TRUE;
173 }
174
175 wxSize wxControl::DoGetBestSize() const
176 {
177 return wxSize(DEFAULT_ITEM_WIDTH, DEFAULT_ITEM_HEIGHT);
178 }
179
180 bool wxControl::ProcessCommand(wxCommandEvent& event)
181 {
182 #if WXWIN_COMPATIBILITY
183 if ( m_callback )
184 {
185 (void)(*m_callback)(*this, event);
186
187 return TRUE;
188 }
189 else
190 #endif // WXWIN_COMPATIBILITY
191
192 return GetEventHandler()->ProcessEvent(event);
193 }
194
195 #ifdef __WIN95__
196 bool wxControl::MSWOnNotify(int idCtrl,
197 WXLPARAM lParam,
198 WXLPARAM* result)
199 {
200 wxEventType eventType = wxEVT_NULL;
201
202 NMHDR *hdr = (NMHDR*) lParam;
203 switch ( hdr->code )
204 {
205 case NM_CLICK:
206 eventType = wxEVT_COMMAND_LEFT_CLICK;
207 break;
208
209 case NM_DBLCLK:
210 eventType = wxEVT_COMMAND_LEFT_DCLICK;
211 break;
212
213 case NM_RCLICK:
214 eventType = wxEVT_COMMAND_RIGHT_CLICK;
215 break;
216
217 case NM_RDBLCLK:
218 eventType = wxEVT_COMMAND_RIGHT_DCLICK;
219 break;
220
221 case NM_SETFOCUS:
222 eventType = wxEVT_COMMAND_SET_FOCUS;
223 break;
224
225 case NM_KILLFOCUS:
226 eventType = wxEVT_COMMAND_KILL_FOCUS;
227 break;
228
229 case NM_RETURN:
230 eventType = wxEVT_COMMAND_ENTER;
231 break;
232
233 default:
234 return wxWindow::MSWOnNotify(idCtrl, lParam, result);
235 }
236
237 wxCommandEvent event(wxEVT_NULL, m_windowId);
238 event.SetEventType(eventType);
239 event.SetEventObject(this);
240
241 return GetEventHandler()->ProcessEvent(event);
242 }
243 #endif // Win95
244
245 void wxControl::OnEraseBackground(wxEraseEvent& event)
246 {
247 // notice that this 'dumb' implementation may cause flicker for some of the
248 // controls in which case they should intercept wxEraseEvent and process it
249 // themselves somehow
250
251 RECT rect;
252 ::GetClientRect(GetHwnd(), &rect);
253
254 HBRUSH hBrush = ::CreateSolidBrush(wxColourToRGB(GetBackgroundColour()));
255
256 HDC hdc = GetHdcOf((*event.GetDC()));
257 int mode = ::SetMapMode(hdc, MM_TEXT);
258
259 ::FillRect(hdc, &rect, hBrush);
260 ::DeleteObject(hBrush);
261 ::SetMapMode(hdc, mode);
262 }
263
264 WXHBRUSH wxControl::OnCtlColor(WXHDC pDC, WXHWND WXUNUSED(pWnd), WXUINT WXUNUSED(nCtlColor),
265 #if wxUSE_CTL3D
266 WXUINT message,
267 WXWPARAM wParam,
268 WXLPARAM lParam
269 #else
270 WXUINT WXUNUSED(message),
271 WXWPARAM WXUNUSED(wParam),
272 WXLPARAM WXUNUSED(lParam)
273 #endif
274 )
275 {
276 #if wxUSE_CTL3D
277 if ( m_useCtl3D )
278 {
279 HBRUSH hbrush = Ctl3dCtlColorEx(message, wParam, lParam);
280 return (WXHBRUSH) hbrush;
281 }
282 #endif // wxUSE_CTL3D
283
284 HDC hdc = (HDC)pDC;
285 if (GetParent()->GetTransparentBackground())
286 SetBkMode(hdc, TRANSPARENT);
287 else
288 SetBkMode(hdc, OPAQUE);
289
290 wxColour colBack = GetBackgroundColour();
291
292 ::SetBkColor(hdc, wxColourToRGB(colBack));
293 ::SetTextColor(hdc, wxColourToRGB(GetForegroundColour()));
294
295 wxBrush *brush = wxTheBrushList->FindOrCreateBrush(colBack, wxSOLID);
296
297 return (WXHBRUSH)brush->GetResourceHandle();
298 }
299
300 WXDWORD wxControl::MSWGetStyle(long style, WXDWORD *exstyle) const
301 {
302 long msStyle = wxWindow::MSWGetStyle(style, exstyle);
303
304 if ( AcceptsFocus() )
305 {
306 msStyle |= WS_TABSTOP;
307 }
308
309 return msStyle;
310 }
311
312 // ---------------------------------------------------------------------------
313 // global functions
314 // ---------------------------------------------------------------------------
315
316 // Call this repeatedly for several wnds to find the overall size
317 // of the widget.
318 // Call it initially with -1 for all values in rect.
319 // Keep calling for other widgets, and rect will be modified
320 // to calculate largest bounding rectangle.
321 void wxFindMaxSize(WXHWND wnd, RECT *rect)
322 {
323 int left = rect->left;
324 int right = rect->right;
325 int top = rect->top;
326 int bottom = rect->bottom;
327
328 GetWindowRect((HWND) wnd, rect);
329
330 if (left < 0)
331 return;
332
333 if (left < rect->left)
334 rect->left = left;
335
336 if (right > rect->right)
337 rect->right = right;
338
339 if (top < rect->top)
340 rect->top = top;
341
342 if (bottom > rect->bottom)
343 rect->bottom = bottom;
344 }
345
346 #endif // wxUSE_CONTROLS