Applied [ 1294048 ] [wxMSW] Correct splitter sash drawing on XP
[wxWidgets.git] / src / msw / renderer.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: 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 // 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 #endif //WX_PRECOMP
32
33 #include "wx/splitter.h"
34 #include "wx/renderer.h"
35 #include "wx/msw/uxtheme.h"
36 #include "wx/msw/private.h"
37
38 // tmschema.h is in Win32 Platform SDK and might not be available with earlier
39 // compilers
40 #ifndef CP_DROPDOWNBUTTON
41 #define CP_DROPDOWNBUTTON 1
42
43 #define CBXS_NORMAL 1
44 #define CBXS_HOT 2
45 #define CBXS_PRESSED 3
46 #define CBXS_DISABLED 4
47 #endif
48
49 // ----------------------------------------------------------------------------
50 // wxRendererMSW: wxRendererNative implementation for "old" Win32 systems
51 // ----------------------------------------------------------------------------
52
53 class WXDLLEXPORT wxRendererMSW : public wxDelegateRendererNative
54 {
55 public:
56 wxRendererMSW() { }
57
58 static wxRendererNative& Get();
59
60 virtual void DrawComboBoxDropButton(wxWindow *win,
61 wxDC& dc,
62 const wxRect& rect,
63 int flags = 0);
64
65 private:
66 DECLARE_NO_COPY_CLASS(wxRendererMSW)
67 };
68
69 // ----------------------------------------------------------------------------
70 // wxRendererXP: wxRendererNative implementation for Windows XP and later
71 // ----------------------------------------------------------------------------
72
73 #if wxUSE_UXTHEME
74
75 class WXDLLEXPORT wxRendererXP : public wxDelegateRendererNative
76 {
77 public:
78 wxRendererXP() : wxDelegateRendererNative(wxRendererMSW::Get()) { }
79
80 static wxRendererNative& Get();
81
82 virtual void DrawSplitterBorder(wxWindow *win,
83 wxDC& dc,
84 const wxRect& rect,
85 int flags = 0);
86 virtual void DrawSplitterSash(wxWindow *win,
87 wxDC& dc,
88 const wxSize& size,
89 wxCoord position,
90 wxOrientation orient,
91 int flags = 0);
92
93 virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win);
94
95 virtual void DrawComboBoxDropButton(wxWindow *win,
96 wxDC& dc,
97 const wxRect& rect,
98 int flags = 0);
99 private:
100 DECLARE_NO_COPY_CLASS(wxRendererXP)
101 };
102
103 #endif // wxUSE_UXTHEME
104
105 // ============================================================================
106 // wxRendererNative and wxRendererMSW implementation
107 // ============================================================================
108
109 /* static */
110 wxRendererNative& wxRendererNative::GetDefault()
111 {
112 #if wxUSE_UXTHEME
113 wxUxThemeEngine *themeEngine = wxUxThemeEngine::Get();
114 if ( themeEngine && themeEngine->IsAppThemed() )
115 return wxRendererXP::Get();
116 #endif // wxUSE_UXTHEME
117
118 return wxRendererMSW::Get();
119 }
120
121 /* static */
122 wxRendererNative& wxRendererMSW::Get()
123 {
124 static wxRendererMSW s_rendererMSW;
125
126 return s_rendererMSW;
127 }
128
129 #if defined(__WXWINCE__) && !defined(DFCS_FLAT)
130 #define DFCS_FLAT 0
131 #endif
132
133 void
134 wxRendererMSW::DrawComboBoxDropButton(wxWindow * WXUNUSED(win),
135 wxDC& dc,
136 const wxRect& rect,
137 int flags)
138 {
139 RECT r;
140 r.left = rect.GetLeft();
141 r.top = rect.GetTop();
142 r.bottom = rect.y + rect.height;
143 r.right = rect.x + rect.width;
144
145 int style = DFCS_SCROLLCOMBOBOX;
146 if ( flags & wxCONTROL_DISABLED )
147 style |= DFCS_INACTIVE;
148 if ( flags & wxCONTROL_PRESSED )
149 style |= DFCS_PUSHED | DFCS_FLAT;
150
151 ::DrawFrameControl(GetHdcOf(dc), &r, DFC_SCROLL, style);
152 }
153
154 // ============================================================================
155 // wxRendererXP implementation
156 // ============================================================================
157
158 #if wxUSE_UXTHEME
159
160 /* static */
161 wxRendererNative& wxRendererXP::Get()
162 {
163 static wxRendererXP s_rendererXP;
164
165 return s_rendererXP;
166 }
167
168 // NOTE: There is no guarantee that the button drawn fills the entire rect (XP
169 // default theme, for example), so the caller should have cleared button's
170 // background before this call. This is quite likely a wxMSW-specific thing.
171 void
172 wxRendererXP::DrawComboBoxDropButton(wxWindow * win,
173 wxDC& dc,
174 const wxRect& rect,
175 int flags)
176 {
177 wxUxThemeHandle hTheme(win, L"COMBOBOX");
178 if ( hTheme )
179 {
180 RECT r;
181 r.left = rect.x;
182 r.top = rect.y;
183 r.right = rect.x + rect.width;
184 r.bottom = rect.y + rect.height;
185
186 int state;
187 if ( flags & wxCONTROL_PRESSED )
188 state = CBXS_PRESSED;
189 else if ( flags & wxCONTROL_CURRENT )
190 state = CBXS_HOT;
191 else if ( flags & wxCONTROL_DISABLED )
192 state = CBXS_DISABLED;
193 else
194 state = CBXS_NORMAL;
195
196 wxUxThemeEngine::Get()->DrawThemeBackground
197 (
198 hTheme,
199 (HDC) dc.GetHDC(),
200 CP_DROPDOWNBUTTON,
201 state,
202 &r,
203 NULL
204 );
205
206 }
207 }
208
209 // ----------------------------------------------------------------------------
210 // splitter drawing
211 // ----------------------------------------------------------------------------
212
213 // the width of the sash: this is the same as used by Explorer...
214 static const wxCoord SASH_WIDTH = 4;
215
216 wxSplitterRenderParams
217 wxRendererXP::GetSplitterParams(const wxWindow * win)
218 {
219 if (win->GetWindowStyle() & wxSP_NO_XP_THEME)
220 return m_rendererNative.GetSplitterParams(win);
221 else
222 return wxSplitterRenderParams(SASH_WIDTH, 0, false);
223 }
224
225 void
226 wxRendererXP::DrawSplitterBorder(wxWindow * win,
227 wxDC& dc,
228 const wxRect& rect,
229 int flags)
230 {
231 if (win->GetWindowStyle() & wxSP_NO_XP_THEME)
232 {
233 m_rendererNative.DrawSplitterBorder(win, dc, rect, flags);
234 }
235 }
236
237 void
238 wxRendererXP::DrawSplitterSash(wxWindow *win,
239 wxDC& dc,
240 const wxSize& size,
241 wxCoord position,
242 wxOrientation orient,
243 int flags)
244 {
245 if ( !win->HasFlag(wxSP_NO_XP_THEME) )
246 {
247 dc.SetPen(*wxTRANSPARENT_PEN);
248 dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)));
249 if ( orient == wxVERTICAL )
250 {
251 dc.DrawRectangle(position, 0, SASH_WIDTH, size.y);
252 }
253 else // wxHORIZONTAL
254 {
255 dc.DrawRectangle(0, position, size.x, SASH_WIDTH);
256 }
257
258 return;
259 }
260
261 m_rendererNative.DrawSplitterSash(win, dc, size, position, orient, flags);
262 }
263
264 #endif // wxUSE_UXTHEME
265