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