]> git.saurik.com Git - wxWidgets.git/blame - src/msw/renderer.cpp
derive wxSTC from wxTextAreaBase to provide wxTextCtrl-like methods (see #9114)
[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
51c42fc5 34#include "wx/scopeguard.h"
3c2544bb 35#include "wx/splitter.h"
9c7f49f5 36#include "wx/renderer.h"
03f01e63 37#include "wx/msw/private.h"
025f7d77 38#include "wx/msw/dc.h"
4614c8e5 39#include "wx/msw/uxtheme.h"
8b97949e 40
7cf3223a
VZ
41// tmschema.h is in Win32 Platform SDK and might not be available with earlier
42// compilers
43#ifndef CP_DROPDOWNBUTTON
2209baae 44 #define BP_PUSHBUTTON 1
9f93b45e
VZ
45 #define BP_CHECKBOX 3
46 #define CBS_UNCHECKEDNORMAL 1
47 #define CBS_CHECKEDNORMAL (CBS_UNCHECKEDNORMAL + 4)
48 #define CBS_MIXEDNORMAL (CBS_CHECKEDNORMAL + 4)
49
2209baae
RR
50 #define PBS_NORMAL 1
51 #define PBS_HOT 2
52 #define PBS_PRESSED 3
53 #define PBS_DISABLED 4
54 #define PBS_DEFAULTED 5
55
7cf3223a
VZ
56 #define CP_DROPDOWNBUTTON 1
57
58 #define CBXS_NORMAL 1
59 #define CBXS_HOT 2
60 #define CBXS_PRESSED 3
61 #define CBXS_DISABLED 4
a9d9e2f2 62
9f93b45e
VZ
63 #define TVP_GLYPH 2
64
65 #define GLPS_CLOSED 1
a9d9e2f2
JS
66 #define GLPS_OPENED 2
67
68 #define HP_HEADERITEM 1
69
70 #define HIS_NORMAL 1
71 #define HIS_HOT 2
72 #define HIS_PRESSED 3
4b94ddc4
RD
73
74 #define TMT_HEIGHT 2417
75
76 #define HP_HEADERSORTARROW 4
77 #define HSAS_SORTEDUP 1
78 #define HSAS_SORTEDDOWN 2
7cf3223a
VZ
79#endif
80
d6f2a891
VZ
81#if defined(__WXWINCE__)
82 #ifndef DFCS_FLAT
83 #define DFCS_FLAT 0
84 #endif
85 #ifndef DFCS_MONO
86 #define DFCS_MONO 0
87 #endif
9f93b45e
VZ
88#endif
89
59ee63e9
VZ
90#ifndef DFCS_HOT
91 #define DFCS_HOT 0x1000
92#endif
93
9c7f49f5 94// ----------------------------------------------------------------------------
8b97949e 95// wxRendererMSW: wxRendererNative implementation for "old" Win32 systems
9c7f49f5
VZ
96// ----------------------------------------------------------------------------
97
38c4cb6a 98class WXDLLEXPORT wxRendererMSW : public wxDelegateRendererNative
9c7f49f5 99{
2eb10e2a
VZ
100public:
101 wxRendererMSW() { }
102
8b97949e
VZ
103 static wxRendererNative& Get();
104
7402677a
VZ
105 virtual void DrawComboBoxDropButton(wxWindow *win,
106 wxDC& dc,
107 const wxRect& rect,
108 int flags = 0);
109
59ee63e9
VZ
110 virtual void DrawCheckBox(wxWindow *win,
111 wxDC& dc,
112 const wxRect& rect,
113 int flags = 0);
114
2209baae
RR
115 virtual void DrawPushButton(wxWindow *win,
116 wxDC& dc,
117 const wxRect& rect,
118 int flags = 0);
119
51c42fc5
VZ
120 virtual void DrawFocusRect(wxWindow* win,
121 wxDC& dc,
122 const wxRect& rect,
123 int flags = 0);
124
125 virtual int GetHeaderButtonHeight(wxWindow *win);
126
2eb10e2a
VZ
127private:
128 DECLARE_NO_COPY_CLASS(wxRendererMSW)
9c7f49f5
VZ
129};
130
8b97949e
VZ
131// ----------------------------------------------------------------------------
132// wxRendererXP: wxRendererNative implementation for Windows XP and later
133// ----------------------------------------------------------------------------
134
7cf3223a
VZ
135#if wxUSE_UXTHEME
136
8b97949e
VZ
137class WXDLLEXPORT wxRendererXP : public wxDelegateRendererNative
138{
139public:
140 wxRendererXP() : wxDelegateRendererNative(wxRendererMSW::Get()) { }
141
142 static wxRendererNative& Get();
143
c97c9952 144 virtual int DrawHeaderButton(wxWindow *win,
4b94ddc4
RD
145 wxDC& dc,
146 const wxRect& rect,
147 int flags = 0,
80752b57 148 wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
4b94ddc4 149 wxHeaderButtonParams* params = NULL);
f4322df6 150
9f93b45e
VZ
151 virtual void DrawTreeItemButton(wxWindow *win,
152 wxDC& dc,
153 const wxRect& rect,
154 int flags = 0);
8b97949e
VZ
155 virtual void DrawSplitterBorder(wxWindow *win,
156 wxDC& dc,
c4e6c15e
VZ
157 const wxRect& rect,
158 int flags = 0);
8b97949e
VZ
159 virtual void DrawSplitterSash(wxWindow *win,
160 wxDC& dc,
161 const wxSize& size,
162 wxCoord position,
c4e6c15e
VZ
163 wxOrientation orient,
164 int flags = 0);
7cf3223a
VZ
165 virtual void DrawComboBoxDropButton(wxWindow *win,
166 wxDC& dc,
167 const wxRect& rect,
168 int flags = 0);
90b903c2
WS
169 virtual void DrawCheckBox(wxWindow *win,
170 wxDC& dc,
171 const wxRect& rect,
172 int flags = 0);
9f93b45e 173
2209baae
RR
174 virtual void DrawPushButton(wxWindow *win,
175 wxDC& dc,
176 const wxRect& rect,
177 int flags = 0);
178
a9fdf824
RR
179 virtual void DrawItemSelectionRect(wxWindow *win,
180 wxDC& dc,
181 const wxRect& rect,
182 int flags = 0 );
183
184
9f93b45e 185 virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win);
8b97949e
VZ
186private:
187 DECLARE_NO_COPY_CLASS(wxRendererXP)
188};
189
7cf3223a
VZ
190#endif // wxUSE_UXTHEME
191
9c7f49f5 192// ============================================================================
8b97949e 193// wxRendererNative and wxRendererMSW implementation
9c7f49f5
VZ
194// ============================================================================
195
196/* static */
f0244295 197wxRendererNative& wxRendererNative::GetDefault()
8b97949e 198{
7cf3223a 199#if wxUSE_UXTHEME
8b97949e 200 wxUxThemeEngine *themeEngine = wxUxThemeEngine::Get();
7cf3223a
VZ
201 if ( themeEngine && themeEngine->IsAppThemed() )
202 return wxRendererXP::Get();
203#endif // wxUSE_UXTHEME
204
205 return wxRendererMSW::Get();
8b97949e
VZ
206}
207
208/* static */
209wxRendererNative& wxRendererMSW::Get()
9c7f49f5
VZ
210{
211 static wxRendererMSW s_rendererMSW;
212
213 return s_rendererMSW;
214}
215
7402677a
VZ
216void
217wxRendererMSW::DrawComboBoxDropButton(wxWindow * WXUNUSED(win),
218 wxDC& dc,
219 const wxRect& rect,
220 int flags)
221{
222 RECT r;
46bd1978 223 wxCopyRectToRECT(rect, r);
7402677a
VZ
224
225 int style = DFCS_SCROLLCOMBOBOX;
226 if ( flags & wxCONTROL_DISABLED )
227 style |= DFCS_INACTIVE;
228 if ( flags & wxCONTROL_PRESSED )
7cf3223a 229 style |= DFCS_PUSHED | DFCS_FLAT;
7402677a 230
888dde65 231 ::DrawFrameControl(GetHdcOf(*((wxMSWDCImpl*)dc.GetImpl())), &r, DFC_SCROLL, style);
7402677a
VZ
232}
233
59ee63e9
VZ
234void
235wxRendererMSW::DrawCheckBox(wxWindow * WXUNUSED(win),
236 wxDC& dc,
237 const wxRect& rect,
238 int flags)
239{
240 RECT r;
241 wxCopyRectToRECT(rect, r);
242
243 int style = DFCS_BUTTONCHECK;
244 if ( flags & wxCONTROL_CHECKED )
245 style |= DFCS_CHECKED;
246 if ( flags & wxCONTROL_DISABLED )
247 style |= DFCS_INACTIVE;
8a461249
VZ
248 if ( flags & wxCONTROL_FLAT )
249 style |= DFCS_MONO;
59ee63e9
VZ
250 if ( flags & wxCONTROL_PRESSED )
251 style |= DFCS_PUSHED;
252 if ( flags & wxCONTROL_CURRENT )
253 style |= DFCS_HOT;
254
888dde65 255 ::DrawFrameControl(GetHdcOf(*((wxMSWDCImpl*)dc.GetImpl())), &r, DFC_BUTTON, style);
59ee63e9
VZ
256}
257
2209baae
RR
258void
259wxRendererMSW::DrawPushButton(wxWindow * WXUNUSED(win),
260 wxDC& dc,
f2ea4255 261 const wxRect& rectOrig,
2209baae
RR
262 int flags)
263{
f2ea4255 264 wxRect rect(rectOrig);
2209baae
RR
265
266 int style = DFCS_BUTTONPUSH;
267 if ( flags & wxCONTROL_DISABLED )
268 style |= DFCS_INACTIVE;
269 if ( flags & wxCONTROL_PRESSED )
270 style |= DFCS_PUSHED | DFCS_FLAT;
f2ea4255
VZ
271 if ( flags & wxCONTROL_ISDEFAULT )
272 {
273 // DrawFrameControl() doesn't seem to support default buttons so we
274 // have to draw the border ourselves
275 wxDCPenChanger pen(dc, *wxBLACK_PEN);
276 wxDCBrushChanger brush(dc, *wxTRANSPARENT_BRUSH);
277 dc.DrawRectangle(rect);
844b9f5f 278 rect.Deflate(1);
f2ea4255
VZ
279 }
280
281 RECT rc;
282 wxCopyRectToRECT(rect, rc);
283
888dde65 284 ::DrawFrameControl(GetHdcOf(*((wxMSWDCImpl*)dc.GetImpl())), &rc, DFC_BUTTON, style);
2209baae
RR
285}
286
51c42fc5
VZ
287void wxRendererMSW::DrawFocusRect(wxWindow * WXUNUSED(win),
288 wxDC& dc,
289 const wxRect& rect,
290 int WXUNUSED(flags))
6d789987
JS
291{
292 RECT rc;
293 wxCopyRectToRECT(rect, rc);
294
888dde65 295 ::DrawFocusRect(GetHdcOf(*((wxMSWDCImpl*)dc.GetImpl())), &rc);
6d789987
JS
296}
297
51c42fc5
VZ
298int wxRendererMSW::GetHeaderButtonHeight(wxWindow * WXUNUSED(win))
299{
300 // some "reasonable" value returned in case of error, it doesn't really
301 // correspond to anything but it's better than returning 0
302 static const int DEFAULT_HEIGHT = 20;
303
304
305 // create a temporary header window just to get its geometry
a268f4b7 306 HWND hwndHeader = ::CreateWindow(WC_HEADER, NULL, 0,
51c42fc5
VZ
307 0, 0, 0, 0, NULL, NULL, NULL, NULL);
308 if ( !hwndHeader )
309 return DEFAULT_HEIGHT;
310
311 wxON_BLOCK_EXIT1( ::DestroyWindow, hwndHeader );
312
313 // initialize the struct filled with the values by Header_Layout()
314 RECT parentRect = { 0, 0, 100, 100 };
11fa6e63 315 WINDOWPOS wp = { 0, 0, 0, 0, 0, 0, 0 };
51c42fc5
VZ
316 HDLAYOUT hdl = { &parentRect, &wp };
317
318 return Header_Layout(hwndHeader, &hdl) ? wp.cy : DEFAULT_HEIGHT;
319}
320
8b97949e
VZ
321// ============================================================================
322// wxRendererXP implementation
323// ============================================================================
324
7cf3223a
VZ
325#if wxUSE_UXTHEME
326
8b97949e
VZ
327/* static */
328wxRendererNative& wxRendererXP::Get()
329{
330 static wxRendererXP s_rendererXP;
331
332 return s_rendererXP;
333}
334
7cf3223a
VZ
335// NOTE: There is no guarantee that the button drawn fills the entire rect (XP
336// default theme, for example), so the caller should have cleared button's
337// background before this call. This is quite likely a wxMSW-specific thing.
338void
339wxRendererXP::DrawComboBoxDropButton(wxWindow * win,
340 wxDC& dc,
341 const wxRect& rect,
342 int flags)
343{
344 wxUxThemeHandle hTheme(win, L"COMBOBOX");
9f93b45e 345 if ( !hTheme )
7cf3223a 346 {
9f93b45e
VZ
347 m_rendererNative.DrawComboBoxDropButton(win, dc, rect, flags);
348 return;
349 }
350
351 RECT r;
352 wxCopyRectToRECT(rect, r);
7cf3223a 353
9f93b45e
VZ
354 int state;
355 if ( flags & wxCONTROL_PRESSED )
356 state = CBXS_PRESSED;
357 else if ( flags & wxCONTROL_CURRENT )
358 state = CBXS_HOT;
359 else if ( flags & wxCONTROL_DISABLED )
360 state = CBXS_DISABLED;
361 else
362 state = CBXS_NORMAL;
363
364 wxUxThemeEngine::Get()->DrawThemeBackground
365 (
366 hTheme,
888dde65 367 GetHdcOf(*((wxMSWDCImpl*)dc.GetImpl())),
9f93b45e
VZ
368 CP_DROPDOWNBUTTON,
369 state,
370 &r,
371 NULL
372 );
373
374}
375
c97c9952 376int
9f93b45e
VZ
377wxRendererXP::DrawHeaderButton(wxWindow *win,
378 wxDC& dc,
379 const wxRect& rect,
4b94ddc4 380 int flags,
80752b57 381 wxHeaderSortIconType sortArrow,
4b94ddc4 382 wxHeaderButtonParams* params)
9f93b45e
VZ
383{
384 wxUxThemeHandle hTheme(win, L"HEADER");
385 if ( !hTheme )
386 {
c97c9952 387 return m_rendererNative.DrawHeaderButton(win, dc, rect, flags, sortArrow, params);
7cf3223a 388 }
9f93b45e
VZ
389
390 RECT r;
391 wxCopyRectToRECT(rect, r);
392
393 int state;
394 if ( flags & wxCONTROL_PRESSED )
395 state = HIS_PRESSED;
396 else if ( flags & wxCONTROL_CURRENT )
397 state = HIS_HOT;
398 else
399 state = HIS_NORMAL;
400 wxUxThemeEngine::Get()->DrawThemeBackground
401 (
402 hTheme,
888dde65 403 GetHdcOf(*((wxMSWDCImpl*)dc.GetImpl())),
9f93b45e
VZ
404 HP_HEADERITEM,
405 state,
406 &r,
407 NULL
408 );
4b94ddc4
RD
409
410 // NOTE: Using the theme to draw HP_HEADERSORTARROW doesn't do anything.
411 // Why? If this can be fixed then draw the sort arrows using the theme
412 // and then clear those flags before calling DrawHeaderButtonContents.
f4322df6 413
4b94ddc4 414 // Add any extras that are specified in flags and params
c97c9952 415 return DrawHeaderButtonContents(win, dc, rect, flags, sortArrow, params);
9f93b45e
VZ
416}
417
4b94ddc4 418
9f93b45e
VZ
419void
420wxRendererXP::DrawTreeItemButton(wxWindow *win,
421 wxDC& dc,
422 const wxRect& rect,
423 int flags)
424{
425 wxUxThemeHandle hTheme(win, L"TREEVIEW");
426 if ( !hTheme )
427 {
428 m_rendererNative.DrawTreeItemButton(win, dc, rect, flags);
429 return;
430 }
431
432 RECT r;
433 wxCopyRectToRECT(rect, r);
434
435 int state = flags & wxCONTROL_EXPANDED ? GLPS_OPENED : GLPS_CLOSED;
436 wxUxThemeEngine::Get()->DrawThemeBackground
437 (
438 hTheme,
888dde65 439 GetHdcOf(*((wxMSWDCImpl*)dc.GetImpl())),
9f93b45e
VZ
440 TVP_GLYPH,
441 state,
442 &r,
443 NULL
444 );
445}
446
447void
90b903c2
WS
448wxRendererXP::DrawCheckBox(wxWindow *win,
449 wxDC& dc,
450 const wxRect& rect,
451 int flags)
9f93b45e
VZ
452{
453 wxUxThemeHandle hTheme(win, L"BUTTON");
454 if ( !hTheme )
455 {
90b903c2 456 m_rendererNative.DrawCheckBox(win, dc, rect, flags);
9f93b45e
VZ
457 return;
458 }
459
460 RECT r;
461 wxCopyRectToRECT(rect, r);
462
463 int state;
464 if ( flags & wxCONTROL_CHECKED )
465 state = CBS_CHECKEDNORMAL;
466 else if ( flags & wxCONTROL_UNDETERMINED )
467 state = CBS_MIXEDNORMAL;
468 else
469 state = CBS_UNCHECKEDNORMAL;
470
59ee63e9
VZ
471 // CBS_XXX is followed by CBX_XXXHOT, then CBS_XXXPRESSED and DISABLED
472 enum
473 {
474 CBS_HOT_OFFSET = 1,
475 CBS_PRESSED_OFFSET = 2,
476 CBS_DISABLED_OFFSET = 3
477 };
478
479 if ( flags & wxCONTROL_DISABLED )
480 state += CBS_DISABLED_OFFSET;
9f93b45e 481 else if ( flags & wxCONTROL_PRESSED )
59ee63e9
VZ
482 state += CBS_PRESSED_OFFSET;
483 else if ( flags & wxCONTROL_CURRENT )
484 state += CBS_HOT_OFFSET;
9f93b45e
VZ
485
486 wxUxThemeEngine::Get()->DrawThemeBackground
487 (
488 hTheme,
888dde65 489 GetHdcOf(*((wxMSWDCImpl*)dc.GetImpl())),
9f93b45e
VZ
490 BP_CHECKBOX,
491 state,
492 &r,
493 NULL
494 );
7cf3223a
VZ
495}
496
2209baae
RR
497void
498wxRendererXP::DrawPushButton(wxWindow * win,
499 wxDC& dc,
500 const wxRect& rect,
501 int flags)
502{
503 wxUxThemeHandle hTheme(win, L"BUTTON");
504 if ( !hTheme )
505 {
506 m_rendererNative.DrawPushButton(win, dc, rect, flags);
507 return;
508 }
509
510 RECT r;
511 wxCopyRectToRECT(rect, r);
512
513 int state;
514 if ( flags & wxCONTROL_PRESSED )
515 state = PBS_PRESSED;
516 else if ( flags & wxCONTROL_CURRENT )
517 state = PBS_HOT;
518 else if ( flags & wxCONTROL_DISABLED )
519 state = PBS_DISABLED;
520 else if ( flags & wxCONTROL_ISDEFAULT )
521 state = PBS_DEFAULTED;
522 else
523 state = PBS_NORMAL;
524
525 wxUxThemeEngine::Get()->DrawThemeBackground
526 (
527 hTheme,
888dde65 528 GetHdcOf(*((wxMSWDCImpl*)dc.GetImpl())),
2209baae
RR
529 BP_PUSHBUTTON,
530 state,
531 &r,
532 NULL
533 );
534
535}
536
a9fdf824 537void
ce0cf2b8 538wxRendererXP::DrawItemSelectionRect(wxWindow *win,
a9fdf824
RR
539 wxDC& dc,
540 const wxRect& rect,
541 int flags)
542{
543 wxBrush brush;
544 if ( flags & wxCONTROL_SELECTED )
545 {
546 if ( flags & wxCONTROL_FOCUSED )
547 {
548 brush = wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT));
549 }
550 else // !focused
551 {
4cda739c 552 brush = wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
a9fdf824
RR
553 }
554 }
555 else // !selected
556 {
557 brush = *wxTRANSPARENT_BRUSH;
558 }
559
560 dc.SetBrush(brush);
a9fdf824 561 dc.SetPen(*wxTRANSPARENT_PEN);
a9fdf824 562 dc.DrawRectangle( rect );
ce0cf2b8
RR
563
564 if ((flags & wxCONTROL_FOCUSED) && (flags & wxCONTROL_CURRENT))
565 DrawFocusRect( win, dc, rect, flags );
a9fdf824
RR
566}
567
568
569
8b97949e
VZ
570// ----------------------------------------------------------------------------
571// splitter drawing
572// ----------------------------------------------------------------------------
573
574// the width of the sash: this is the same as used by Explorer...
575static const wxCoord SASH_WIDTH = 4;
576
c4e6c15e 577wxSplitterRenderParams
3c2544bb 578wxRendererXP::GetSplitterParams(const wxWindow * win)
8b97949e 579{
9f93b45e 580 if ( win->HasFlag(wxSP_NO_XP_THEME) )
3c2544bb
JS
581 return m_rendererNative.GetSplitterParams(win);
582 else
583 return wxSplitterRenderParams(SASH_WIDTH, 0, false);
8b97949e
VZ
584}
585
586void
3c2544bb
JS
587wxRendererXP::DrawSplitterBorder(wxWindow * win,
588 wxDC& dc,
589 const wxRect& rect,
590 int flags)
8b97949e 591{
9f93b45e 592 if ( win->HasFlag(wxSP_NO_XP_THEME) )
3c2544bb
JS
593 {
594 m_rendererNative.DrawSplitterBorder(win, dc, rect, flags);
595 }
8b97949e
VZ
596}
597
598void
599wxRendererXP::DrawSplitterSash(wxWindow *win,
600 wxDC& dc,
601 const wxSize& size,
602 wxCoord position,
c4e6c15e 603 wxOrientation orient,
3c2544bb 604 int flags)
8b97949e 605{
6421119d 606 if ( !win->HasFlag(wxSP_NO_XP_THEME) )
8b97949e 607 {
fe404d1a
JS
608 dc.SetPen(*wxTRANSPARENT_PEN);
609 dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)));
610 if ( orient == wxVERTICAL )
8b97949e 611 {
fe404d1a 612 dc.DrawRectangle(position, 0, SASH_WIDTH, size.y);
8b97949e 613 }
fe404d1a
JS
614 else // wxHORIZONTAL
615 {
616 dc.DrawRectangle(0, position, size.x, SASH_WIDTH);
617 }
618
619 return;
8b97949e 620 }
6421119d
VZ
621
622 m_rendererNative.DrawSplitterSash(win, dc, size, position, orient, flags);
8b97949e
VZ
623}
624
7cf3223a 625#endif // wxUSE_UXTHEME