]> git.saurik.com Git - wxWidgets.git/blame - src/msw/renderer.cpp
don't leave dummy extension in of.lpstrDefExt (bug 1609614)
[wxWidgets.git] / src / msw / renderer.cpp
CommitLineData
9c7f49f5 1///////////////////////////////////////////////////////////////////////////////
90b903c2 2// Name: src/msw/renderer.cpp
38c4cb6a 3// Purpose: implementation of wxRendererNative for Windows
9c7f49f5
VZ
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>
65571936 9// License: wxWindows licence
9c7f49f5
VZ
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"
85b657c7
VS
29 #include "wx/window.h"
30 #include "wx/dc.h"
9eddec69 31 #include "wx/settings.h"
9c7f49f5
VZ
32#endif //WX_PRECOMP
33
3c2544bb 34#include "wx/splitter.h"
9c7f49f5 35#include "wx/renderer.h"
03f01e63 36#include "wx/msw/private.h"
4614c8e5 37#include "wx/msw/uxtheme.h"
8b97949e 38
7cf3223a
VZ
39// tmschema.h is in Win32 Platform SDK and might not be available with earlier
40// compilers
41#ifndef CP_DROPDOWNBUTTON
2209baae 42 #define BP_PUSHBUTTON 1
9f93b45e
VZ
43 #define BP_CHECKBOX 3
44 #define CBS_UNCHECKEDNORMAL 1
45 #define CBS_CHECKEDNORMAL (CBS_UNCHECKEDNORMAL + 4)
46 #define CBS_MIXEDNORMAL (CBS_CHECKEDNORMAL + 4)
47
2209baae
RR
48 #define PBS_NORMAL 1
49 #define PBS_HOT 2
50 #define PBS_PRESSED 3
51 #define PBS_DISABLED 4
52 #define PBS_DEFAULTED 5
53
7cf3223a
VZ
54 #define CP_DROPDOWNBUTTON 1
55
56 #define CBXS_NORMAL 1
57 #define CBXS_HOT 2
58 #define CBXS_PRESSED 3
59 #define CBXS_DISABLED 4
a9d9e2f2 60
9f93b45e
VZ
61 #define TVP_GLYPH 2
62
63 #define GLPS_CLOSED 1
a9d9e2f2
JS
64 #define GLPS_OPENED 2
65
66 #define HP_HEADERITEM 1
67
68 #define HIS_NORMAL 1
69 #define HIS_HOT 2
70 #define HIS_PRESSED 3
4b94ddc4
RD
71
72 #define TMT_HEIGHT 2417
73
74 #define HP_HEADERSORTARROW 4
75 #define HSAS_SORTEDUP 1
76 #define HSAS_SORTEDDOWN 2
7cf3223a
VZ
77#endif
78
9f93b45e
VZ
79#if defined(__WXWINCE__) && !defined(DFCS_FLAT)
80 #define DFCS_FLAT 0
81#endif
82
9c7f49f5 83// ----------------------------------------------------------------------------
8b97949e 84// wxRendererMSW: wxRendererNative implementation for "old" Win32 systems
9c7f49f5
VZ
85// ----------------------------------------------------------------------------
86
38c4cb6a 87class WXDLLEXPORT wxRendererMSW : public wxDelegateRendererNative
9c7f49f5 88{
2eb10e2a
VZ
89public:
90 wxRendererMSW() { }
91
8b97949e
VZ
92 static wxRendererNative& Get();
93
7402677a
VZ
94 virtual void DrawComboBoxDropButton(wxWindow *win,
95 wxDC& dc,
96 const wxRect& rect,
97 int flags = 0);
98
2209baae
RR
99 virtual void DrawPushButton(wxWindow *win,
100 wxDC& dc,
101 const wxRect& rect,
102 int flags = 0);
103
2eb10e2a
VZ
104private:
105 DECLARE_NO_COPY_CLASS(wxRendererMSW)
9c7f49f5
VZ
106};
107
8b97949e
VZ
108// ----------------------------------------------------------------------------
109// wxRendererXP: wxRendererNative implementation for Windows XP and later
110// ----------------------------------------------------------------------------
111
7cf3223a
VZ
112#if wxUSE_UXTHEME
113
8b97949e
VZ
114class WXDLLEXPORT wxRendererXP : public wxDelegateRendererNative
115{
116public:
117 wxRendererXP() : wxDelegateRendererNative(wxRendererMSW::Get()) { }
118
119 static wxRendererNative& Get();
120
c97c9952 121 virtual int DrawHeaderButton(wxWindow *win,
4b94ddc4
RD
122 wxDC& dc,
123 const wxRect& rect,
124 int flags = 0,
80752b57 125 wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
4b94ddc4
RD
126 wxHeaderButtonParams* params = NULL);
127 virtual int GetHeaderButtonHeight(wxWindow *win);
128
9f93b45e
VZ
129 virtual void DrawTreeItemButton(wxWindow *win,
130 wxDC& dc,
131 const wxRect& rect,
132 int flags = 0);
8b97949e
VZ
133 virtual void DrawSplitterBorder(wxWindow *win,
134 wxDC& dc,
c4e6c15e
VZ
135 const wxRect& rect,
136 int flags = 0);
8b97949e
VZ
137 virtual void DrawSplitterSash(wxWindow *win,
138 wxDC& dc,
139 const wxSize& size,
140 wxCoord position,
c4e6c15e
VZ
141 wxOrientation orient,
142 int flags = 0);
7cf3223a
VZ
143 virtual void DrawComboBoxDropButton(wxWindow *win,
144 wxDC& dc,
145 const wxRect& rect,
146 int flags = 0);
90b903c2
WS
147 virtual void DrawCheckBox(wxWindow *win,
148 wxDC& dc,
149 const wxRect& rect,
150 int flags = 0);
9f93b45e 151
2209baae
RR
152 virtual void DrawPushButton(wxWindow *win,
153 wxDC& dc,
154 const wxRect& rect,
155 int flags = 0);
156
9f93b45e 157 virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win);
8b97949e
VZ
158private:
159 DECLARE_NO_COPY_CLASS(wxRendererXP)
160};
161
7cf3223a
VZ
162#endif // wxUSE_UXTHEME
163
9c7f49f5 164// ============================================================================
8b97949e 165// wxRendererNative and wxRendererMSW implementation
9c7f49f5
VZ
166// ============================================================================
167
168/* static */
f0244295 169wxRendererNative& wxRendererNative::GetDefault()
8b97949e 170{
7cf3223a 171#if wxUSE_UXTHEME
8b97949e 172 wxUxThemeEngine *themeEngine = wxUxThemeEngine::Get();
7cf3223a
VZ
173 if ( themeEngine && themeEngine->IsAppThemed() )
174 return wxRendererXP::Get();
175#endif // wxUSE_UXTHEME
176
177 return wxRendererMSW::Get();
8b97949e
VZ
178}
179
180/* static */
181wxRendererNative& wxRendererMSW::Get()
9c7f49f5
VZ
182{
183 static wxRendererMSW s_rendererMSW;
184
185 return s_rendererMSW;
186}
187
7402677a
VZ
188void
189wxRendererMSW::DrawComboBoxDropButton(wxWindow * WXUNUSED(win),
190 wxDC& dc,
191 const wxRect& rect,
192 int flags)
193{
194 RECT r;
195 r.left = rect.GetLeft();
196 r.top = rect.GetTop();
7cf3223a
VZ
197 r.bottom = rect.y + rect.height;
198 r.right = rect.x + rect.width;
7402677a
VZ
199
200 int style = DFCS_SCROLLCOMBOBOX;
201 if ( flags & wxCONTROL_DISABLED )
202 style |= DFCS_INACTIVE;
203 if ( flags & wxCONTROL_PRESSED )
7cf3223a 204 style |= DFCS_PUSHED | DFCS_FLAT;
7402677a
VZ
205
206 ::DrawFrameControl(GetHdcOf(dc), &r, DFC_SCROLL, style);
207}
208
2209baae
RR
209void
210wxRendererMSW::DrawPushButton(wxWindow * WXUNUSED(win),
211 wxDC& dc,
f2ea4255 212 const wxRect& rectOrig,
2209baae
RR
213 int flags)
214{
f2ea4255 215 wxRect rect(rectOrig);
2209baae
RR
216
217 int style = DFCS_BUTTONPUSH;
218 if ( flags & wxCONTROL_DISABLED )
219 style |= DFCS_INACTIVE;
220 if ( flags & wxCONTROL_PRESSED )
221 style |= DFCS_PUSHED | DFCS_FLAT;
f2ea4255
VZ
222 if ( flags & wxCONTROL_ISDEFAULT )
223 {
224 // DrawFrameControl() doesn't seem to support default buttons so we
225 // have to draw the border ourselves
226 wxDCPenChanger pen(dc, *wxBLACK_PEN);
227 wxDCBrushChanger brush(dc, *wxTRANSPARENT_BRUSH);
228 dc.DrawRectangle(rect);
844b9f5f 229 rect.Deflate(1);
f2ea4255
VZ
230 }
231
232 RECT rc;
233 wxCopyRectToRECT(rect, rc);
234
235 ::DrawFrameControl(GetHdcOf(dc), &rc, DFC_BUTTON, style);
2209baae
RR
236}
237
8b97949e
VZ
238// ============================================================================
239// wxRendererXP implementation
240// ============================================================================
241
7cf3223a
VZ
242#if wxUSE_UXTHEME
243
8b97949e
VZ
244/* static */
245wxRendererNative& wxRendererXP::Get()
246{
247 static wxRendererXP s_rendererXP;
248
249 return s_rendererXP;
250}
251
7cf3223a
VZ
252// NOTE: There is no guarantee that the button drawn fills the entire rect (XP
253// default theme, for example), so the caller should have cleared button's
254// background before this call. This is quite likely a wxMSW-specific thing.
255void
256wxRendererXP::DrawComboBoxDropButton(wxWindow * win,
257 wxDC& dc,
258 const wxRect& rect,
259 int flags)
260{
261 wxUxThemeHandle hTheme(win, L"COMBOBOX");
9f93b45e 262 if ( !hTheme )
7cf3223a 263 {
9f93b45e
VZ
264 m_rendererNative.DrawComboBoxDropButton(win, dc, rect, flags);
265 return;
266 }
267
268 RECT r;
269 wxCopyRectToRECT(rect, r);
7cf3223a 270
9f93b45e
VZ
271 int state;
272 if ( flags & wxCONTROL_PRESSED )
273 state = CBXS_PRESSED;
274 else if ( flags & wxCONTROL_CURRENT )
275 state = CBXS_HOT;
276 else if ( flags & wxCONTROL_DISABLED )
277 state = CBXS_DISABLED;
278 else
279 state = CBXS_NORMAL;
280
281 wxUxThemeEngine::Get()->DrawThemeBackground
282 (
283 hTheme,
284 GetHdcOf(dc),
285 CP_DROPDOWNBUTTON,
286 state,
287 &r,
288 NULL
289 );
290
291}
292
c97c9952 293int
9f93b45e
VZ
294wxRendererXP::DrawHeaderButton(wxWindow *win,
295 wxDC& dc,
296 const wxRect& rect,
4b94ddc4 297 int flags,
80752b57 298 wxHeaderSortIconType sortArrow,
4b94ddc4 299 wxHeaderButtonParams* params)
9f93b45e
VZ
300{
301 wxUxThemeHandle hTheme(win, L"HEADER");
302 if ( !hTheme )
303 {
c97c9952 304 return m_rendererNative.DrawHeaderButton(win, dc, rect, flags, sortArrow, params);
7cf3223a 305 }
9f93b45e
VZ
306
307 RECT r;
308 wxCopyRectToRECT(rect, r);
309
310 int state;
311 if ( flags & wxCONTROL_PRESSED )
312 state = HIS_PRESSED;
313 else if ( flags & wxCONTROL_CURRENT )
314 state = HIS_HOT;
315 else
316 state = HIS_NORMAL;
317 wxUxThemeEngine::Get()->DrawThemeBackground
318 (
319 hTheme,
320 GetHdcOf(dc),
321 HP_HEADERITEM,
322 state,
323 &r,
324 NULL
325 );
4b94ddc4
RD
326
327 // NOTE: Using the theme to draw HP_HEADERSORTARROW doesn't do anything.
328 // Why? If this can be fixed then draw the sort arrows using the theme
329 // and then clear those flags before calling DrawHeaderButtonContents.
330
331 // Add any extras that are specified in flags and params
c97c9952 332 return DrawHeaderButtonContents(win, dc, rect, flags, sortArrow, params);
9f93b45e
VZ
333}
334
4b94ddc4
RD
335
336int
337wxRendererXP::GetHeaderButtonHeight(wxWindow *win)
338{
339 wxUxThemeHandle hTheme(win, L"HEADER");
340 if ( !hTheme )
341 {
342 return m_rendererNative.GetHeaderButtonHeight(win);
343 }
344
345 HRESULT hr;
346 int value = -1;
347
348 hr = wxUxThemeEngine::Get()->GetThemeMetric( hTheme,
349 NULL,
350 HP_HEADERITEM,
351 HIS_NORMAL,
352 TMT_HEIGHT,
353 &value );
354 if ( hr == S_OK )
355 return value;
356 else
357 return 20;
358}
359
360
9f93b45e
VZ
361void
362wxRendererXP::DrawTreeItemButton(wxWindow *win,
363 wxDC& dc,
364 const wxRect& rect,
365 int flags)
366{
367 wxUxThemeHandle hTheme(win, L"TREEVIEW");
368 if ( !hTheme )
369 {
370 m_rendererNative.DrawTreeItemButton(win, dc, rect, flags);
371 return;
372 }
373
374 RECT r;
375 wxCopyRectToRECT(rect, r);
376
377 int state = flags & wxCONTROL_EXPANDED ? GLPS_OPENED : GLPS_CLOSED;
378 wxUxThemeEngine::Get()->DrawThemeBackground
379 (
380 hTheme,
381 GetHdcOf(dc),
382 TVP_GLYPH,
383 state,
384 &r,
385 NULL
386 );
387}
388
389void
90b903c2
WS
390wxRendererXP::DrawCheckBox(wxWindow *win,
391 wxDC& dc,
392 const wxRect& rect,
393 int flags)
9f93b45e
VZ
394{
395 wxUxThemeHandle hTheme(win, L"BUTTON");
396 if ( !hTheme )
397 {
90b903c2 398 m_rendererNative.DrawCheckBox(win, dc, rect, flags);
9f93b45e
VZ
399 return;
400 }
401
402 RECT r;
403 wxCopyRectToRECT(rect, r);
404
405 int state;
406 if ( flags & wxCONTROL_CHECKED )
407 state = CBS_CHECKEDNORMAL;
408 else if ( flags & wxCONTROL_UNDETERMINED )
409 state = CBS_MIXEDNORMAL;
410 else
411 state = CBS_UNCHECKEDNORMAL;
412
413 // CBS_XXX is followed by CBX_XXXGOT, then CBS_XXXPRESSED and DISABLED
414 if ( flags & wxCONTROL_CURRENT )
415 state += 1;
416 else if ( flags & wxCONTROL_PRESSED )
417 state += 2;
418 else if ( flags & wxCONTROL_DISABLED )
419 state += 3;
420
421 wxUxThemeEngine::Get()->DrawThemeBackground
422 (
423 hTheme,
424 GetHdcOf(dc),
425 BP_CHECKBOX,
426 state,
427 &r,
428 NULL
429 );
7cf3223a
VZ
430}
431
2209baae
RR
432void
433wxRendererXP::DrawPushButton(wxWindow * win,
434 wxDC& dc,
435 const wxRect& rect,
436 int flags)
437{
438 wxUxThemeHandle hTheme(win, L"BUTTON");
439 if ( !hTheme )
440 {
441 m_rendererNative.DrawPushButton(win, dc, rect, flags);
442 return;
443 }
444
445 RECT r;
446 wxCopyRectToRECT(rect, r);
447
448 int state;
449 if ( flags & wxCONTROL_PRESSED )
450 state = PBS_PRESSED;
451 else if ( flags & wxCONTROL_CURRENT )
452 state = PBS_HOT;
453 else if ( flags & wxCONTROL_DISABLED )
454 state = PBS_DISABLED;
455 else if ( flags & wxCONTROL_ISDEFAULT )
456 state = PBS_DEFAULTED;
457 else
458 state = PBS_NORMAL;
459
460 wxUxThemeEngine::Get()->DrawThemeBackground
461 (
462 hTheme,
463 GetHdcOf(dc),
464 BP_PUSHBUTTON,
465 state,
466 &r,
467 NULL
468 );
469
470}
471
8b97949e
VZ
472// ----------------------------------------------------------------------------
473// splitter drawing
474// ----------------------------------------------------------------------------
475
476// the width of the sash: this is the same as used by Explorer...
477static const wxCoord SASH_WIDTH = 4;
478
c4e6c15e 479wxSplitterRenderParams
3c2544bb 480wxRendererXP::GetSplitterParams(const wxWindow * win)
8b97949e 481{
9f93b45e 482 if ( win->HasFlag(wxSP_NO_XP_THEME) )
3c2544bb
JS
483 return m_rendererNative.GetSplitterParams(win);
484 else
485 return wxSplitterRenderParams(SASH_WIDTH, 0, false);
8b97949e
VZ
486}
487
488void
3c2544bb
JS
489wxRendererXP::DrawSplitterBorder(wxWindow * win,
490 wxDC& dc,
491 const wxRect& rect,
492 int flags)
8b97949e 493{
9f93b45e 494 if ( win->HasFlag(wxSP_NO_XP_THEME) )
3c2544bb
JS
495 {
496 m_rendererNative.DrawSplitterBorder(win, dc, rect, flags);
497 }
8b97949e
VZ
498}
499
500void
501wxRendererXP::DrawSplitterSash(wxWindow *win,
502 wxDC& dc,
503 const wxSize& size,
504 wxCoord position,
c4e6c15e 505 wxOrientation orient,
3c2544bb 506 int flags)
8b97949e 507{
6421119d 508 if ( !win->HasFlag(wxSP_NO_XP_THEME) )
8b97949e 509 {
fe404d1a
JS
510 dc.SetPen(*wxTRANSPARENT_PEN);
511 dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)));
512 if ( orient == wxVERTICAL )
8b97949e 513 {
fe404d1a 514 dc.DrawRectangle(position, 0, SASH_WIDTH, size.y);
8b97949e 515 }
fe404d1a
JS
516 else // wxHORIZONTAL
517 {
518 dc.DrawRectangle(0, position, size.x, SASH_WIDTH);
519 }
520
521 return;
8b97949e 522 }
6421119d
VZ
523
524 m_rendererNative.DrawSplitterSash(win, dc, size, position, orient, flags);
8b97949e
VZ
525}
526
7cf3223a 527#endif // wxUSE_UXTHEME