1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/renderer.cpp
3 // Purpose: implementation of wxRendererNative for Windows
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 20.07.2003
7 // RCS-ID: $Id: renderer.cpp 53524 2008-05-10 00:05:20Z RD $
8 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // License: 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 #ifndef WX_PRECOMP
28 #include "wx/string.h"
29 #include "wx/window.h"
30 #include "wx/dc.h"
31 #include "wx/settings.h"
32 #endif //WX_PRECOMP
33
34 #include "wx/splitter.h"
35 #include "wx/renderer.h"
36 #include "wx/msw/private.h"
37 #include "wx/msw/uxtheme.h"
38
39 #if wxUSE_GRAPHICS_CONTEXT
40 // TODO remove this dependency (gdiplus needs the macros)
41 #ifndef max
42 #define max(a,b) (((a) > (b)) ? (a) : (b))
43 #endif
44
45 #ifndef min
46 #define min(a,b) (((a) < (b)) ? (a) : (b))
47 #endif
48
49 #include "gdiplus.h"
50 using namespace Gdiplus;
51 #endif
52
53 // tmschema.h is in Win32 Platform SDK and might not be available with earlier
54 // compilers
55 #ifndef CP_DROPDOWNBUTTON
56 #define BP_PUSHBUTTON 1
57 #define BP_RADIOBUTTON 2
58 #define BP_CHECKBOX 3
59 #define RBS_UNCHECKEDNORMAL 1
60 #define RBS_CHECKEDNORMAL (RBS_UNCHECKEDNORMAL + 4)
61 #define RBS_MIXEDNORMAL (RBS_CHECKEDNORMAL + 4)
62 #define CBS_UNCHECKEDNORMAL 1
63 #define CBS_CHECKEDNORMAL (CBS_UNCHECKEDNORMAL + 4)
64 #define CBS_MIXEDNORMAL (CBS_CHECKEDNORMAL + 4)
65
66 #define PBS_NORMAL 1
67 #define PBS_HOT 2
68 #define PBS_PRESSED 3
69 #define PBS_DISABLED 4
70 #define PBS_DEFAULTED 5
71
72 #define CP_DROPDOWNBUTTON 1
73
74 #define CBXS_NORMAL 1
75 #define CBXS_HOT 2
76 #define CBXS_PRESSED 3
77 #define CBXS_DISABLED 4
78
79 #define TVP_GLYPH 2
80
81 #define GLPS_CLOSED 1
82 #define GLPS_OPENED 2
83
84 #define HP_HEADERITEM 1
85
86 #define HIS_NORMAL 1
87 #define HIS_HOT 2
88 #define HIS_PRESSED 3
89
90 #define TMT_HEIGHT 2417
91
92 #define HP_HEADERSORTARROW 4
93 #define HSAS_SORTEDUP 1
94 #define HSAS_SORTEDDOWN 2
95
96 #define EP_EDITTEXT 1
97 #define ETS_NORMAL 1
98 #define ETS_HOT 2
99 #define ETS_SELECTED 3
100 #define ETS_DISABLED 4
101 #define ETS_FOCUSED 5
102 #define ETS_READONLY 6
103 #define ETS_ASSIST 7
104 #define TMT_FILLCOLOR 3802
105 #define TMT_TEXTCOLOR 3803
106 #define TMT_BORDERCOLOR 3801
107 #define TMT_EDGEFILLCOLOR 3808
108 #endif
109
110 #if defined(__WXWINCE__) && !defined(DFCS_FLAT)
111 #define DFCS_FLAT 0
112 #endif
113
114
115 // ----------------------------------------------------------------------------
116 // If the DC is a wxGCDC then pull out the HDC from the GraphicsContext when
117 // it is needed, and handle the Release when done.
118
119 class GraphicsHDC
120 {
121 public:
GraphicsHDC(wxDC * dc)122 GraphicsHDC(wxDC* dc)
123 {
124 #if wxUSE_GRAPHICS_CONTEXT
125 m_graphics = NULL;
126 wxGCDC* gcdc = wxDynamicCast(dc, wxGCDC);
127 if (gcdc) {
128 m_graphics = (Graphics*)gcdc->GetGraphicsContext()->GetNativeContext();
129 m_hdc = m_graphics->GetHDC();
130 }
131 else
132 #endif
133 m_hdc = GetHdcOf(*dc);
134 }
135
~GraphicsHDC()136 ~GraphicsHDC()
137 {
138 #if wxUSE_GRAPHICS_CONTEXT
139 if (m_graphics)
140 m_graphics->ReleaseHDC(m_hdc);
141 #endif
142 }
143
operator HDC() const144 operator HDC() const { return m_hdc; }
145
146 private:
147 HDC m_hdc;
148 #if wxUSE_GRAPHICS_CONTEXT
149 Graphics* m_graphics;
150 #endif
151 };
152
153 // ----------------------------------------------------------------------------
154 // wxRendererMSW: wxRendererNative implementation for "old" Win32 systems
155 // ----------------------------------------------------------------------------
156
157 class WXDLLEXPORT wxRendererMSW : public wxDelegateRendererNative
158 {
159 public:
wxRendererMSW()160 wxRendererMSW() { }
161
162 static wxRendererNative& Get();
163
164 virtual void DrawComboBoxDropButton(wxWindow *win,
165 wxDC& dc,
166 const wxRect& rect,
167 int flags = 0);
168
169 virtual void DrawPushButton(wxWindow *win,
170 wxDC& dc,
171 const wxRect& rect,
172 int flags = 0);
173
174 private:
175 DECLARE_NO_COPY_CLASS(wxRendererMSW)
176 };
177
178 // ----------------------------------------------------------------------------
179 // wxRendererXP: wxRendererNative implementation for Windows XP and later
180 // ----------------------------------------------------------------------------
181
182 #if wxUSE_UXTHEME
183
184 class WXDLLEXPORT wxRendererXP : public wxDelegateRendererNative
185 {
186 public:
wxRendererXP()187 wxRendererXP() : wxDelegateRendererNative(wxRendererMSW::Get()) { }
188
189 static wxRendererNative& Get();
190
191 virtual int DrawHeaderButton(wxWindow *win,
192 wxDC& dc,
193 const wxRect& rect,
194 int flags = 0,
195 wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
196 wxHeaderButtonParams* params = NULL);
197 virtual int GetHeaderButtonHeight(wxWindow *win);
198
199 virtual void DrawTreeItemButton(wxWindow *win,
200 wxDC& dc,
201 const wxRect& rect,
202 int flags = 0);
203 virtual void DrawSplitterBorder(wxWindow *win,
204 wxDC& dc,
205 const wxRect& rect,
206 int flags = 0);
207 virtual void DrawSplitterSash(wxWindow *win,
208 wxDC& dc,
209 const wxSize& size,
210 wxCoord position,
211 wxOrientation orient,
212 int flags = 0);
213 virtual void DrawComboBoxDropButton(wxWindow *win,
214 wxDC& dc,
215 const wxRect& rect,
216 int flags = 0);
217 virtual void DrawCheckBox(wxWindow *win,
218 wxDC& dc,
219 const wxRect& rect,
220 int flags = 0);
221
222 virtual void DrawPushButton(wxWindow *win,
223 wxDC& dc,
224 const wxRect& rect,
225 int flags = 0);
226
227 virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win);
228 private:
229 DECLARE_NO_COPY_CLASS(wxRendererXP)
230 };
231
232 #endif // wxUSE_UXTHEME
233
234 // ============================================================================
235 // wxRendererNative and wxRendererMSW implementation
236 // ============================================================================
237
238 /* static */
GetDefault()239 wxRendererNative& wxRendererNative::GetDefault()
240 {
241 #if wxUSE_UXTHEME
242 wxUxThemeEngine *themeEngine = wxUxThemeEngine::Get();
243 if ( themeEngine && themeEngine->IsAppThemed() )
244 return wxRendererXP::Get();
245 #endif // wxUSE_UXTHEME
246
247 return wxRendererMSW::Get();
248 }
249
250 /* static */
Get()251 wxRendererNative& wxRendererMSW::Get()
252 {
253 static wxRendererMSW s_rendererMSW;
254
255 return s_rendererMSW;
256 }
257
258 void
DrawComboBoxDropButton(wxWindow * WXUNUSED (win),wxDC & dc,const wxRect & rect,int flags)259 wxRendererMSW::DrawComboBoxDropButton(wxWindow * WXUNUSED(win),
260 wxDC& dc,
261 const wxRect& rect,
262 int flags)
263 {
264 RECT r;
265 r.left = rect.GetLeft();
266 r.top = rect.GetTop();
267 r.bottom = rect.y + rect.height;
268 r.right = rect.x + rect.width;
269
270 int style = DFCS_SCROLLCOMBOBOX;
271 if ( flags & wxCONTROL_DISABLED )
272 style |= DFCS_INACTIVE;
273 if ( flags & wxCONTROL_PRESSED )
274 style |= DFCS_PUSHED | DFCS_FLAT;
275
276 ::DrawFrameControl(GraphicsHDC(&dc), &r, DFC_SCROLL, style);
277 }
278
279 void
DrawPushButton(wxWindow * WXUNUSED (win),wxDC & dc,const wxRect & rectOrig,int flags)280 wxRendererMSW::DrawPushButton(wxWindow * WXUNUSED(win),
281 wxDC& dc,
282 const wxRect& rectOrig,
283 int flags)
284 {
285 wxRect rect(rectOrig);
286
287 int style = DFCS_BUTTONPUSH;
288 if ( flags & wxCONTROL_DISABLED )
289 style |= DFCS_INACTIVE;
290 if ( flags & wxCONTROL_PRESSED )
291 style |= DFCS_PUSHED | DFCS_FLAT;
292 if ( flags & wxCONTROL_ISDEFAULT )
293 {
294 // DrawFrameControl() doesn't seem to support default buttons so we
295 // have to draw the border ourselves
296 wxDCPenChanger pen(dc, *wxBLACK_PEN);
297 wxDCBrushChanger brush(dc, *wxTRANSPARENT_BRUSH);
298 dc.DrawRectangle(rect);
299 rect.Deflate(1);
300 }
301
302 RECT rc;
303 wxCopyRectToRECT(rect, rc);
304
305 ::DrawFrameControl(GraphicsHDC(&dc), &rc, DFC_BUTTON, style);
306 }
307
308 // ============================================================================
309 // wxRendererXP implementation
310 // ============================================================================
311
312 #if wxUSE_UXTHEME
313
314 /* static */
Get()315 wxRendererNative& wxRendererXP::Get()
316 {
317 static wxRendererXP s_rendererXP;
318
319 return s_rendererXP;
320 }
321
322 // NOTE: There is no guarantee that the button drawn fills the entire rect (XP
323 // default theme, for example), so the caller should have cleared button's
324 // background before this call. This is quite likely a wxMSW-specific thing.
325 void
DrawComboBoxDropButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)326 wxRendererXP::DrawComboBoxDropButton(wxWindow * win,
327 wxDC& dc,
328 const wxRect& rect,
329 int flags)
330 {
331 wxUxThemeHandle hTheme(win, L"COMBOBOX");
332 if ( !hTheme )
333 {
334 m_rendererNative.DrawComboBoxDropButton(win, dc, rect, flags);
335 return;
336 }
337
338 RECT r;
339 wxCopyRectToRECT(rect, r);
340
341 int state;
342 if ( flags & wxCONTROL_PRESSED )
343 state = CBXS_PRESSED;
344 else if ( flags & wxCONTROL_CURRENT )
345 state = CBXS_HOT;
346 else if ( flags & wxCONTROL_DISABLED )
347 state = CBXS_DISABLED;
348 else
349 state = CBXS_NORMAL;
350
351 wxUxThemeEngine::Get()->DrawThemeBackground
352 (
353 hTheme,
354 GraphicsHDC(&dc),
355 CP_DROPDOWNBUTTON,
356 state,
357 &r,
358 NULL
359 );
360
361 }
362
363 int
DrawHeaderButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags,wxHeaderSortIconType sortArrow,wxHeaderButtonParams * params)364 wxRendererXP::DrawHeaderButton(wxWindow *win,
365 wxDC& dc,
366 const wxRect& rect,
367 int flags,
368 wxHeaderSortIconType sortArrow,
369 wxHeaderButtonParams* params)
370 {
371 wxUxThemeHandle hTheme(win, L"HEADER");
372 if ( !hTheme )
373 {
374 return m_rendererNative.DrawHeaderButton(win, dc, rect, flags, sortArrow, params);
375 }
376
377 RECT r;
378 wxCopyRectToRECT(rect, r);
379
380 int state;
381 if ( flags & wxCONTROL_PRESSED )
382 state = HIS_PRESSED;
383 else if ( flags & wxCONTROL_CURRENT )
384 state = HIS_HOT;
385 else
386 state = HIS_NORMAL;
387 wxUxThemeEngine::Get()->DrawThemeBackground
388 (
389 hTheme,
390 GraphicsHDC(&dc),
391 HP_HEADERITEM,
392 state,
393 &r,
394 NULL
395 );
396
397 // NOTE: Using the theme to draw HP_HEADERSORTARROW doesn't do anything.
398 // Why? If this can be fixed then draw the sort arrows using the theme
399 // and then clear those flags before calling DrawHeaderButtonContents.
400
401 // Add any extras that are specified in flags and params
402 return DrawHeaderButtonContents(win, dc, rect, flags, sortArrow, params);
403 }
404
405
406 int
GetHeaderButtonHeight(wxWindow * win)407 wxRendererXP::GetHeaderButtonHeight(wxWindow *win)
408 {
409 wxUxThemeHandle hTheme(win, L"HEADER");
410 if ( !hTheme )
411 {
412 return m_rendererNative.GetHeaderButtonHeight(win);
413 }
414
415 HRESULT hr;
416 int value = -1;
417
418 hr = wxUxThemeEngine::Get()->GetThemeMetric( hTheme,
419 NULL,
420 HP_HEADERITEM,
421 HIS_NORMAL,
422 TMT_HEIGHT,
423 &value );
424 if ( hr == S_OK )
425 return value;
426 else
427 return 20;
428 }
429
430
431 void
DrawTreeItemButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)432 wxRendererXP::DrawTreeItemButton(wxWindow *win,
433 wxDC& dc,
434 const wxRect& rect,
435 int flags)
436 {
437 wxUxThemeHandle hTheme(win, L"TREEVIEW");
438 if ( !hTheme )
439 {
440 m_rendererNative.DrawTreeItemButton(win, dc, rect, flags);
441 return;
442 }
443
444 RECT r;
445 wxCopyRectToRECT(rect, r);
446
447 int state = flags & wxCONTROL_EXPANDED ? GLPS_OPENED : GLPS_CLOSED;
448 wxUxThemeEngine::Get()->DrawThemeBackground
449 (
450 hTheme,
451 GraphicsHDC(&dc),
452 TVP_GLYPH,
453 state,
454 &r,
455 NULL
456 );
457 }
458
459 void
DrawCheckBox(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)460 wxRendererXP::DrawCheckBox(wxWindow *win,
461 wxDC& dc,
462 const wxRect& rect,
463 int flags)
464 {
465 wxUxThemeHandle hTheme(win, L"BUTTON");
466 if ( !hTheme )
467 {
468 m_rendererNative.DrawCheckBox(win, dc, rect, flags);
469 return;
470 }
471
472 RECT r;
473 wxCopyRectToRECT(rect, r);
474
475 int state;
476 if ( flags & wxCONTROL_CHECKED )
477 state = CBS_CHECKEDNORMAL;
478 else if ( flags & wxCONTROL_UNDETERMINED )
479 state = CBS_MIXEDNORMAL;
480 else
481 state = CBS_UNCHECKEDNORMAL;
482
483 // CBS_XXX is followed by CBX_XXXGOT, then CBS_XXXPRESSED and DISABLED
484 if ( flags & wxCONTROL_CURRENT )
485 state += 1;
486 else if ( flags & wxCONTROL_PRESSED )
487 state += 2;
488 else if ( flags & wxCONTROL_DISABLED )
489 state += 3;
490
491 wxUxThemeEngine::Get()->DrawThemeBackground
492 (
493 hTheme,
494 GraphicsHDC(&dc),
495 BP_CHECKBOX,
496 state,
497 &r,
498 NULL
499 );
500 }
501
502
503
504 void
DrawPushButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)505 wxRendererXP::DrawPushButton(wxWindow * win,
506 wxDC& dc,
507 const wxRect& rect,
508 int flags)
509 {
510 wxUxThemeHandle hTheme(win, L"BUTTON");
511 if ( !hTheme )
512 {
513 m_rendererNative.DrawPushButton(win, dc, rect, flags);
514 return;
515 }
516
517 RECT r;
518 wxCopyRectToRECT(rect, r);
519
520 int state;
521 if ( flags & wxCONTROL_PRESSED )
522 state = PBS_PRESSED;
523 else if ( flags & wxCONTROL_CURRENT )
524 state = PBS_HOT;
525 else if ( flags & wxCONTROL_DISABLED )
526 state = PBS_DISABLED;
527 else if ( flags & wxCONTROL_ISDEFAULT )
528 state = PBS_DEFAULTED;
529 else
530 state = PBS_NORMAL;
531
532 wxUxThemeEngine::Get()->DrawThemeBackground
533 (
534 hTheme,
535 GraphicsHDC(&dc),
536 BP_PUSHBUTTON,
537 state,
538 &r,
539 NULL
540 );
541 }
542
543 // ----------------------------------------------------------------------------
544 // splitter drawing
545 // ----------------------------------------------------------------------------
546
547 // the width of the sash: this is the same as used by Explorer...
548 static const wxCoord SASH_WIDTH = 4;
549
550 wxSplitterRenderParams
GetSplitterParams(const wxWindow * win)551 wxRendererXP::GetSplitterParams(const wxWindow * win)
552 {
553 if ( win->HasFlag(wxSP_NO_XP_THEME) )
554 return m_rendererNative.GetSplitterParams(win);
555 else
556 return wxSplitterRenderParams(SASH_WIDTH, 0, false);
557 }
558
559 void
DrawSplitterBorder(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)560 wxRendererXP::DrawSplitterBorder(wxWindow * win,
561 wxDC& dc,
562 const wxRect& rect,
563 int flags)
564 {
565 if ( win->HasFlag(wxSP_NO_XP_THEME) )
566 {
567 m_rendererNative.DrawSplitterBorder(win, dc, rect, flags);
568 }
569 }
570
571 void
DrawSplitterSash(wxWindow * win,wxDC & dc,const wxSize & size,wxCoord position,wxOrientation orient,int flags)572 wxRendererXP::DrawSplitterSash(wxWindow *win,
573 wxDC& dc,
574 const wxSize& size,
575 wxCoord position,
576 wxOrientation orient,
577 int flags)
578 {
579 if ( !win->HasFlag(wxSP_NO_XP_THEME) )
580 {
581 dc.SetPen(*wxTRANSPARENT_PEN);
582 dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)));
583 if ( orient == wxVERTICAL )
584 {
585 dc.DrawRectangle(position, 0, SASH_WIDTH, size.y);
586 }
587 else // wxHORIZONTAL
588 {
589 dc.DrawRectangle(0, position, size.x, SASH_WIDTH);
590 }
591
592 return;
593 }
594
595 m_rendererNative.DrawSplitterSash(win, dc, size, position, orient, flags);
596 }
597
598 // ----------------------------------------------------------------------------
599 // Other renderer functions to be merged in to wxRenderer class in 2.9, but
600 // they are standalone functions here to protect the ABI.
601 // ----------------------------------------------------------------------------
602
603 // Uses the theme to draw the border and fill for something like a wxTextCtrl
wxRenderer_DrawTextCtrl(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)604 void wxRenderer_DrawTextCtrl(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
605 {
606 wxColour fill;
607 wxColour bdr;
608 COLORREF cref;
609
610 #if wxUSE_UXTHEME
611 wxUxThemeHandle hTheme(win, L"EDIT");
612 if (hTheme)
613 {
614 wxUxThemeEngine::Get()->GetThemeColor(hTheme, EP_EDITTEXT,
615 ETS_NORMAL, TMT_FILLCOLOR, &cref);
616 fill = wxRGBToColour(cref);
617
618 int etsState;
619 if ( flags & wxCONTROL_DISABLED )
620 etsState = ETS_DISABLED;
621 else
622 etsState = ETS_NORMAL;
623
624 wxUxThemeEngine::Get()->GetThemeColor(hTheme, EP_EDITTEXT,
625 etsState, TMT_BORDERCOLOR, &cref);
626 bdr = wxRGBToColour(cref);
627 }
628 else
629 #endif
630 {
631 fill = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
632 bdr = *wxBLACK;
633 }
634
635 dc.SetPen( bdr );
636 dc.SetBrush( fill );
637 dc.DrawRectangle(rect);
638 }
639
640
641 // Draw the equivallent of a wxComboBox
wxRenderer_DrawComboBox(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)642 void wxRenderer_DrawComboBox(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
643 {
644 // Draw the main part of the control same as TextCtrl
645 wxRenderer_DrawTextCtrl(win, dc, rect, flags);
646
647 // Draw the button inside the border, on the right side
648 wxRect br(rect);
649 br.height -= 2;
650 br.x += br.width - br.height - 1;
651 br.width = br.height;
652 br.y += 1;
653
654 wxRendererNative::Get().DrawComboBoxDropButton(win, dc, br, flags);
655 }
656
657
wxRenderer_DrawChoice(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)658 void wxRenderer_DrawChoice(wxWindow* win, wxDC& dc,
659 const wxRect& rect, int flags)
660 {
661 wxRenderer_DrawComboBox(win, dc, rect, flags);
662 }
663
664
665 // Draw a themed radio button
wxRenderer_DrawRadioButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)666 void wxRenderer_DrawRadioButton(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
667 {
668 #if wxUSE_UXTHEME
669 wxUxThemeHandle hTheme(win, L"BUTTON");
670 if ( !hTheme )
671 #endif
672 {
673 // ??? m_rendererNative.DrawRadioButton(win, dc, rect, flags);
674 return;
675 }
676
677 #if wxUSE_UXTHEME
678 RECT r;
679 wxCopyRectToRECT(rect, r);
680
681 int state;
682 if ( flags & wxCONTROL_CHECKED )
683 state = RBS_CHECKEDNORMAL;
684 else if ( flags & wxCONTROL_UNDETERMINED )
685 state = RBS_MIXEDNORMAL;
686 else
687 state = RBS_UNCHECKEDNORMAL;
688
689 // RBS_XXX is followed by RBX_XXXGOT, then RBS_XXXPRESSED and DISABLED
690 if ( flags & wxCONTROL_CURRENT )
691 state += 1;
692 else if ( flags & wxCONTROL_PRESSED )
693 state += 2;
694 else if ( flags & wxCONTROL_DISABLED )
695 state += 3;
696
697 wxUxThemeEngine::Get()->DrawThemeBackground
698 (
699 hTheme,
700 GraphicsHDC(&dc),
701 BP_RADIOBUTTON,
702 state,
703 &r,
704 NULL
705 );
706 #endif
707 }
708
709 #endif // wxUSE_UXTHEME
710