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