]> git.saurik.com Git - wxWidgets.git/blame - src/msw/renderer.cpp
explicitly mention that IsChecked() can't be used with wxCheckListBox
[wxWidgets.git] / src / msw / renderer.cpp
CommitLineData
9c7f49f5 1///////////////////////////////////////////////////////////////////////////////
90b903c2 2// Name: src/msw/renderer.cpp
38c4cb6a 3// Purpose: implementation of wxRendererNative for Windows
9c7f49f5
VZ
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 20.07.2003
7// RCS-ID: $Id$
8// Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
65571936 9// License: wxWindows licence
9c7f49f5
VZ
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#ifndef WX_PRECOMP
28 #include "wx/string.h"
85b657c7
VS
29 #include "wx/window.h"
30 #include "wx/dc.h"
9eddec69 31 #include "wx/settings.h"
9c7f49f5
VZ
32#endif //WX_PRECOMP
33
51c42fc5 34#include "wx/scopeguard.h"
3c2544bb 35#include "wx/splitter.h"
9c7f49f5 36#include "wx/renderer.h"
03f01e63 37#include "wx/msw/private.h"
4614c8e5 38#include "wx/msw/uxtheme.h"
8b97949e 39
7cf3223a
VZ
40// tmschema.h is in Win32 Platform SDK and might not be available with earlier
41// compilers
42#ifndef CP_DROPDOWNBUTTON
2209baae 43 #define BP_PUSHBUTTON 1
9f93b45e
VZ
44 #define BP_CHECKBOX 3
45 #define CBS_UNCHECKEDNORMAL 1
46 #define CBS_CHECKEDNORMAL (CBS_UNCHECKEDNORMAL + 4)
47 #define CBS_MIXEDNORMAL (CBS_CHECKEDNORMAL + 4)
48
2209baae
RR
49 #define PBS_NORMAL 1
50 #define PBS_HOT 2
51 #define PBS_PRESSED 3
52 #define PBS_DISABLED 4
53 #define PBS_DEFAULTED 5
54
7cf3223a
VZ
55 #define CP_DROPDOWNBUTTON 1
56
57 #define CBXS_NORMAL 1
58 #define CBXS_HOT 2
59 #define CBXS_PRESSED 3
60 #define CBXS_DISABLED 4
a9d9e2f2 61
9f93b45e
VZ
62 #define TVP_GLYPH 2
63
64 #define GLPS_CLOSED 1
a9d9e2f2
JS
65 #define GLPS_OPENED 2
66
67 #define HP_HEADERITEM 1
68
69 #define HIS_NORMAL 1
70 #define HIS_HOT 2
71 #define HIS_PRESSED 3
4b94ddc4
RD
72
73 #define TMT_HEIGHT 2417
74
75 #define HP_HEADERSORTARROW 4
76 #define HSAS_SORTEDUP 1
77 #define HSAS_SORTEDDOWN 2
7cf3223a
VZ
78#endif
79
d6f2a891
VZ
80#if defined(__WXWINCE__)
81 #ifndef DFCS_FLAT
82 #define DFCS_FLAT 0
83 #endif
84 #ifndef DFCS_MONO
85 #define DFCS_MONO 0
86 #endif
9f93b45e
VZ
87#endif
88
59ee63e9
VZ
89#ifndef DFCS_HOT
90 #define DFCS_HOT 0x1000
91#endif
92
9c7f49f5 93// ----------------------------------------------------------------------------
8b97949e 94// wxRendererMSW: wxRendererNative implementation for "old" Win32 systems
9c7f49f5
VZ
95// ----------------------------------------------------------------------------
96
38c4cb6a 97class WXDLLEXPORT wxRendererMSW : public wxDelegateRendererNative
9c7f49f5 98{
2eb10e2a
VZ
99public:
100 wxRendererMSW() { }
101
8b97949e
VZ
102 static wxRendererNative& Get();
103
7402677a
VZ
104 virtual void DrawComboBoxDropButton(wxWindow *win,
105 wxDC& dc,
106 const wxRect& rect,
107 int flags = 0);
108
59ee63e9
VZ
109 virtual void DrawCheckBox(wxWindow *win,
110 wxDC& dc,
111 const wxRect& rect,
112 int flags = 0);
113
2209baae
RR
114 virtual void DrawPushButton(wxWindow *win,
115 wxDC& dc,
116 const wxRect& rect,
117 int flags = 0);
118
51c42fc5
VZ
119 virtual void DrawFocusRect(wxWindow* win,
120 wxDC& dc,
121 const wxRect& rect,
122 int flags = 0);
123
124 virtual int GetHeaderButtonHeight(wxWindow *win);
125
2eb10e2a
VZ
126private:
127 DECLARE_NO_COPY_CLASS(wxRendererMSW)
9c7f49f5
VZ
128};
129
8b97949e
VZ
130// ----------------------------------------------------------------------------
131// wxRendererXP: wxRendererNative implementation for Windows XP and later
132// ----------------------------------------------------------------------------
133
7cf3223a
VZ
134#if wxUSE_UXTHEME
135
8b97949e
VZ
136class WXDLLEXPORT wxRendererXP : public wxDelegateRendererNative
137{
138public:
139 wxRendererXP() : wxDelegateRendererNative(wxRendererMSW::Get()) { }
140
141 static wxRendererNative& Get();
142
c97c9952 143 virtual int DrawHeaderButton(wxWindow *win,
4b94ddc4
RD
144 wxDC& dc,
145 const wxRect& rect,
146 int flags = 0,
80752b57 147 wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
4b94ddc4 148 wxHeaderButtonParams* params = NULL);
f4322df6 149
9f93b45e
VZ
150 virtual void DrawTreeItemButton(wxWindow *win,
151 wxDC& dc,
152 const wxRect& rect,
153 int flags = 0);
8b97949e
VZ
154 virtual void DrawSplitterBorder(wxWindow *win,
155 wxDC& dc,
c4e6c15e
VZ
156 const wxRect& rect,
157 int flags = 0);
8b97949e
VZ
158 virtual void DrawSplitterSash(wxWindow *win,
159 wxDC& dc,
160 const wxSize& size,
161 wxCoord position,
c4e6c15e
VZ
162 wxOrientation orient,
163 int flags = 0);
7cf3223a
VZ
164 virtual void DrawComboBoxDropButton(wxWindow *win,
165 wxDC& dc,
166 const wxRect& rect,
167 int flags = 0);
90b903c2
WS
168 virtual void DrawCheckBox(wxWindow *win,
169 wxDC& dc,
170 const wxRect& rect,
171 int flags = 0);
9f93b45e 172
2209baae
RR
173 virtual void DrawPushButton(wxWindow *win,
174 wxDC& dc,
175 const wxRect& rect,
176 int flags = 0);
177
a9fdf824
RR
178 virtual void DrawItemSelectionRect(wxWindow *win,
179 wxDC& dc,
180 const wxRect& rect,
181 int flags = 0 );
182
183
9f93b45e 184 virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win);
8b97949e
VZ
185private:
186 DECLARE_NO_COPY_CLASS(wxRendererXP)
187};
188
7cf3223a
VZ
189#endif // wxUSE_UXTHEME
190
9c7f49f5 191// ============================================================================
8b97949e 192// wxRendererNative and wxRendererMSW implementation
9c7f49f5
VZ
193// ============================================================================
194
195/* static */
f0244295 196wxRendererNative& wxRendererNative::GetDefault()
8b97949e 197{
7cf3223a 198#if wxUSE_UXTHEME
8b97949e 199 wxUxThemeEngine *themeEngine = wxUxThemeEngine::Get();
7cf3223a
VZ
200 if ( themeEngine && themeEngine->IsAppThemed() )
201 return wxRendererXP::Get();
202#endif // wxUSE_UXTHEME
203
204 return wxRendererMSW::Get();
8b97949e
VZ
205}
206
207/* static */
208wxRendererNative& wxRendererMSW::Get()
9c7f49f5
VZ
209{
210 static wxRendererMSW s_rendererMSW;
211
212 return s_rendererMSW;
213}
214
7402677a
VZ
215void
216wxRendererMSW::DrawComboBoxDropButton(wxWindow * WXUNUSED(win),
217 wxDC& dc,
218 const wxRect& rect,
219 int flags)
220{
221 RECT r;
46bd1978 222 wxCopyRectToRECT(rect, r);
7402677a
VZ
223
224 int style = DFCS_SCROLLCOMBOBOX;
225 if ( flags & wxCONTROL_DISABLED )
226 style |= DFCS_INACTIVE;
227 if ( flags & wxCONTROL_PRESSED )
7cf3223a 228 style |= DFCS_PUSHED | DFCS_FLAT;
7402677a
VZ
229
230 ::DrawFrameControl(GetHdcOf(dc), &r, DFC_SCROLL, style);
231}
232
59ee63e9
VZ
233void
234wxRendererMSW::DrawCheckBox(wxWindow * WXUNUSED(win),
235 wxDC& dc,
236 const wxRect& rect,
237 int flags)
238{
239 RECT r;
240 wxCopyRectToRECT(rect, r);
241
242 int style = DFCS_BUTTONCHECK;
243 if ( flags & wxCONTROL_CHECKED )
244 style |= DFCS_CHECKED;
245 if ( flags & wxCONTROL_DISABLED )
246 style |= DFCS_INACTIVE;
8a461249
VZ
247 if ( flags & wxCONTROL_FLAT )
248 style |= DFCS_MONO;
59ee63e9
VZ
249 if ( flags & wxCONTROL_PRESSED )
250 style |= DFCS_PUSHED;
251 if ( flags & wxCONTROL_CURRENT )
252 style |= DFCS_HOT;
253
254 ::DrawFrameControl(GetHdcOf(dc), &r, DFC_BUTTON, style);
255}
256
2209baae
RR
257void
258wxRendererMSW::DrawPushButton(wxWindow * WXUNUSED(win),
259 wxDC& dc,
f2ea4255 260 const wxRect& rectOrig,
2209baae
RR
261 int flags)
262{
f2ea4255 263 wxRect rect(rectOrig);
2209baae
RR
264
265 int style = DFCS_BUTTONPUSH;
266 if ( flags & wxCONTROL_DISABLED )
267 style |= DFCS_INACTIVE;
268 if ( flags & wxCONTROL_PRESSED )
269 style |= DFCS_PUSHED | DFCS_FLAT;
f2ea4255
VZ
270 if ( flags & wxCONTROL_ISDEFAULT )
271 {
272 // DrawFrameControl() doesn't seem to support default buttons so we
273 // have to draw the border ourselves
274 wxDCPenChanger pen(dc, *wxBLACK_PEN);
275 wxDCBrushChanger brush(dc, *wxTRANSPARENT_BRUSH);
276 dc.DrawRectangle(rect);
844b9f5f 277 rect.Deflate(1);
f2ea4255
VZ
278 }
279
280 RECT rc;
281 wxCopyRectToRECT(rect, rc);
282
283 ::DrawFrameControl(GetHdcOf(dc), &rc, DFC_BUTTON, style);
2209baae
RR
284}
285
51c42fc5
VZ
286void wxRendererMSW::DrawFocusRect(wxWindow * WXUNUSED(win),
287 wxDC& dc,
288 const wxRect& rect,
289 int WXUNUSED(flags))
6d789987
JS
290{
291 RECT rc;
292 wxCopyRectToRECT(rect, rc);
293
294 ::DrawFocusRect(GetHdcOf(dc), &rc);
295}
296
51c42fc5
VZ
297int wxRendererMSW::GetHeaderButtonHeight(wxWindow * WXUNUSED(win))
298{
299 // some "reasonable" value returned in case of error, it doesn't really
300 // correspond to anything but it's better than returning 0
301 static const int DEFAULT_HEIGHT = 20;
302
303
304 // create a temporary header window just to get its geometry
a268f4b7 305 HWND hwndHeader = ::CreateWindow(WC_HEADER, NULL, 0,
51c42fc5
VZ
306 0, 0, 0, 0, NULL, NULL, NULL, NULL);
307 if ( !hwndHeader )
308 return DEFAULT_HEIGHT;
309
310 wxON_BLOCK_EXIT1( ::DestroyWindow, hwndHeader );
311
312 // initialize the struct filled with the values by Header_Layout()
313 RECT parentRect = { 0, 0, 100, 100 };
11fa6e63 314 WINDOWPOS wp = { 0, 0, 0, 0, 0, 0, 0 };
51c42fc5
VZ
315 HDLAYOUT hdl = { &parentRect, &wp };
316
317 return Header_Layout(hwndHeader, &hdl) ? wp.cy : DEFAULT_HEIGHT;
318}
319
8b97949e
VZ
320// ============================================================================
321// wxRendererXP implementation
322// ============================================================================
323
7cf3223a
VZ
324#if wxUSE_UXTHEME
325
8b97949e
VZ
326/* static */
327wxRendererNative& wxRendererXP::Get()
328{
329 static wxRendererXP s_rendererXP;
330
331 return s_rendererXP;
332}
333
7cf3223a
VZ
334// NOTE: There is no guarantee that the button drawn fills the entire rect (XP
335// default theme, for example), so the caller should have cleared button's
336// background before this call. This is quite likely a wxMSW-specific thing.
337void
338wxRendererXP::DrawComboBoxDropButton(wxWindow * win,
339 wxDC& dc,
340 const wxRect& rect,
341 int flags)
342{
343 wxUxThemeHandle hTheme(win, L"COMBOBOX");
9f93b45e 344 if ( !hTheme )
7cf3223a 345 {
9f93b45e
VZ
346 m_rendererNative.DrawComboBoxDropButton(win, dc, rect, flags);
347 return;
348 }
349
350 RECT r;
351 wxCopyRectToRECT(rect, r);
7cf3223a 352
9f93b45e
VZ
353 int state;
354 if ( flags & wxCONTROL_PRESSED )
355 state = CBXS_PRESSED;
356 else if ( flags & wxCONTROL_CURRENT )
357 state = CBXS_HOT;
358 else if ( flags & wxCONTROL_DISABLED )
359 state = CBXS_DISABLED;
360 else
361 state = CBXS_NORMAL;
362
363 wxUxThemeEngine::Get()->DrawThemeBackground
364 (
365 hTheme,
366 GetHdcOf(dc),
367 CP_DROPDOWNBUTTON,
368 state,
369 &r,
370 NULL
371 );
372
373}
374
c97c9952 375int
9f93b45e
VZ
376wxRendererXP::DrawHeaderButton(wxWindow *win,
377 wxDC& dc,
378 const wxRect& rect,
4b94ddc4 379 int flags,
80752b57 380 wxHeaderSortIconType sortArrow,
4b94ddc4 381 wxHeaderButtonParams* params)
9f93b45e
VZ
382{
383 wxUxThemeHandle hTheme(win, L"HEADER");
384 if ( !hTheme )
385 {
c97c9952 386 return m_rendererNative.DrawHeaderButton(win, dc, rect, flags, sortArrow, params);
7cf3223a 387 }
9f93b45e
VZ
388
389 RECT r;
390 wxCopyRectToRECT(rect, r);
391
392 int state;
393 if ( flags & wxCONTROL_PRESSED )
394 state = HIS_PRESSED;
395 else if ( flags & wxCONTROL_CURRENT )
396 state = HIS_HOT;
397 else
398 state = HIS_NORMAL;
399 wxUxThemeEngine::Get()->DrawThemeBackground
400 (
401 hTheme,
402 GetHdcOf(dc),
403 HP_HEADERITEM,
404 state,
405 &r,
406 NULL
407 );
4b94ddc4
RD
408
409 // NOTE: Using the theme to draw HP_HEADERSORTARROW doesn't do anything.
410 // Why? If this can be fixed then draw the sort arrows using the theme
411 // and then clear those flags before calling DrawHeaderButtonContents.
f4322df6 412
4b94ddc4 413 // Add any extras that are specified in flags and params
c97c9952 414 return DrawHeaderButtonContents(win, dc, rect, flags, sortArrow, params);
9f93b45e
VZ
415}
416
4b94ddc4 417
9f93b45e
VZ
418void
419wxRendererXP::DrawTreeItemButton(wxWindow *win,
420 wxDC& dc,
421 const wxRect& rect,
422 int flags)
423{
424 wxUxThemeHandle hTheme(win, L"TREEVIEW");
425 if ( !hTheme )
426 {
427 m_rendererNative.DrawTreeItemButton(win, dc, rect, flags);
428 return;
429 }
430
431 RECT r;
432 wxCopyRectToRECT(rect, r);
433
434 int state = flags & wxCONTROL_EXPANDED ? GLPS_OPENED : GLPS_CLOSED;
435 wxUxThemeEngine::Get()->DrawThemeBackground
436 (
437 hTheme,
438 GetHdcOf(dc),
439 TVP_GLYPH,
440 state,
441 &r,
442 NULL
443 );
444}
445
446void
90b903c2
WS
447wxRendererXP::DrawCheckBox(wxWindow *win,
448 wxDC& dc,
449 const wxRect& rect,
450 int flags)
9f93b45e
VZ
451{
452 wxUxThemeHandle hTheme(win, L"BUTTON");
453 if ( !hTheme )
454 {
90b903c2 455 m_rendererNative.DrawCheckBox(win, dc, rect, flags);
9f93b45e
VZ
456 return;
457 }
458
459 RECT r;
460 wxCopyRectToRECT(rect, r);
461
462 int state;
463 if ( flags & wxCONTROL_CHECKED )
464 state = CBS_CHECKEDNORMAL;
465 else if ( flags & wxCONTROL_UNDETERMINED )
466 state = CBS_MIXEDNORMAL;
467 else
468 state = CBS_UNCHECKEDNORMAL;
469
59ee63e9
VZ
470 // CBS_XXX is followed by CBX_XXXHOT, then CBS_XXXPRESSED and DISABLED
471 enum
472 {
473 CBS_HOT_OFFSET = 1,
474 CBS_PRESSED_OFFSET = 2,
475 CBS_DISABLED_OFFSET = 3
476 };
477
478 if ( flags & wxCONTROL_DISABLED )
479 state += CBS_DISABLED_OFFSET;
9f93b45e 480 else if ( flags & wxCONTROL_PRESSED )
59ee63e9
VZ
481 state += CBS_PRESSED_OFFSET;
482 else if ( flags & wxCONTROL_CURRENT )
483 state += CBS_HOT_OFFSET;
9f93b45e
VZ
484
485 wxUxThemeEngine::Get()->DrawThemeBackground
486 (
487 hTheme,
488 GetHdcOf(dc),
489 BP_CHECKBOX,
490 state,
491 &r,
492 NULL
493 );
7cf3223a
VZ
494}
495
2209baae
RR
496void
497wxRendererXP::DrawPushButton(wxWindow * win,
498 wxDC& dc,
499 const wxRect& rect,
500 int flags)
501{
502 wxUxThemeHandle hTheme(win, L"BUTTON");
503 if ( !hTheme )
504 {
505 m_rendererNative.DrawPushButton(win, dc, rect, flags);
506 return;
507 }
508
509 RECT r;
510 wxCopyRectToRECT(rect, r);
511
512 int state;
513 if ( flags & wxCONTROL_PRESSED )
514 state = PBS_PRESSED;
515 else if ( flags & wxCONTROL_CURRENT )
516 state = PBS_HOT;
517 else if ( flags & wxCONTROL_DISABLED )
518 state = PBS_DISABLED;
519 else if ( flags & wxCONTROL_ISDEFAULT )
520 state = PBS_DEFAULTED;
521 else
522 state = PBS_NORMAL;
523
524 wxUxThemeEngine::Get()->DrawThemeBackground
525 (
526 hTheme,
527 GetHdcOf(dc),
528 BP_PUSHBUTTON,
529 state,
530 &r,
531 NULL
532 );
533
534}
535
a9fdf824
RR
536void
537wxRendererXP::DrawItemSelectionRect(wxWindow * WXUNUSED(win),
538 wxDC& dc,
539 const wxRect& rect,
540 int flags)
541{
542 wxBrush brush;
543 if ( flags & wxCONTROL_SELECTED )
544 {
545 if ( flags & wxCONTROL_FOCUSED )
546 {
547 brush = wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT));
548 }
549 else // !focused
550 {
551 brush = wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW));
552 }
553 }
554 else // !selected
555 {
556 brush = *wxTRANSPARENT_BRUSH;
557 }
558
559 dc.SetBrush(brush);
560
561 // unlike for wxRendererGeneric, on windows we _never_ want to draw
562 // the outline of the rectangle:
563 dc.SetPen(*wxTRANSPARENT_PEN);
564
565 dc.DrawRectangle( rect );
566}
567
568
569
8b97949e
VZ
570// ----------------------------------------------------------------------------
571// splitter drawing
572// ----------------------------------------------------------------------------
573
574// the width of the sash: this is the same as used by Explorer...
575static const wxCoord SASH_WIDTH = 4;
576
c4e6c15e 577wxSplitterRenderParams
3c2544bb 578wxRendererXP::GetSplitterParams(const wxWindow * win)
8b97949e 579{
9f93b45e 580 if ( win->HasFlag(wxSP_NO_XP_THEME) )
3c2544bb
JS
581 return m_rendererNative.GetSplitterParams(win);
582 else
583 return wxSplitterRenderParams(SASH_WIDTH, 0, false);
8b97949e
VZ
584}
585
586void
3c2544bb
JS
587wxRendererXP::DrawSplitterBorder(wxWindow * win,
588 wxDC& dc,
589 const wxRect& rect,
590 int flags)
8b97949e 591{
9f93b45e 592 if ( win->HasFlag(wxSP_NO_XP_THEME) )
3c2544bb
JS
593 {
594 m_rendererNative.DrawSplitterBorder(win, dc, rect, flags);
595 }
8b97949e
VZ
596}
597
598void
599wxRendererXP::DrawSplitterSash(wxWindow *win,
600 wxDC& dc,
601 const wxSize& size,
602 wxCoord position,
c4e6c15e 603 wxOrientation orient,
3c2544bb 604 int flags)
8b97949e 605{
6421119d 606 if ( !win->HasFlag(wxSP_NO_XP_THEME) )
8b97949e 607 {
fe404d1a
JS
608 dc.SetPen(*wxTRANSPARENT_PEN);
609 dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)));
610 if ( orient == wxVERTICAL )
8b97949e 611 {
fe404d1a 612 dc.DrawRectangle(position, 0, SASH_WIDTH, size.y);
8b97949e 613 }
fe404d1a
JS
614 else // wxHORIZONTAL
615 {
616 dc.DrawRectangle(0, position, size.x, SASH_WIDTH);
617 }
618
619 return;
8b97949e 620 }
6421119d
VZ
621
622 m_rendererNative.DrawSplitterSash(win, dc, size, position, orient, flags);
8b97949e
VZ
623}
624
7cf3223a 625#endif // wxUSE_UXTHEME