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 // Copyright:   (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
8 // Licence:     wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10 
11 // ============================================================================
12 // declarations
13 // ============================================================================
14 
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18 
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21 
22 #ifdef __BORLANDC__
23     #pragma hdrstop
24 #endif
25 
26 #ifndef WX_PRECOMP
27     #include "wx/string.h"
28     #include "wx/window.h"
29     #include "wx/dc.h"
30     #include "wx/settings.h"
31 #endif //WX_PRECOMP
32 
33 #include "wx/dcgraph.h"
34 #include "wx/scopeguard.h"
35 #include "wx/splitter.h"
36 #include "wx/renderer.h"
37 #include "wx/msw/private.h"
38 #include "wx/msw/uxtheme.h"
39 
40 // tmschema.h is in Win32 Platform SDK and might not be available with earlier
41 // compilers
42 #ifndef CP_DROPDOWNBUTTON
43     #define BP_PUSHBUTTON      1
44     #define BP_RADIOBUTTON     2
45     #define BP_CHECKBOX        3
46     #define RBS_UNCHECKEDNORMAL 1
47     #define RBS_CHECKEDNORMAL   (RBS_UNCHECKEDNORMAL + 4)
48     #define RBS_MIXEDNORMAL     (RBS_CHECKEDNORMAL + 4)
49     #define CBS_UNCHECKEDNORMAL 1
50     #define CBS_CHECKEDNORMAL   (CBS_UNCHECKEDNORMAL + 4)
51     #define CBS_MIXEDNORMAL     (CBS_CHECKEDNORMAL + 4)
52 
53     #define PBS_NORMAL          1
54     #define PBS_HOT             2
55     #define PBS_PRESSED         3
56     #define PBS_DISABLED        4
57     #define PBS_DEFAULTED       5
58 
59     #define CP_DROPDOWNBUTTON  1
60 
61     #define CBXS_NORMAL        1
62     #define CBXS_HOT           2
63     #define CBXS_PRESSED       3
64     #define CBXS_DISABLED      4
65 
66     #define TVP_GLYPH           2
67 
68     #define GLPS_CLOSED         1
69     #define GLPS_OPENED         2
70 
71     #define HP_HEADERITEM       1
72 
73     #define HIS_NORMAL          1
74     #define HIS_HOT             2
75     #define HIS_PRESSED         3
76 
77     #define TMT_HEIGHT          2417
78 
79     #define HP_HEADERSORTARROW  4
80     #define HSAS_SORTEDUP       1
81     #define HSAS_SORTEDDOWN     2
82 
83     #define EP_EDITTEXT         1
84     #define ETS_NORMAL          1
85     #define ETS_HOT             2
86     #define ETS_SELECTED        3
87     #define ETS_DISABLED        4
88     #define ETS_FOCUSED         5
89     #define ETS_READONLY        6
90     #define ETS_ASSIST          7
91     #define TMT_FILLCOLOR       3802
92     #define TMT_TEXTCOLOR       3803
93     #define TMT_BORDERCOLOR     3801
94     #define TMT_EDGEFILLCOLOR   3808
95 
96     #define WP_MINBUTTON 15
97     #define WP_MAXBUTTON 17
98     #define WP_CLOSEBUTTON 18
99     #define WP_RESTOREBUTTON 21
100     #define WP_HELPBUTTON 23
101 #endif
102 
103 #if defined(__WXWINCE__)
104     #ifndef DFCS_FLAT
105         #define DFCS_FLAT 0
106     #endif
107     #ifndef DFCS_MONO
108         #define DFCS_MONO 0
109     #endif
110 #endif
111 
112 #ifndef DFCS_HOT
113     #define DFCS_HOT 0x1000
114 #endif
115 
116 // ----------------------------------------------------------------------------
117 // methods common to wxRendererMSW and wxRendererXP
118 // ----------------------------------------------------------------------------
119 
120 class wxRendererMSWBase : public wxDelegateRendererNative
121 {
122 public:
wxRendererMSWBase()123     wxRendererMSWBase() { }
wxRendererMSWBase(wxRendererNative & rendererNative)124     wxRendererMSWBase(wxRendererNative& rendererNative)
125         : wxDelegateRendererNative(rendererNative) { }
126 
127     void DrawFocusRect(wxWindow * win,
128                         wxDC& dc,
129                         const wxRect& rect,
130                         int flags = 0);
131 
132     void DrawItemSelectionRect(wxWindow *win,
133                                 wxDC& dc,
134                                 const wxRect& rect,
135                                 int flags = 0);
136 
137     void DrawChoice(wxWindow* win,
138                      wxDC& dc,
139                      const wxRect& rect,
140                      int flags = 0);
141 
142     void DrawComboBox(wxWindow* win,
143                        wxDC& dc,
144                        const wxRect& rect,
145                        int flags = 0);
146 
147     virtual void DrawComboBoxDropButton(wxWindow *win,
148                                          wxDC& dc,
149                                          const wxRect& rect,
150                                          int flags = 0) = 0;
151 
152     virtual void DrawTextCtrl(wxWindow* win,
153                                wxDC& dc,
154                                const wxRect& rect,
155                                int flags = 0) = 0;
156 };
157 
158 // ----------------------------------------------------------------------------
159 // wxRendererMSW: wxRendererNative implementation for "old" Win32 systems
160 // ----------------------------------------------------------------------------
161 
162 class wxRendererMSW : public wxRendererMSWBase
163 {
164 public:
wxRendererMSW()165     wxRendererMSW() { }
166 
167     static wxRendererNative& Get();
168 
169     virtual void DrawComboBoxDropButton(wxWindow *win,
170                                         wxDC& dc,
171                                         const wxRect& rect,
172                                         int flags = 0);
173 
DrawCheckBox(wxWindow * win,wxDC & dc,const wxRect & rect,int flags=0)174     virtual void DrawCheckBox(wxWindow *win,
175                               wxDC& dc,
176                               const wxRect& rect,
177                               int flags = 0)
178     {
179         DoDrawButton(DFCS_BUTTONCHECK, win, dc, rect, flags);
180     }
181 
182     virtual void DrawPushButton(wxWindow *win,
183                                 wxDC& dc,
184                                 const wxRect& rect,
185                                 int flags = 0);
186 
187     virtual void DrawTextCtrl(wxWindow* win,
188                               wxDC& dc,
189                               const wxRect& rect,
190                               int flags = 0);
191 
DrawRadioBitmap(wxWindow * win,wxDC & dc,const wxRect & rect,int flags=0)192     virtual void DrawRadioBitmap(wxWindow* win,
193                                  wxDC& dc,
194                                  const wxRect& rect,
195                                  int flags = 0)
196     {
197         DoDrawButton(DFCS_BUTTONRADIO, win, dc, rect, flags);
198     }
199 
200     virtual void DrawTitleBarBitmap(wxWindow *win,
201                                     wxDC& dc,
202                                     const wxRect& rect,
203                                     wxTitleBarButton button,
204                                     int flags = 0);
205 
206     virtual wxSize GetCheckBoxSize(wxWindow *win);
207 
208     virtual int GetHeaderButtonHeight(wxWindow *win);
209 
210     virtual int GetHeaderButtonMargin(wxWindow *win);
211 
212 private:
213     // wrapper of DrawFrameControl()
214     void DoDrawFrameControl(UINT type,
215                             UINT kind,
216                             wxWindow *win,
217                             wxDC& dc,
218                             const wxRect& rect,
219                             int flags);
220 
221     // common part of Draw{PushButton,CheckBox,RadioBitmap}(): wraps
222     // DrawFrameControl(DFC_BUTTON)
DoDrawButton(UINT kind,wxWindow * win,wxDC & dc,const wxRect & rect,int flags)223     void DoDrawButton(UINT kind,
224                       wxWindow *win,
225                       wxDC& dc,
226                       const wxRect& rect,
227                       int flags)
228     {
229         DoDrawFrameControl(DFC_BUTTON, kind, win, dc, rect, flags);
230     }
231 
232     wxDECLARE_NO_COPY_CLASS(wxRendererMSW);
233 };
234 
235 // ----------------------------------------------------------------------------
236 // wxRendererXP: wxRendererNative implementation for Windows XP and later
237 // ----------------------------------------------------------------------------
238 
239 #if wxUSE_UXTHEME
240 
241 class wxRendererXP : public wxRendererMSWBase
242 {
243 public:
wxRendererXP()244     wxRendererXP() : wxRendererMSWBase(wxRendererMSW::Get()) { }
245 
246     static wxRendererNative& Get();
247 
248     virtual int DrawHeaderButton(wxWindow *win,
249                                   wxDC& dc,
250                                   const wxRect& rect,
251                                   int flags = 0,
252                                   wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
253                                   wxHeaderButtonParams* params = NULL);
254 
255     virtual void DrawTreeItemButton(wxWindow *win,
256                                     wxDC& dc,
257                                     const wxRect& rect,
258                                     int flags = 0);
259     virtual void DrawSplitterBorder(wxWindow *win,
260                                     wxDC& dc,
261                                     const wxRect& rect,
262                                     int flags = 0);
263     virtual void DrawSplitterSash(wxWindow *win,
264                                   wxDC& dc,
265                                   const wxSize& size,
266                                   wxCoord position,
267                                   wxOrientation orient,
268                                   int flags = 0);
269     virtual void DrawComboBoxDropButton(wxWindow *win,
270                                         wxDC& dc,
271                                         const wxRect& rect,
272                                         int flags = 0);
DrawCheckBox(wxWindow * win,wxDC & dc,const wxRect & rect,int flags=0)273     virtual void DrawCheckBox(wxWindow *win,
274                               wxDC& dc,
275                               const wxRect& rect,
276                               int flags = 0)
277     {
278         if ( !DoDrawXPButton(BP_CHECKBOX, win, dc, rect, flags) )
279             m_rendererNative.DrawCheckBox(win, dc, rect, flags);
280     }
281 
DrawPushButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags=0)282     virtual void DrawPushButton(wxWindow *win,
283                                 wxDC& dc,
284                                 const wxRect& rect,
285                                 int flags = 0)
286     {
287         if ( !DoDrawXPButton(BP_PUSHBUTTON, win, dc, rect, flags) )
288             m_rendererNative.DrawPushButton(win, dc, rect, flags);
289     }
290 
291     virtual void DrawTextCtrl(wxWindow* win,
292                               wxDC& dc,
293                               const wxRect& rect,
294                               int flags = 0);
295 
DrawRadioBitmap(wxWindow * win,wxDC & dc,const wxRect & rect,int flags=0)296     virtual void DrawRadioBitmap(wxWindow *win,
297                                  wxDC& dc,
298                                  const wxRect& rect,
299                                  int flags = 0)
300     {
301         if ( !DoDrawXPButton(BP_RADIOBUTTON, win, dc, rect, flags) )
302             m_rendererNative.DrawRadioBitmap(win, dc, rect, flags);
303     }
304 
305     virtual void DrawTitleBarBitmap(wxWindow *win,
306                                     wxDC& dc,
307                                     const wxRect& rect,
308                                     wxTitleBarButton button,
309                                     int flags = 0);
310 
311     virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win);
312 
313 private:
314     // wrapper around DrawThemeBackground() translating flags to NORMAL/HOT/
315     // PUSHED/DISABLED states (and so suitable for drawing anything
316     // button-like)
317     void DoDrawButtonLike(HTHEME htheme,
318                           int part,
319                           wxDC& dc,
320                           const wxRect& rect,
321                           int flags);
322 
323     // common part of DrawCheckBox(), DrawPushButton() and DrawRadioBitmap()
324     bool DoDrawXPButton(int kind,
325                         wxWindow *win,
326                         wxDC& dc,
327                         const wxRect& rect,
328                         int flags);
329 
330     wxDECLARE_NO_COPY_CLASS(wxRendererXP);
331 };
332 
333 #endif // wxUSE_UXTHEME
334 
335 
336 // ============================================================================
337 // wxRendererMSWBase implementation
338 // ============================================================================
339 
DrawFocusRect(wxWindow * WXUNUSED (win),wxDC & dc,const wxRect & rect,int WXUNUSED (flags))340 void wxRendererMSWBase::DrawFocusRect(wxWindow * WXUNUSED(win),
341                                       wxDC& dc,
342                                       const wxRect& rect,
343                                       int WXUNUSED(flags))
344 {
345     RECT rc;
346     wxCopyRectToRECT(rect, rc);
347 
348     ::DrawFocusRect(GetHdcOf(dc.GetTempHDC()), &rc);
349 }
350 
DrawItemSelectionRect(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)351 void wxRendererMSWBase::DrawItemSelectionRect(wxWindow *win,
352                                               wxDC& dc,
353                                               const wxRect& rect,
354                                               int flags)
355 {
356     wxBrush brush;
357     if ( flags & wxCONTROL_SELECTED )
358     {
359         if ( flags & wxCONTROL_FOCUSED )
360         {
361             brush = wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT));
362         }
363         else // !focused
364         {
365             brush = wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
366         }
367     }
368     else // !selected
369     {
370         brush = *wxTRANSPARENT_BRUSH;
371     }
372 
373     dc.SetBrush(brush);
374     dc.SetPen(*wxTRANSPARENT_PEN);
375     dc.DrawRectangle( rect );
376 
377     if ((flags & wxCONTROL_FOCUSED) && (flags & wxCONTROL_CURRENT))
378         DrawFocusRect( win, dc, rect, flags );
379 }
380 
DrawChoice(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)381 void wxRendererMSWBase::DrawChoice(wxWindow* win,
382                                    wxDC& dc,
383                                    const wxRect& rect,
384                                    int flags)
385 {
386     DrawComboBox(win, dc, rect, flags);
387 }
388 
DrawComboBox(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)389 void wxRendererMSWBase::DrawComboBox(wxWindow* win,
390                                      wxDC& dc,
391                                      const wxRect& rect,
392                                      int flags)
393 {
394     // Draw the main part of the control same as TextCtrl
395     DrawTextCtrl(win, dc, rect, flags);
396 
397     // Draw the button inside the border, on the right side
398     wxRect br(rect);
399     br.height -= 2;
400     br.x += br.width - br.height - 1;
401     br.width = br.height;
402     br.y += 1;
403 
404     DrawComboBoxDropButton(win, dc, br, flags);
405 }
406 
407 // ============================================================================
408 // wxRendererNative and wxRendererMSW implementation
409 // ============================================================================
410 
411 /* static */
GetDefault()412 wxRendererNative& wxRendererNative::GetDefault()
413 {
414 #if wxUSE_UXTHEME
415     wxUxThemeEngine *themeEngine = wxUxThemeEngine::Get();
416     if ( themeEngine && themeEngine->IsAppThemed() )
417         return wxRendererXP::Get();
418 #endif // wxUSE_UXTHEME
419 
420     return wxRendererMSW::Get();
421 }
422 
423 /* static */
Get()424 wxRendererNative& wxRendererMSW::Get()
425 {
426     static wxRendererMSW s_rendererMSW;
427 
428     return s_rendererMSW;
429 }
430 
431 void
DrawComboBoxDropButton(wxWindow * WXUNUSED (win),wxDC & dc,const wxRect & rect,int flags)432 wxRendererMSW::DrawComboBoxDropButton(wxWindow * WXUNUSED(win),
433                                       wxDC& dc,
434                                       const wxRect& rect,
435                                       int flags)
436 {
437     wxCHECK_RET( dc.GetImpl(), wxT("Invalid wxDC") );
438 
439     wxRect adjustedRect = dc.GetImpl()->MSWApplyGDIPlusTransform(rect);
440 
441     RECT r;
442     wxCopyRectToRECT(adjustedRect, r);
443 
444     int style = DFCS_SCROLLCOMBOBOX;
445     if ( flags & wxCONTROL_DISABLED )
446         style |= DFCS_INACTIVE;
447     if ( flags & wxCONTROL_PRESSED )
448         style |= DFCS_PUSHED | DFCS_FLAT;
449 
450     ::DrawFrameControl(GetHdcOf(dc.GetTempHDC()), &r, DFC_SCROLL, style);
451 }
452 
453 void
DoDrawFrameControl(UINT type,UINT kind,wxWindow * WXUNUSED (win),wxDC & dc,const wxRect & rect,int flags)454 wxRendererMSW::DoDrawFrameControl(UINT type,
455                                   UINT kind,
456                                   wxWindow * WXUNUSED(win),
457                                   wxDC& dc,
458                                   const wxRect& rect,
459                                   int flags)
460 {
461     wxCHECK_RET( dc.GetImpl(), wxT("Invalid wxDC") );
462 
463     wxRect adjustedRect = dc.GetImpl()->MSWApplyGDIPlusTransform(rect);
464 
465     RECT r;
466     wxCopyRectToRECT(adjustedRect, r);
467 
468     int style = kind;
469     if ( flags & wxCONTROL_CHECKED )
470         style |= DFCS_CHECKED;
471     if ( flags & wxCONTROL_DISABLED )
472         style |= DFCS_INACTIVE;
473     if ( flags & wxCONTROL_FLAT )
474         style |= DFCS_MONO;
475     if ( flags & wxCONTROL_PRESSED )
476         style |= DFCS_PUSHED;
477     if ( flags & wxCONTROL_CURRENT )
478         style |= DFCS_HOT;
479     if ( flags & wxCONTROL_UNDETERMINED )
480         // Using DFCS_BUTTON3STATE here doesn't work (as might be expected),
481         // use the following two styles to get the same look of a check box
482         // in the undetermined state.
483         style |= DFCS_INACTIVE | DFCS_CHECKED;
484 
485     ::DrawFrameControl(GetHdcOf(dc.GetTempHDC()), &r, type, style);
486 }
487 
488 void
DrawPushButton(wxWindow * win,wxDC & dc,const wxRect & rectOrig,int flags)489 wxRendererMSW::DrawPushButton(wxWindow *win,
490                               wxDC& dc,
491                               const wxRect& rectOrig,
492                               int flags)
493 {
494     wxRect rect(rectOrig);
495     if ( flags & wxCONTROL_ISDEFAULT )
496     {
497         // DrawFrameControl() doesn't seem to support default buttons so we
498         // have to draw the border ourselves
499         wxDCPenChanger pen(dc, *wxBLACK_PEN);
500         wxDCBrushChanger brush(dc, *wxTRANSPARENT_BRUSH);
501         dc.DrawRectangle(rect);
502         rect.Deflate(1);
503     }
504 
505     DoDrawButton(DFCS_BUTTONPUSH, win, dc, rect, flags);
506 }
507 
508 void
DrawTitleBarBitmap(wxWindow * win,wxDC & dc,const wxRect & rect,wxTitleBarButton button,int flags)509 wxRendererMSW::DrawTitleBarBitmap(wxWindow *win,
510                                   wxDC& dc,
511                                   const wxRect& rect,
512                                   wxTitleBarButton button,
513                                   int flags)
514 {
515     UINT kind;
516     switch ( button )
517     {
518         case wxTITLEBAR_BUTTON_CLOSE:
519             kind = DFCS_CAPTIONCLOSE;
520             break;
521 
522         case wxTITLEBAR_BUTTON_MAXIMIZE:
523             kind = DFCS_CAPTIONMAX;
524             break;
525 
526         case wxTITLEBAR_BUTTON_ICONIZE:
527             kind = DFCS_CAPTIONMIN;
528             break;
529 
530         case wxTITLEBAR_BUTTON_RESTORE:
531             kind = DFCS_CAPTIONRESTORE;
532             break;
533 
534         case wxTITLEBAR_BUTTON_HELP:
535             kind = DFCS_CAPTIONHELP;
536             break;
537 
538         default:
539             wxFAIL_MSG( "unsupported title bar button" );
540             return;
541     }
542 
543     DoDrawFrameControl(DFC_CAPTION, kind, win, dc, rect, flags);
544 }
545 
GetCheckBoxSize(wxWindow * WXUNUSED (win))546 wxSize wxRendererMSW::GetCheckBoxSize(wxWindow * WXUNUSED(win))
547 {
548     return wxSize(::GetSystemMetrics(SM_CXMENUCHECK),
549                   ::GetSystemMetrics(SM_CYMENUCHECK));
550 }
551 
GetHeaderButtonHeight(wxWindow * WXUNUSED (win))552 int wxRendererMSW::GetHeaderButtonHeight(wxWindow * WXUNUSED(win))
553 {
554     // some "reasonable" value returned in case of error, it doesn't really
555     // correspond to anything but it's better than returning 0
556     static const int DEFAULT_HEIGHT = 20;
557 
558 
559     // create a temporary header window just to get its geometry
560     HWND hwndHeader = ::CreateWindow(WC_HEADER, NULL, 0,
561                                      0, 0, 0, 0, NULL, NULL, NULL, NULL);
562     if ( !hwndHeader )
563         return DEFAULT_HEIGHT;
564 
565     wxON_BLOCK_EXIT1( ::DestroyWindow, hwndHeader );
566 
567     // initialize the struct filled with the values by Header_Layout()
568     RECT parentRect = { 0, 0, 100, 100 };
569     WINDOWPOS wp = { 0, 0, 0, 0, 0, 0, 0 };
570     HDLAYOUT hdl = { &parentRect, &wp };
571 
572     return Header_Layout(hwndHeader, &hdl) ? wp.cy : DEFAULT_HEIGHT;
573 }
574 
GetHeaderButtonMargin(wxWindow * WXUNUSED (win))575 int wxRendererMSW::GetHeaderButtonMargin(wxWindow *WXUNUSED(win))
576 {
577     return 10;
578 }
579 
580 // Uses the theme to draw the border and fill for something like a wxTextCtrl
DrawTextCtrl(wxWindow * WXUNUSED (win),wxDC & dc,const wxRect & rect,int WXUNUSED (flags))581 void wxRendererMSW::DrawTextCtrl(wxWindow* WXUNUSED(win),
582                                  wxDC& dc,
583                                  const wxRect& rect,
584                                  int WXUNUSED(flags))
585 {
586     wxColour fill;
587     wxColour bdr;
588     {
589         fill = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
590         bdr = *wxBLACK;
591     }
592 
593     dc.SetPen(bdr);
594     dc.SetBrush(fill);
595     dc.DrawRectangle(rect);
596 }
597 
598 
599 // ============================================================================
600 // wxRendererXP implementation
601 // ============================================================================
602 
603 #if wxUSE_UXTHEME
604 
605 /* static */
Get()606 wxRendererNative& wxRendererXP::Get()
607 {
608     static wxRendererXP s_rendererXP;
609 
610     return s_rendererXP;
611 }
612 
613 // NOTE: There is no guarantee that the button drawn fills the entire rect (XP
614 // default theme, for example), so the caller should have cleared button's
615 // background before this call. This is quite likely a wxMSW-specific thing.
616 void
DrawComboBoxDropButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)617 wxRendererXP::DrawComboBoxDropButton(wxWindow * win,
618                                       wxDC& dc,
619                                       const wxRect& rect,
620                                       int flags)
621 {
622     wxUxThemeHandle hTheme(win, L"COMBOBOX");
623     if ( !hTheme )
624     {
625         m_rendererNative.DrawComboBoxDropButton(win, dc, rect, flags);
626         return;
627     }
628 
629     wxCHECK_RET( dc.GetImpl(), wxT("Invalid wxDC") );
630 
631     wxRect adjustedRect = dc.GetImpl()->MSWApplyGDIPlusTransform(rect);
632 
633     RECT r;
634     wxCopyRectToRECT(adjustedRect, r);
635 
636     int state;
637     if ( flags & wxCONTROL_PRESSED )
638         state = CBXS_PRESSED;
639     else if ( flags & wxCONTROL_CURRENT )
640         state = CBXS_HOT;
641     else if ( flags & wxCONTROL_DISABLED )
642         state = CBXS_DISABLED;
643     else
644         state = CBXS_NORMAL;
645 
646     wxUxThemeEngine::Get()->DrawThemeBackground
647                             (
648                                 hTheme,
649                                 GetHdcOf(dc.GetTempHDC()),
650                                 CP_DROPDOWNBUTTON,
651                                 state,
652                                 &r,
653                                 NULL
654                             );
655 
656 }
657 
658 int
DrawHeaderButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags,wxHeaderSortIconType sortArrow,wxHeaderButtonParams * params)659 wxRendererXP::DrawHeaderButton(wxWindow *win,
660                                wxDC& dc,
661                                const wxRect& rect,
662                                int flags,
663                                wxHeaderSortIconType sortArrow,
664                                wxHeaderButtonParams* params)
665 {
666     wxUxThemeHandle hTheme(win, L"HEADER");
667     if ( !hTheme )
668     {
669         return m_rendererNative.DrawHeaderButton(win, dc, rect, flags, sortArrow, params);
670     }
671 
672     wxCHECK_MSG( dc.GetImpl(), -1, wxT("Invalid wxDC") );
673 
674     wxRect adjustedRect = dc.GetImpl()->MSWApplyGDIPlusTransform(rect);
675 
676     RECT r;
677     wxCopyRectToRECT(adjustedRect, r);
678 
679     int state;
680     if ( flags & wxCONTROL_PRESSED )
681         state = HIS_PRESSED;
682     else if ( flags & wxCONTROL_CURRENT )
683         state = HIS_HOT;
684     else
685         state = HIS_NORMAL;
686     wxUxThemeEngine::Get()->DrawThemeBackground
687                             (
688                                 hTheme,
689                                 GetHdcOf(dc.GetTempHDC()),
690                                 HP_HEADERITEM,
691                                 state,
692                                 &r,
693                                 NULL
694                             );
695 
696     // NOTE: Using the theme to draw HP_HEADERSORTARROW doesn't do anything.
697     // Why?  If this can be fixed then draw the sort arrows using the theme
698     // and then clear those flags before calling DrawHeaderButtonContents.
699 
700     // Add any extras that are specified in flags and params
701     return DrawHeaderButtonContents(win, dc, rect, flags, sortArrow, params);
702 }
703 
704 
705 void
DrawTreeItemButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)706 wxRendererXP::DrawTreeItemButton(wxWindow *win,
707                                  wxDC& dc,
708                                  const wxRect& rect,
709                                  int flags)
710 {
711     wxUxThemeHandle hTheme(win, L"TREEVIEW");
712     if ( !hTheme )
713     {
714         m_rendererNative.DrawTreeItemButton(win, dc, rect, flags);
715         return;
716     }
717 
718     wxCHECK_RET( dc.GetImpl(), wxT("Invalid wxDC") );
719 
720     wxRect adjustedRect = dc.GetImpl()->MSWApplyGDIPlusTransform(rect);
721 
722     RECT r;
723     wxCopyRectToRECT(adjustedRect, r);
724 
725     int state = flags & wxCONTROL_EXPANDED ? GLPS_OPENED : GLPS_CLOSED;
726     wxUxThemeEngine::Get()->DrawThemeBackground
727                             (
728                                 hTheme,
729                                 GetHdcOf(dc.GetTempHDC()),
730                                 TVP_GLYPH,
731                                 state,
732                                 &r,
733                                 NULL
734                             );
735 }
736 
737 bool
DoDrawXPButton(int kind,wxWindow * win,wxDC & dc,const wxRect & rect,int flags)738 wxRendererXP::DoDrawXPButton(int kind,
739                              wxWindow *win,
740                              wxDC& dc,
741                              const wxRect& rect,
742                              int flags)
743 {
744     wxUxThemeHandle hTheme(win, L"BUTTON");
745     if ( !hTheme )
746         return false;
747 
748     DoDrawButtonLike(hTheme, kind, dc, rect, flags);
749 
750     return true;
751 }
752 
753 void
DoDrawButtonLike(HTHEME htheme,int part,wxDC & dc,const wxRect & rect,int flags)754 wxRendererXP::DoDrawButtonLike(HTHEME htheme,
755                                int part,
756                                wxDC& dc,
757                                const wxRect& rect,
758                                int flags)
759 {
760     wxCHECK_RET( dc.GetImpl(), wxT("Invalid wxDC") );
761 
762     wxRect adjustedRect = dc.GetImpl()->MSWApplyGDIPlusTransform(rect);
763 
764     RECT r;
765     wxCopyRectToRECT(adjustedRect, r);
766 
767     // the base state is always 1, whether it is PBS_NORMAL,
768     // {CBS,RBS}_UNCHECKEDNORMAL or CBS_NORMAL
769     int state = 1;
770 
771     // XBS_XXX is followed by XBX_XXXHOT, then XBS_XXXPRESSED and DISABLED
772     enum
773     {
774         NORMAL_OFFSET,
775         HOT_OFFSET,
776         PRESSED_OFFSET,
777         DISABLED_OFFSET,
778         STATES_COUNT
779     };
780 
781     // in both RBS_ and CBS_ enums CHECKED elements are offset by 4 from base
782     // (UNCHECKED) ones and MIXED are offset by 4 again as there are all states
783     // from the above enum in between them
784     if ( flags & wxCONTROL_CHECKED )
785         state += STATES_COUNT;
786     else if ( flags & wxCONTROL_UNDETERMINED )
787         state += 2*STATES_COUNT;
788 
789     if ( flags & wxCONTROL_DISABLED )
790         state += DISABLED_OFFSET;
791     else if ( flags & wxCONTROL_PRESSED )
792         state += PRESSED_OFFSET;
793     else if ( flags & wxCONTROL_CURRENT )
794         state += HOT_OFFSET;
795     // wxCONTROL_ISDEFAULT flag is only valid for push buttons
796     else if ( part == BP_PUSHBUTTON && (flags & wxCONTROL_ISDEFAULT) )
797         state = PBS_DEFAULTED;
798 
799     wxUxThemeEngine::Get()->DrawThemeBackground
800                             (
801                                 htheme,
802                                 GetHdcOf(dc.GetTempHDC()),
803                                 part,
804                                 state,
805                                 &r,
806                                 NULL
807                             );
808 }
809 
810 void
DrawTitleBarBitmap(wxWindow * win,wxDC & dc,const wxRect & rect,wxTitleBarButton button,int flags)811 wxRendererXP::DrawTitleBarBitmap(wxWindow *win,
812                                  wxDC& dc,
813                                  const wxRect& rect,
814                                  wxTitleBarButton button,
815                                  int flags)
816 {
817     wxUxThemeHandle hTheme(win, L"WINDOW");
818     if ( !hTheme )
819     {
820         m_rendererNative.DrawTitleBarBitmap(win, dc, rect, button, flags);
821         return;
822     }
823 
824     int part;
825     switch ( button )
826     {
827         case wxTITLEBAR_BUTTON_CLOSE:
828             part = WP_CLOSEBUTTON;
829             break;
830 
831         case wxTITLEBAR_BUTTON_MAXIMIZE:
832             part = WP_MAXBUTTON;
833             break;
834 
835         case wxTITLEBAR_BUTTON_ICONIZE:
836             part = WP_MINBUTTON;
837             break;
838 
839         case wxTITLEBAR_BUTTON_RESTORE:
840             part = WP_RESTOREBUTTON;
841             break;
842 
843         case wxTITLEBAR_BUTTON_HELP:
844             part = WP_HELPBUTTON;
845             break;
846 
847         default:
848             wxFAIL_MSG( "unsupported title bar button" );
849             return;
850     }
851 
852     DoDrawButtonLike(hTheme, part, dc, rect, flags);
853 }
854 
855 // Uses the theme to draw the border and fill for something like a wxTextCtrl
DrawTextCtrl(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)856 void wxRendererXP::DrawTextCtrl(wxWindow* win,
857                                 wxDC& dc,
858                                 const wxRect& rect,
859                                 int flags)
860 {
861     wxUxThemeHandle hTheme(win, L"EDIT");
862     if ( !hTheme )
863     {
864         m_rendererNative.DrawTextCtrl(win,dc,rect,flags);
865         return;
866     }
867 
868     wxColour fill;
869     wxColour bdr;
870     COLORREF cref;
871 
872     wxUxThemeEngine::Get()->GetThemeColor(hTheme, EP_EDITTEXT,
873                                           ETS_NORMAL, TMT_FILLCOLOR, &cref);
874     fill = wxRGBToColour(cref);
875 
876     int etsState;
877     if ( flags & wxCONTROL_DISABLED )
878         etsState = ETS_DISABLED;
879     else
880         etsState = ETS_NORMAL;
881 
882     wxUxThemeEngine::Get()->GetThemeColor(hTheme, EP_EDITTEXT,
883                                               etsState, TMT_BORDERCOLOR, &cref);
884     bdr = wxRGBToColour(cref);
885 
886     dc.SetPen( bdr );
887     dc.SetBrush( fill );
888     dc.DrawRectangle(rect);
889 }
890 
891 // ----------------------------------------------------------------------------
892 // splitter drawing
893 // ----------------------------------------------------------------------------
894 
895 // the width of the sash: this is the same as used by Explorer...
896 static const wxCoord SASH_WIDTH = 4;
897 
898 wxSplitterRenderParams
GetSplitterParams(const wxWindow * win)899 wxRendererXP::GetSplitterParams(const wxWindow * win)
900 {
901     if ( win->HasFlag(wxSP_NO_XP_THEME) )
902         return m_rendererNative.GetSplitterParams(win);
903     else
904         return wxSplitterRenderParams(SASH_WIDTH, 0, false);
905 }
906 
907 void
DrawSplitterBorder(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)908 wxRendererXP::DrawSplitterBorder(wxWindow * win,
909                                  wxDC& dc,
910                                  const wxRect& rect,
911                                  int flags)
912 {
913     if ( win->HasFlag(wxSP_NO_XP_THEME) )
914     {
915         m_rendererNative.DrawSplitterBorder(win, dc, rect, flags);
916     }
917 }
918 
919 void
DrawSplitterSash(wxWindow * win,wxDC & dc,const wxSize & size,wxCoord position,wxOrientation orient,int flags)920 wxRendererXP::DrawSplitterSash(wxWindow *win,
921                                wxDC& dc,
922                                const wxSize& size,
923                                wxCoord position,
924                                wxOrientation orient,
925                                int flags)
926 {
927     if ( !win->HasFlag(wxSP_NO_XP_THEME) )
928     {
929         dc.SetPen(*wxTRANSPARENT_PEN);
930         dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)));
931         if ( orient == wxVERTICAL )
932         {
933             dc.DrawRectangle(position, 0, SASH_WIDTH, size.y);
934         }
935         else // wxHORIZONTAL
936         {
937             dc.DrawRectangle(0, position, size.x, SASH_WIDTH);
938         }
939 
940         return;
941     }
942 
943     m_rendererNative.DrawSplitterSash(win, dc, size, position, orient, flags);
944 }
945 
946 #endif // wxUSE_UXTHEME
947