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