]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/control.cpp
no changes; just code cleanup in OnEraseBackground()
[wxWidgets.git] / src / msw / control.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/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
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#if wxUSE_CONTROLS
28
29#ifndef WX_PRECOMP
30 #include "wx/event.h"
31 #include "wx/app.h"
32 #include "wx/dcclient.h"
33 #include "wx/log.h"
34 #include "wx/settings.h"
35#endif
36
37#include "wx/control.h"
38
39#if wxUSE_NOTEBOOK
40 #include "wx/notebook.h"
41#endif // wxUSE_NOTEBOOK
42
43#include "wx/msw/private.h"
44#include "wx/msw/uxtheme.h"
45
46// include <commctrl.h> "properly"
47#include "wx/msw/wrapcctl.h"
48
49// ----------------------------------------------------------------------------
50// wxWin macros
51// ----------------------------------------------------------------------------
52
53IMPLEMENT_ABSTRACT_CLASS(wxControl, wxWindow)
54
55// ============================================================================
56// wxControl implementation
57// ============================================================================
58
59// ----------------------------------------------------------------------------
60// wxControl ctor/dtor
61// ----------------------------------------------------------------------------
62
63wxControl::~wxControl()
64{
65 m_isBeingDeleted = true;
66}
67
68// ----------------------------------------------------------------------------
69// control window creation
70// ----------------------------------------------------------------------------
71
72bool wxControl::Create(wxWindow *parent,
73 wxWindowID id,
74 const wxPoint& pos,
75 const wxSize& size,
76 long style,
77 const wxValidator& wxVALIDATOR_PARAM(validator),
78 const wxString& name)
79{
80 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
81 return false;
82
83#if wxUSE_VALIDATORS
84 SetValidator(validator);
85#endif
86
87 return true;
88}
89
90bool wxControl::MSWCreateControl(const wxChar *classname,
91 const wxString& label,
92 const wxPoint& pos,
93 const wxSize& size)
94{
95 WXDWORD exstyle;
96 WXDWORD msStyle = MSWGetStyle(GetWindowStyle(), &exstyle);
97
98 return MSWCreateControl(classname, msStyle, pos, size, label, exstyle);
99}
100
101bool wxControl::MSWCreateControl(const wxChar *classname,
102 WXDWORD style,
103 const wxPoint& pos,
104 const wxSize& size,
105 const wxString& label,
106 WXDWORD exstyle)
107{
108 // if no extended style given, determine it ourselves
109 if ( exstyle == (WXDWORD)-1 )
110 {
111 exstyle = 0;
112 (void) MSWGetStyle(GetWindowStyle(), &exstyle);
113 }
114
115 // all controls should have this style
116 style |= WS_CHILD;
117
118 // create the control visible if it's currently shown for wxWidgets
119 if ( m_isShown )
120 {
121 style |= WS_VISIBLE;
122 }
123
124 // choose the position for the control: we have a problem with default size
125 // here as we can't calculate the best size before the control exists
126 // (DoGetBestSize() may need to use m_hWnd), so just choose the minimal
127 // possible but non 0 size because 0 window width/height result in problems
128 // elsewhere
129 int x = pos.x == wxDefaultCoord ? 0 : pos.x,
130 y = pos.y == wxDefaultCoord ? 0 : pos.y,
131 w = size.x == wxDefaultCoord ? 1 : size.x,
132 h = size.y == wxDefaultCoord ? 1 : size.y;
133
134 // ... and adjust it to account for a possible parent frames toolbar
135 AdjustForParentClientOrigin(x, y);
136
137 m_hWnd = (WXHWND)::CreateWindowEx
138 (
139 exstyle, // extended style
140 classname, // the kind of control to create
141 label, // the window name
142 style, // the window style
143 x, y, w, h, // the window position and size
144 GetHwndOf(GetParent()), // parent
145 (HMENU)GetId(), // child id
146 wxGetInstance(), // app instance
147 NULL // creation parameters
148 );
149
150 if ( !m_hWnd )
151 {
152#ifdef __WXDEBUG__
153 wxFAIL_MSG(wxString::Format
154 (
155 _T("CreateWindowEx(\"%s\", flags=%08x, ex=%08x) failed"),
156 classname, (unsigned int)style, (unsigned int)exstyle
157 ));
158#endif // __WXDEBUG__
159
160 return false;
161 }
162
163 // install wxWidgets window proc for this window
164 SubclassWin(m_hWnd);
165
166 // set up fonts and colours
167 InheritAttributes();
168 if (!m_hasFont)
169 SetFont(GetDefaultAttributes().font);
170
171 // set the size now if no initial size specified
172 SetInitialBestSize(size);
173
174 return true;
175}
176
177// ----------------------------------------------------------------------------
178// various accessors
179// ----------------------------------------------------------------------------
180
181wxBorder wxControl::GetDefaultBorder() const
182{
183 // we want to automatically give controls a sunken style (confusingly,
184 // it may not really mean sunken at all as we map it to WS_EX_CLIENTEDGE
185 // which is not sunken at all under Windows XP -- rather, just the default)
186#if defined(__POCKETPC__) || defined(__SMARTPHONE__)
187 return wxBORDER_SIMPLE;
188#else
189 return wxBORDER_SUNKEN;
190#endif
191}
192
193WXDWORD wxControl::MSWGetStyle(long style, WXDWORD *exstyle) const
194{
195 long msStyle = wxWindow::MSWGetStyle(style, exstyle);
196
197 if ( AcceptsFocus() )
198 {
199 msStyle |= WS_TABSTOP;
200 }
201
202 return msStyle;
203}
204
205wxSize wxControl::DoGetBestSize() const
206{
207 return wxSize(DEFAULT_ITEM_WIDTH, DEFAULT_ITEM_HEIGHT);
208}
209
210// This is a helper for all wxControls made with UPDOWN native control.
211// In wxMSW it was only wxSpinCtrl derived from wxSpinButton but in
212// WinCE of Smartphones this happens also for native wxTextCtrl,
213// wxChoice and others.
214wxSize wxControl::GetBestSpinnerSize(const bool is_vertical) const
215{
216 // take size according to layout
217 wxSize bestSize(
218#if defined(__SMARTPHONE__) && defined(__WXWINCE__)
219 0,GetCharHeight()
220#else
221 ::GetSystemMetrics(is_vertical ? SM_CXVSCROLL : SM_CXHSCROLL),
222 ::GetSystemMetrics(is_vertical ? SM_CYVSCROLL : SM_CYHSCROLL)
223#endif
224 );
225
226 // correct size as for undocumented MSW variants cases (WinCE and perhaps others)
227 if (bestSize.x==0)
228 bestSize.x = bestSize.y;
229 if (bestSize.y==0)
230 bestSize.y = bestSize.x;
231
232 // double size according to layout
233 if (is_vertical)
234 bestSize.y *= 2;
235 else
236 bestSize.x *= 2;
237
238 return bestSize;
239}
240
241/* static */ wxVisualAttributes
242wxControl::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
243{
244 wxVisualAttributes attrs;
245
246 // old school (i.e. not "common") controls use the standard dialog font
247 // by default
248 attrs.font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
249
250 // most, or at least many, of the controls use the same colours as the
251 // buttons -- others will have to override this (and possibly simply call
252 // GetCompositeControlsDefaultAttributes() from their versions)
253 attrs.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT);
254 attrs.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
255
256 return attrs;
257}
258
259// another version for the "composite", i.e. non simple controls
260/* static */ wxVisualAttributes
261wxControl::GetCompositeControlsDefaultAttributes(wxWindowVariant WXUNUSED(variant))
262{
263 wxVisualAttributes attrs;
264 attrs.font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
265 attrs.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
266 attrs.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
267
268 return attrs;
269}
270
271// ----------------------------------------------------------------------------
272// message handling
273// ----------------------------------------------------------------------------
274
275bool wxControl::ProcessCommand(wxCommandEvent& event)
276{
277 return GetEventHandler()->ProcessEvent(event);
278}
279
280bool wxControl::MSWOnNotify(int idCtrl,
281 WXLPARAM lParam,
282 WXLPARAM* result)
283{
284 wxEventType eventType wxDUMMY_INITIALIZE(wxEVT_NULL);
285
286 NMHDR *hdr = (NMHDR*) lParam;
287 switch ( hdr->code )
288 {
289 case NM_CLICK:
290 eventType = wxEVT_COMMAND_LEFT_CLICK;
291 break;
292
293 case NM_DBLCLK:
294 eventType = wxEVT_COMMAND_LEFT_DCLICK;
295 break;
296
297 case NM_RCLICK:
298 eventType = wxEVT_COMMAND_RIGHT_CLICK;
299 break;
300
301 case NM_RDBLCLK:
302 eventType = wxEVT_COMMAND_RIGHT_DCLICK;
303 break;
304
305 case NM_SETFOCUS:
306 eventType = wxEVT_COMMAND_SET_FOCUS;
307 break;
308
309 case NM_KILLFOCUS:
310 eventType = wxEVT_COMMAND_KILL_FOCUS;
311 break;
312
313 case NM_RETURN:
314 eventType = wxEVT_COMMAND_ENTER;
315 break;
316
317 default:
318 return wxWindow::MSWOnNotify(idCtrl, lParam, result);
319 }
320
321 wxCommandEvent event(wxEVT_NULL, m_windowId);
322 event.SetEventType(eventType);
323 event.SetEventObject(this);
324
325 return GetEventHandler()->ProcessEvent(event);
326}
327
328WXHBRUSH wxControl::DoMSWControlColor(WXHDC pDC, wxColour colBg, WXHWND hWnd)
329{
330 HDC hdc = (HDC)pDC;
331 if ( m_hasFgCol )
332 {
333 ::SetTextColor(hdc, wxColourToRGB(GetForegroundColour()));
334 }
335
336 WXHBRUSH hbr = 0;
337 if ( !colBg.Ok() )
338 {
339 hbr = MSWGetBgBrush(pDC, hWnd);
340
341 // if the control doesn't have any bg colour, foreground colour will be
342 // ignored as the return value would be 0 -- so forcefully give it a
343 // non default background brush in this case
344 if ( !hbr && m_hasFgCol )
345 colBg = GetBackgroundColour();
346 }
347
348 // use the background colour override if a valid colour is given
349 if ( colBg.Ok() )
350 {
351 ::SetBkColor(hdc, wxColourToRGB(colBg));
352
353 // draw children with the same colour as the parent
354 wxBrush *brush = wxTheBrushList->FindOrCreateBrush(colBg, wxSOLID);
355
356 hbr = (WXHBRUSH)brush->GetResourceHandle();
357
358 // if we use custom background, we should set foreground ourselves too
359 if ( !m_hasFgCol )
360 {
361 ::SetTextColor(hdc, ::GetSysColor(COLOR_WINDOWTEXT));
362 }
363 //else: already set above
364 }
365
366 return hbr;
367}
368
369WXHBRUSH wxControl::MSWControlColor(WXHDC pDC, WXHWND hWnd)
370{
371 wxColour colBg;
372
373 if ( HasTransparentBackground() )
374 ::SetBkMode((HDC)pDC, TRANSPARENT);
375 else // if the control is opaque it shouldn't use the parents background
376 colBg = GetBackgroundColour();
377
378 return DoMSWControlColor(pDC, colBg, hWnd);
379}
380
381WXHBRUSH wxControl::MSWControlColorDisabled(WXHDC pDC)
382{
383 return DoMSWControlColor(pDC,
384 wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE),
385 GetHWND());
386}
387
388// ---------------------------------------------------------------------------
389// global functions
390// ---------------------------------------------------------------------------
391
392// this is used in radiobox.cpp and slider95.cpp and should be removed as soon
393// as it is not needed there any more!
394//
395// Call this repeatedly for several wnds to find the overall size
396// of the widget.
397// Call it initially with wxDefaultCoord for all values in rect.
398// Keep calling for other widgets, and rect will be modified
399// to calculate largest bounding rectangle.
400void wxFindMaxSize(WXHWND wnd, RECT *rect)
401{
402 int left = rect->left;
403 int right = rect->right;
404 int top = rect->top;
405 int bottom = rect->bottom;
406
407 GetWindowRect((HWND) wnd, rect);
408
409 if (left < 0)
410 return;
411
412 if (left < rect->left)
413 rect->left = left;
414
415 if (right > rect->right)
416 rect->right = right;
417
418 if (top < rect->top)
419 rect->top = top;
420
421 if (bottom > rect->bottom)
422 rect->bottom = bottom;
423}
424
425#endif // wxUSE_CONTROLS