1 // Name: univ/themes/win32.cpp
2 // Purpose: wxUniversal theme implementing Win32-like LNF
3 // Author: Vadim Zeitlin
7 // Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
8 // Licence: wxWindows license
9 ///////////////////////////////////////////////////////////////////////////////
11 // ===========================================================================
13 // ===========================================================================
15 // ---------------------------------------------------------------------------
17 // ---------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
30 #include "wx/window.h"
32 #include "wx/dcmemory.h"
34 #include "wx/button.h"
35 #include "wx/listbox.h"
36 #include "wx/checklst.h"
37 #include "wx/combobox.h"
38 #include "wx/scrolbar.h"
39 #include "wx/slider.h"
40 #include "wx/textctrl.h"
43 // for COLOR_* constants
44 #include "wx/msw/private.h"
48 #include "wx/notebook.h"
49 #include "wx/spinbutt.h"
50 #include "wx/settings.h"
53 #include "wx/univ/scrtimer.h"
55 #include "wx/univ/renderer.h"
56 #include "wx/univ/inphand.h"
57 #include "wx/univ/colschem.h"
58 #include "wx/univ/theme.h"
60 // ----------------------------------------------------------------------------
62 // ----------------------------------------------------------------------------
64 static const int BORDER_THICKNESS
= 2;
66 // the offset between the label and focus rect around it
67 static const int FOCUS_RECT_OFFSET_X
= 1;
68 static const int FOCUS_RECT_OFFSET_Y
= 1;
80 IndicatorState_Normal
,
81 IndicatorState_Pressed
, // this one is for check/radioboxes
82 IndicatorState_Selected
= IndicatorState_Pressed
, // for menus
83 IndicatorState_Disabled
,
84 IndicatorState_SelectedDisabled
, // only for the menus
90 IndicatorStatus_Checked
,
91 IndicatorStatus_Unchecked
,
95 // wxWin32Renderer: draw the GUI elements in Win32 style
96 // ----------------------------------------------------------------------------
98 class wxWin32Renderer
: public wxRenderer
102 enum wxArrowDirection
117 Arrow_InversedDisabled
,
122 wxWin32Renderer(const wxColourScheme
*scheme
);
124 // implement the base class pure virtuals
125 virtual void DrawBackground(wxDC
& dc
,
129 virtual void DrawLabel(wxDC
& dc
,
130 const wxString
& label
,
133 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
135 wxRect
*rectBounds
= NULL
);
136 virtual void DrawButtonLabel(wxDC
& dc
,
137 const wxString
& label
,
138 const wxBitmap
& image
,
141 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
143 wxRect
*rectBounds
= NULL
);
144 virtual void DrawBorder(wxDC
& dc
,
148 wxRect
*rectIn
= (wxRect
*)NULL
);
149 virtual void DrawHorizontalLine(wxDC
& dc
,
150 wxCoord y
, wxCoord x1
, wxCoord x2
);
151 virtual void DrawVerticalLine(wxDC
& dc
,
152 wxCoord x
, wxCoord y1
, wxCoord y2
);
153 virtual void DrawFrame(wxDC
& dc
,
154 const wxString
& label
,
157 int alignment
= wxALIGN_LEFT
,
158 int indexAccel
= -1);
159 virtual void DrawTextBorder(wxDC
& dc
,
163 wxRect
*rectIn
= (wxRect
*)NULL
);
164 virtual void DrawButtonBorder(wxDC
& dc
,
167 wxRect
*rectIn
= (wxRect
*)NULL
);
168 virtual void DrawArrow(wxDC
& dc
,
172 virtual void DrawScrollbarArrow(wxDC
& dc
,
176 { DrawArrow(dc
, dir
, rect
, flags
); }
177 virtual void DrawScrollbarThumb(wxDC
& dc
,
178 wxOrientation orient
,
181 virtual void DrawScrollbarShaft(wxDC
& dc
,
182 wxOrientation orient
,
185 virtual void DrawScrollCorner(wxDC
& dc
,
187 virtual void DrawItem(wxDC
& dc
,
188 const wxString
& label
,
191 virtual void DrawCheckItem(wxDC
& dc
,
192 const wxString
& label
,
193 const wxBitmap
& bitmap
,
196 virtual void DrawCheckButton(wxDC
& dc
,
197 const wxString
& label
,
198 const wxBitmap
& bitmap
,
201 wxAlignment align
= wxALIGN_LEFT
,
202 int indexAccel
= -1);
203 virtual void DrawRadioButton(wxDC
& dc
,
204 const wxString
& label
,
205 const wxBitmap
& bitmap
,
208 wxAlignment align
= wxALIGN_LEFT
,
209 int indexAccel
= -1);
210 virtual void DrawTextLine(wxDC
& dc
,
211 const wxString
& text
,
216 virtual void DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
);
217 virtual void DrawTab(wxDC
& dc
,
220 const wxString
& label
,
221 const wxBitmap
& bitmap
= wxNullBitmap
,
223 int indexAccel
= -1);
225 virtual void DrawSliderShaft(wxDC
& dc
,
227 wxOrientation orient
,
229 wxRect
*rectShaft
= NULL
);
230 virtual void DrawSliderThumb(wxDC
& dc
,
232 wxOrientation orient
,
234 virtual void DrawSliderTicks(wxDC
& dc
,
236 const wxSize
& sizeThumb
,
237 wxOrientation orient
,
244 virtual void DrawMenuBarItem(wxDC
& dc
,
246 const wxString
& label
,
248 int indexAccel
= -1);
249 virtual void DrawMenuItem(wxDC
& dc
,
251 const wxMenuGeometryInfo
& geometryInfo
,
252 const wxString
& label
,
253 const wxString
& accel
,
254 const wxBitmap
& bitmap
= wxNullBitmap
,
256 int indexAccel
= -1);
257 virtual void DrawMenuSeparator(wxDC
& dc
,
259 const wxMenuGeometryInfo
& geomInfo
);
261 virtual void GetComboBitmaps(wxBitmap
*bmpNormal
,
263 wxBitmap
*bmpPressed
,
264 wxBitmap
*bmpDisabled
);
266 virtual void AdjustSize(wxSize
*size
, const wxWindow
*window
);
267 virtual wxRect
GetBorderDimensions(wxBorder border
) const;
268 virtual bool AreScrollbarsInsideBorder() const;
270 virtual wxSize
GetScrollbarArrowSize() const
271 { return m_sizeScrollbarArrow
; }
272 virtual wxRect
GetScrollbarRect(const wxScrollBar
*scrollbar
,
273 wxScrollBar::Element elem
,
274 int thumbPos
= -1) const;
275 virtual wxCoord
GetScrollbarSize(const wxScrollBar
*scrollbar
);
276 virtual wxHitTest
HitTestScrollbar(const wxScrollBar
*scrollbar
,
277 const wxPoint
& pt
) const;
278 virtual wxCoord
ScrollbarToPixel(const wxScrollBar
*scrollbar
,
280 virtual int PixelToScrollbar(const wxScrollBar
*scrollbar
, wxCoord coord
);
281 virtual wxCoord
GetListboxItemHeight(wxCoord fontHeight
)
282 { return fontHeight
+ 2; }
283 virtual wxSize
GetCheckBitmapSize() const
284 { return wxSize(13, 13); }
285 virtual wxSize
GetRadioBitmapSize() const
286 { return wxSize(12, 12); }
287 virtual wxCoord
GetCheckItemMargin() const
290 virtual wxRect
GetTextTotalArea(const wxTextCtrl
*text
,
292 virtual wxRect
GetTextClientArea(const wxTextCtrl
*text
,
294 wxCoord
*extraSpaceBeyond
);
296 virtual wxSize
GetTabIndent() const { return wxSize(2, 2); }
297 virtual wxSize
GetTabPadding() const { return wxSize(6, 5); }
299 virtual wxCoord
GetSliderDim() const { return 20; }
300 virtual wxCoord
GetSliderTickLen() const { return 4; }
301 virtual wxRect
GetSliderShaftRect(const wxRect
& rect
,
302 wxOrientation orient
) const;
303 virtual wxSize
GetSliderThumbSize(const wxRect
& rect
,
304 wxOrientation orient
) const;
305 virtual wxSize
GetProgressBarStep() const { return wxSize(16, 32); }
308 virtual wxSize
GetMenuBarItemSize(const wxSize
& sizeText
) const;
309 virtual wxMenuGeometryInfo
*GetMenuGeometry(wxWindow
*win
,
310 const wxMenu
& menu
) const;
313 // helper of DrawLabel() and DrawCheckOrRadioButton()
314 void DoDrawLabel(wxDC
& dc
,
315 const wxString
& label
,
318 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
320 wxRect
*rectBounds
= NULL
,
321 const wxPoint
& focusOffset
322 = wxPoint(FOCUS_RECT_OFFSET_X
, FOCUS_RECT_OFFSET_Y
));
324 // common part of DrawLabel() and DrawItem()
325 void DrawFocusRect(wxDC
& dc
, const wxRect
& rect
);
327 // DrawLabel() and DrawButtonLabel() helper
328 void DrawLabelShadow(wxDC
& dc
,
329 const wxString
& label
,
334 // DrawButtonBorder() helper
335 void DoDrawBackground(wxDC
& dc
,
339 // DrawBorder() helpers: all of them shift and clip the DC after drawing
342 // just draw a rectangle with the given pen
343 void DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
345 // draw the lower left part of rectangle
346 void DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
348 // draw the rectange using the first brush for the left and top sides and
349 // the second one for the bottom and right ones
350 void DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
351 const wxPen
& pen1
, const wxPen
& pen2
);
353 // draw the normal 3D border
354 void DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
);
356 // draw the sunken 3D border
357 void DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
);
359 // draw the border used for scrollbar arrows
360 void DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
= FALSE
);
362 // public DrawArrow()s helper
363 void DrawArrow(wxDC
& dc
, const wxRect
& rect
,
364 wxArrowDirection arrowDir
, wxArrowStyle arrowStyle
);
366 // DrawArrowButton is used by DrawScrollbar and DrawComboButton
367 void DrawArrowButton(wxDC
& dc
, const wxRect
& rect
,
368 wxArrowDirection arrowDir
,
369 wxArrowStyle arrowStyle
);
371 // DrawCheckButton/DrawRadioButton helper
372 void DrawCheckOrRadioButton(wxDC
& dc
,
373 const wxString
& label
,
374 const wxBitmap
& bitmap
,
379 wxCoord focusOffsetY
);
381 // draw a normal or transposed line (useful for using the same code fo both
382 // horizontal and vertical widgets)
383 void DrawLine(wxDC
& dc
,
384 wxCoord x1
, wxCoord y1
,
385 wxCoord x2
, wxCoord y2
,
386 bool transpose
= FALSE
)
389 dc
.DrawLine(y1
, x1
, y2
, x2
);
391 dc
.DrawLine(x1
, y1
, x2
, y2
);
394 // get the standard check/radio button bitmap
395 wxBitmap
GetIndicator(IndicatorType indType
, int flags
);
396 wxBitmap
GetCheckBitmap(int flags
)
397 { return GetIndicator(IndicatorType_Check
, flags
); }
398 wxBitmap
GetRadioBitmap(int flags
)
399 { return GetIndicator(IndicatorType_Radio
, flags
); }
402 const wxColourScheme
*m_scheme
;
404 // the sizing parameters (TODO make them changeable)
405 wxSize m_sizeScrollbarArrow
;
407 // GDI objects we use for drawing
408 wxColour m_colDarkGrey
,
416 // first row is for the normal state, second - for the disabled
417 wxBitmap m_bmpArrows
[Arrow_StateMax
][Arrow_Max
];
420 // ----------------------------------------------------------------------------
421 // wxWin32InputHandler and derived classes: process the keyboard and mouse
422 // messages according to Windows standards
423 // ----------------------------------------------------------------------------
425 class wxWin32InputHandler
: public wxInputHandler
428 wxWin32InputHandler(wxWin32Renderer
*renderer
);
430 virtual bool HandleKey(wxControl
*control
,
431 const wxKeyEvent
& event
,
433 virtual bool HandleMouse(wxControl
*control
,
434 const wxMouseEvent
& event
);
437 wxWin32Renderer
*m_renderer
;
440 class wxWin32ScrollBarInputHandler
: public wxStdScrollBarInputHandler
443 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
444 wxInputHandler
*handler
);
446 virtual bool HandleMouse(wxControl
*control
, const wxMouseEvent
& event
);
447 virtual bool HandleMouseMove(wxControl
*control
, const wxMouseEvent
& event
);
449 virtual bool OnScrollTimer(wxScrollBar
*scrollbar
,
450 const wxControlAction
& action
);
453 virtual bool IsAllowedButton(int button
) { return button
== 1; }
455 virtual void Highlight(wxScrollBar
*scrollbar
, bool doIt
)
457 // we don't highlight anything
460 // the first and last event which caused the thumb to move
461 wxMouseEvent m_eventStartDrag
,
464 // have we paused the scrolling because the mouse moved?
467 // we remember the interval of the timer to be able to restart it
471 class wxWin32CheckboxInputHandler
: public wxStdCheckboxInputHandler
474 wxWin32CheckboxInputHandler(wxInputHandler
*handler
)
475 : wxStdCheckboxInputHandler(handler
) { }
477 virtual bool HandleKey(wxControl
*control
,
478 const wxKeyEvent
& event
,
482 class wxWin32TextCtrlInputHandler
: public wxStdTextCtrlInputHandler
485 wxWin32TextCtrlInputHandler(wxInputHandler
*handler
)
486 : wxStdTextCtrlInputHandler(handler
) { }
488 virtual bool HandleKey(wxControl
*control
,
489 const wxKeyEvent
& event
,
493 // ----------------------------------------------------------------------------
494 // wxWin32ColourScheme: uses (default) Win32 colours
495 // ----------------------------------------------------------------------------
497 class wxWin32ColourScheme
: public wxColourScheme
500 virtual wxColour
Get(StdColour col
) const;
501 virtual wxColour
GetBackground(wxWindow
*win
) const;
504 // ----------------------------------------------------------------------------
506 // ----------------------------------------------------------------------------
508 WX_DEFINE_ARRAY(wxInputHandler
*, wxArrayHandlers
);
510 class wxWin32Theme
: public wxTheme
514 virtual ~wxWin32Theme();
516 virtual wxRenderer
*GetRenderer() { return m_renderer
; }
517 virtual wxInputHandler
*GetInputHandler(const wxString
& control
);
518 virtual wxColourScheme
*GetColourScheme();
521 // get the default input handler
522 wxInputHandler
*GetDefaultInputHandler();
524 wxWin32Renderer
*m_renderer
;
526 // the names of the already created handlers and the handlers themselves
527 // (these arrays are synchronized)
528 wxSortedArrayString m_handlerNames
;
529 wxArrayHandlers m_handlers
;
531 wxWin32InputHandler
*m_handlerDefault
;
533 wxWin32ColourScheme
*m_scheme
;
535 WX_DECLARE_THEME(win32
)
538 // ----------------------------------------------------------------------------
540 // ----------------------------------------------------------------------------
544 static const char *checked_menu_xpm
[] = {
545 /* columns rows colors chars-per-pixel */
561 static const char *selected_checked_menu_xpm
[] = {
562 /* columns rows colors chars-per-pixel */
578 static const char *disabled_checked_menu_xpm
[] = {
579 /* columns rows colors chars-per-pixel */
596 static const char *selected_disabled_checked_menu_xpm
[] = {
597 /* columns rows colors chars-per-pixel */
613 // checkbox and radiobox bitmaps below
615 static const char *checked_xpm
[] = {
616 /* columns rows colors chars-per-pixel */
639 static const char *pressed_checked_xpm
[] = {
640 /* columns rows colors chars-per-pixel */
662 static const char *pressed_disabled_checked_xpm
[] = {
663 /* columns rows colors chars-per-pixel */
685 static const char *checked_item_xpm
[] = {
686 /* columns rows colors chars-per-pixel */
707 static const char *unchecked_xpm
[] = {
708 /* columns rows colors chars-per-pixel */
731 static const char *pressed_unchecked_xpm
[] = {
732 /* columns rows colors chars-per-pixel */
754 static const char *unchecked_item_xpm
[] = {
755 /* columns rows colors chars-per-pixel */
775 static const char *checked_radio_xpm
[] = {
776 /* columns rows colors chars-per-pixel */
799 static const char *pressed_checked_radio_xpm
[] = {
800 /* columns rows colors chars-per-pixel */
823 static const char *pressed_disabled_checked_radio_xpm
[] = {
824 /* columns rows colors chars-per-pixel */
847 static const char *unchecked_radio_xpm
[] = {
848 /* columns rows colors chars-per-pixel */
871 static const char *pressed_unchecked_radio_xpm
[] = {
872 /* columns rows colors chars-per-pixel */
896 bmpIndicators
[IndicatorType_Max
][IndicatorState_Max
][IndicatorStatus_Max
] =
901 { checked_xpm
, unchecked_xpm
},
904 { pressed_checked_xpm
, pressed_unchecked_xpm
},
907 { pressed_disabled_checked_xpm
, pressed_unchecked_xpm
},
913 { checked_radio_xpm
, unchecked_radio_xpm
},
916 { pressed_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
919 { pressed_disabled_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
925 { checked_menu_xpm
, NULL
},
928 { selected_checked_menu_xpm
, NULL
},
931 { disabled_checked_menu_xpm
, NULL
},
933 // disabled selected state
934 { selected_disabled_checked_menu_xpm
, NULL
},
938 // ============================================================================
940 // ============================================================================
942 WX_IMPLEMENT_THEME(wxWin32Theme
, win32
, wxTRANSLATE("Win32 theme"));
944 // ----------------------------------------------------------------------------
946 // ----------------------------------------------------------------------------
948 wxWin32Theme::wxWin32Theme()
950 m_scheme
= new wxWin32ColourScheme
;
951 m_renderer
= new wxWin32Renderer(m_scheme
);
952 m_handlerDefault
= NULL
;
955 wxWin32Theme::~wxWin32Theme()
957 size_t count
= m_handlers
.GetCount();
958 for ( size_t n
= 0; n
< count
; n
++ )
960 if ( m_handlers
[n
] != m_handlerDefault
)
961 delete m_handlers
[n
];
964 delete m_handlerDefault
;
970 wxInputHandler
*wxWin32Theme::GetDefaultInputHandler()
972 if ( !m_handlerDefault
)
974 m_handlerDefault
= new wxWin32InputHandler(m_renderer
);
977 return m_handlerDefault
;
980 wxInputHandler
*wxWin32Theme::GetInputHandler(const wxString
& control
)
982 wxInputHandler
*handler
;
983 int n
= m_handlerNames
.Index(control
);
984 if ( n
== wxNOT_FOUND
)
986 // create a new handler
987 if ( control
== wxINP_HANDLER_SCROLLBAR
)
988 handler
= new wxWin32ScrollBarInputHandler(m_renderer
,
989 GetDefaultInputHandler());
991 else if ( control
== wxINP_HANDLER_BUTTON
)
992 handler
= new wxStdButtonInputHandler(GetDefaultInputHandler());
993 #endif // wxUSE_BUTTON
995 else if ( control
== wxINP_HANDLER_CHECKBOX
)
996 handler
= new wxWin32CheckboxInputHandler(GetDefaultInputHandler());
997 #endif // wxUSE_CHECKBOX
999 else if ( control
== wxINP_HANDLER_COMBOBOX
)
1000 handler
= new wxStdComboBoxInputHandler(GetDefaultInputHandler());
1001 #endif // wxUSE_COMBOBOX
1003 else if ( control
== wxINP_HANDLER_LISTBOX
)
1004 handler
= new wxStdListboxInputHandler(GetDefaultInputHandler());
1005 #endif // wxUSE_LISTBOX
1006 #if wxUSE_CHECKLISTBOX
1007 else if ( control
== wxINP_HANDLER_CHECKLISTBOX
)
1008 handler
= new wxStdCheckListboxInputHandler(GetDefaultInputHandler());
1009 #endif // wxUSE_CHECKLISTBOX
1011 else if ( control
== wxINP_HANDLER_TEXTCTRL
)
1012 handler
= new wxWin32TextCtrlInputHandler(GetDefaultInputHandler());
1013 #endif // wxUSE_TEXTCTRL
1015 else if ( control
== wxINP_HANDLER_SLIDER
)
1016 handler
= new wxStdSliderButtonInputHandler(GetDefaultInputHandler());
1017 #endif // wxUSE_SLIDER
1019 else if ( control
== wxINP_HANDLER_SPINBTN
)
1020 handler
= new wxStdSpinButtonInputHandler(GetDefaultInputHandler());
1021 #endif // wxUSE_SPINBTN
1023 else if ( control
== wxINP_HANDLER_NOTEBOOK
)
1024 handler
= new wxStdNotebookInputHandler(GetDefaultInputHandler());
1025 #endif // wxUSE_NOTEBOOK
1027 handler
= GetDefaultInputHandler();
1029 n
= m_handlerNames
.Add(control
);
1030 m_handlers
.Insert(handler
, n
);
1032 else // we already have it
1034 handler
= m_handlers
[n
];
1040 wxColourScheme
*wxWin32Theme::GetColourScheme()
1045 // ============================================================================
1046 // wxWin32ColourScheme
1047 // ============================================================================
1049 wxColour
wxWin32ColourScheme::GetBackground(wxWindow
*win
) const
1052 if ( win
->UseBgCol() )
1054 // use the user specified colour
1055 col
= win
->GetBackgroundColour();
1058 if ( win
->IsContainerWindow() )
1060 wxTextCtrl
*text
= wxDynamicCast(win
, wxTextCtrl
);
1063 if ( !text
->IsEnabled() ) // not IsEditable()
1065 //else: execute code below
1070 // doesn't depend on the state
1076 int flags
= win
->GetStateFlags();
1078 // the colour set by the user should be used for the normal state
1079 // and for the states for which we don't have any specific colours
1080 if ( !col
.Ok() || (flags
!= 0) )
1082 if ( wxDynamicCast(win
, wxScrollBar
) )
1083 col
= Get(flags
& wxCONTROL_PRESSED
? SCROLLBAR_PRESSED
1093 wxColour
wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col
) const
1097 // use the system colours under Windows
1098 #if defined(__WXMSW__)
1099 case WINDOW
: return wxColour(GetSysColor(COLOR_WINDOW
));
1101 case CONTROL_PRESSED
:
1102 case CONTROL_CURRENT
:
1103 case CONTROL
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1105 case CONTROL_TEXT
: return wxColour(GetSysColor(COLOR_BTNTEXT
));
1107 case SCROLLBAR
: return wxColour(GetSysColor(COLOR_SCROLLBAR
));
1108 case SCROLLBAR_PRESSED
: return wxColour(GetSysColor(COLOR_HIGHLIGHT
));
1110 case HIGHLIGHT
: return wxColour(GetSysColor(COLOR_HIGHLIGHT
));
1111 case HIGHLIGHT_TEXT
: return wxColour(GetSysColor(COLOR_HIGHLIGHTTEXT
));
1113 #if defined(COLOR_3DDKSHADOW)
1114 case SHADOW_DARK
: return wxColour(GetSysColor(COLOR_3DDKSHADOW
));
1116 case SHADOW_DARK
: return *wxBLACK
;
1119 case CONTROL_TEXT_DISABLED
:
1120 case SHADOW_HIGHLIGHT
: return wxColour(GetSysColor(COLOR_BTNHIGHLIGHT
));
1122 case SHADOW_IN
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1124 case CONTROL_TEXT_DISABLED_SHADOW
:
1125 case SHADOW_OUT
: return wxColour(GetSysColor(COLOR_BTNSHADOW
));
1127 // use the standard Windows colours elsewhere
1128 case WINDOW
: return *wxWHITE
;
1130 case CONTROL_PRESSED
:
1131 case CONTROL_CURRENT
:
1132 case CONTROL
: return wxColour(0xc0c0c0);
1134 case CONTROL_TEXT
: return *wxBLACK
;
1136 case SCROLLBAR
: return wxColour(0xe0e0e0);
1137 case SCROLLBAR_PRESSED
: return *wxBLACK
;
1139 case HIGHLIGHT
: return wxColour(0x800000);
1140 case HIGHLIGHT_TEXT
: return wxColour(0xffffff);
1142 case SHADOW_DARK
: return *wxBLACK
;
1144 case CONTROL_TEXT_DISABLED
:
1145 case SHADOW_HIGHLIGHT
: return wxColour(0xe0e0e0);
1147 case SHADOW_IN
: return wxColour(0xc0c0c0);
1149 case CONTROL_TEXT_DISABLED_SHADOW
:
1150 case SHADOW_OUT
: return wxColour(0x7f7f7f);
1155 wxFAIL_MSG(_T("invalid standard colour"));
1160 // ============================================================================
1162 // ============================================================================
1164 // ----------------------------------------------------------------------------
1166 // ----------------------------------------------------------------------------
1168 wxWin32Renderer::wxWin32Renderer(const wxColourScheme
*scheme
)
1172 m_sizeScrollbarArrow
= wxSize(16, 16);
1174 // init colours and pens
1175 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
), 0, wxSOLID
);
1177 m_colDarkGrey
= wxSCHEME_COLOUR(scheme
, SHADOW_OUT
);
1178 m_penDarkGrey
= wxPen(m_colDarkGrey
, 0, wxSOLID
);
1180 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
), 0, wxSOLID
);
1182 m_colHighlight
= wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
);
1183 m_penHighlight
= wxPen(m_colHighlight
, 0, wxSOLID
);
1185 // init the arrow bitmaps
1186 static const size_t ARROW_WIDTH
= 7;
1187 static const size_t ARROW_LENGTH
= 4;
1190 wxMemoryDC dcNormal
,
1193 for ( size_t n
= 0; n
< Arrow_Max
; n
++ )
1195 bool isVertical
= n
> Arrow_Right
;
1208 // disabled arrow is larger because of the shadow
1209 m_bmpArrows
[Arrow_Normal
][n
].Create(w
, h
);
1210 m_bmpArrows
[Arrow_Disabled
][n
].Create(w
+ 1, h
+ 1);
1212 dcNormal
.SelectObject(m_bmpArrows
[Arrow_Normal
][n
]);
1213 dcDisabled
.SelectObject(m_bmpArrows
[Arrow_Disabled
][n
]);
1215 dcNormal
.SetBackground(*wxWHITE_BRUSH
);
1216 dcDisabled
.SetBackground(*wxWHITE_BRUSH
);
1220 dcNormal
.SetPen(m_penBlack
);
1221 dcDisabled
.SetPen(m_penDarkGrey
);
1223 // calculate the position of the point of the arrow
1227 x1
= (ARROW_WIDTH
- 1)/2;
1228 y1
= n
== Arrow_Up
? 0 : ARROW_LENGTH
- 1;
1232 x1
= n
== Arrow_Left
? 0 : ARROW_LENGTH
- 1;
1233 y1
= (ARROW_WIDTH
- 1)/2;
1244 for ( size_t i
= 0; i
< ARROW_LENGTH
; i
++ )
1246 dcNormal
.DrawLine(x1
, y1
, x2
, y2
);
1247 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1254 if ( n
== Arrow_Up
)
1265 else // left or right arrow
1270 if ( n
== Arrow_Left
)
1283 // draw the shadow for the disabled one
1284 dcDisabled
.SetPen(m_penHighlight
);
1289 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1293 x1
= ARROW_LENGTH
- 1;
1294 y1
= (ARROW_WIDTH
- 1)/2 + 1;
1297 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1298 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1303 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1307 x1
= ARROW_WIDTH
- 1;
1309 x2
= (ARROW_WIDTH
- 1)/2;
1311 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1312 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1317 // create the inversed bitmap but only for the right arrow as we only
1318 // use it for the menus
1319 if ( n
== Arrow_Right
)
1321 m_bmpArrows
[Arrow_Inversed
][n
].Create(w
, h
);
1322 dcInverse
.SelectObject(m_bmpArrows
[Arrow_Inversed
][n
]);
1324 dcInverse
.Blit(0, 0, w
, h
,
1327 dcInverse
.SelectObject(wxNullBitmap
);
1329 mask
= new wxMask(m_bmpArrows
[Arrow_Inversed
][n
], *wxBLACK
);
1330 m_bmpArrows
[Arrow_Inversed
][n
].SetMask(mask
);
1332 m_bmpArrows
[Arrow_InversedDisabled
][n
].Create(w
, h
);
1333 dcInverse
.SelectObject(m_bmpArrows
[Arrow_InversedDisabled
][n
]);
1335 dcInverse
.Blit(0, 0, w
, h
,
1338 dcInverse
.SelectObject(wxNullBitmap
);
1340 mask
= new wxMask(m_bmpArrows
[Arrow_InversedDisabled
][n
], *wxBLACK
);
1341 m_bmpArrows
[Arrow_InversedDisabled
][n
].SetMask(mask
);
1344 dcNormal
.SelectObject(wxNullBitmap
);
1345 dcDisabled
.SelectObject(wxNullBitmap
);
1347 mask
= new wxMask(m_bmpArrows
[Arrow_Normal
][n
], *wxWHITE
);
1348 m_bmpArrows
[Arrow_Normal
][n
].SetMask(mask
);
1349 mask
= new wxMask(m_bmpArrows
[Arrow_Disabled
][n
], *wxWHITE
);
1350 m_bmpArrows
[Arrow_Disabled
][n
].SetMask(mask
);
1352 m_bmpArrows
[Arrow_Pressed
][n
] = m_bmpArrows
[Arrow_Normal
][n
];
1356 // ----------------------------------------------------------------------------
1358 // ----------------------------------------------------------------------------
1361 The raised border in Win32 looks like this:
1363 IIIIIIIIIIIIIIIIIIIIIIB
1365 I GB I = white (HILIGHT)
1366 I GB H = light grey (LIGHT)
1367 I GB G = dark grey (SHADOI)
1368 I GB B = black (DKSHADOI)
1369 I GB I = hIghlight (COLOR_3DHILIGHT)
1371 IGGGGGGGGGGGGGGGGGGGGGB
1372 BBBBBBBBBBBBBBBBBBBBBBB
1374 The sunken border looks like this:
1376 GGGGGGGGGGGGGGGGGGGGGGI
1377 GBBBBBBBBBBBBBBBBBBBBHI
1384 GHHHHHHHHHHHHHHHHHHHHHI
1385 IIIIIIIIIIIIIIIIIIIIIII
1387 The static border (used for the controls which don't get focus) is like
1390 GGGGGGGGGGGGGGGGGGGGGGW
1398 WWWWWWWWWWWWWWWWWWWWWWW
1400 The most complicated is the double border:
1402 HHHHHHHHHHHHHHHHHHHHHHB
1403 HWWWWWWWWWWWWWWWWWWWWGB
1404 HWHHHHHHHHHHHHHHHHHHHGB
1409 HWHHHHHHHHHHHHHHHHHHHGB
1410 HGGGGGGGGGGGGGGGGGGGGGB
1411 BBBBBBBBBBBBBBBBBBBBBBB
1413 And the simple border is, well, simple:
1415 BBBBBBBBBBBBBBBBBBBBBBB
1424 BBBBBBBBBBBBBBBBBBBBBBB
1427 void wxWin32Renderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1431 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1432 dc
.DrawRectangle(*rect
);
1438 void wxWin32Renderer::DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1440 // draw the bottom and right sides
1442 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1443 rect
->GetRight() + 1, rect
->GetBottom());
1444 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1445 rect
->GetRight(), rect
->GetBottom());
1452 void wxWin32Renderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
1453 const wxPen
& pen1
, const wxPen
& pen2
)
1455 // draw the rectangle
1457 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
1458 rect
->GetLeft(), rect
->GetBottom());
1459 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
1460 rect
->GetRight(), rect
->GetTop());
1462 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1463 rect
->GetRight(), rect
->GetBottom());
1464 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1465 rect
->GetRight() + 1, rect
->GetBottom());
1471 void wxWin32Renderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
1473 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
1474 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
1477 void wxWin32Renderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
1479 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
1480 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
1483 void wxWin32Renderer::DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
)
1487 DrawRect(dc
, rect
, m_penDarkGrey
);
1489 // the arrow is usually drawn inside border of width 2 and is offset by
1490 // another pixel in both directions when it's pressed - as the border
1491 // in this case is more narrow as well, we have to adjust rect like
1499 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
1500 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
1504 void wxWin32Renderer::DrawBorder(wxDC
& dc
,
1506 const wxRect
& rectTotal
,
1507 int WXUNUSED(flags
),
1512 wxRect rect
= rectTotal
;
1516 case wxBORDER_SUNKEN
:
1517 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1519 DrawSunkenBorder(dc
, &rect
);
1523 case wxBORDER_STATIC
:
1524 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1527 case wxBORDER_RAISED
:
1528 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1530 DrawRaisedBorder(dc
, &rect
);
1534 case wxBORDER_DOUBLE
:
1535 DrawArrowBorder(dc
, &rect
);
1536 DrawRect(dc
, &rect
, m_penLightGrey
);
1539 case wxBORDER_SIMPLE
:
1540 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1542 DrawRect(dc
, &rect
, m_penBlack
);
1547 wxFAIL_MSG(_T("unknown border type"));
1550 case wxBORDER_DEFAULT
:
1559 wxRect
wxWin32Renderer::GetBorderDimensions(wxBorder border
) const
1564 case wxBORDER_RAISED
:
1565 case wxBORDER_SUNKEN
:
1566 width
= BORDER_THICKNESS
;
1569 case wxBORDER_SIMPLE
:
1570 case wxBORDER_STATIC
:
1574 case wxBORDER_DOUBLE
:
1579 wxFAIL_MSG(_T("unknown border type"));
1582 case wxBORDER_DEFAULT
:
1592 rect
.height
= width
;
1597 bool wxWin32Renderer::AreScrollbarsInsideBorder() const
1602 // ----------------------------------------------------------------------------
1604 // ----------------------------------------------------------------------------
1606 void wxWin32Renderer::DrawTextBorder(wxDC
& dc
,
1612 // text controls are not special under windows
1613 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
1616 void wxWin32Renderer::DrawButtonBorder(wxDC
& dc
,
1617 const wxRect
& rectTotal
,
1621 wxRect rect
= rectTotal
;
1623 if ( flags
& wxCONTROL_PRESSED
)
1625 // button pressed: draw a double border around it
1626 DrawRect(dc
, &rect
, m_penBlack
);
1627 DrawRect(dc
, &rect
, m_penDarkGrey
);
1631 // button not pressed
1633 if ( flags
& (wxCONTROL_FOCUSED
| wxCONTROL_ISDEFAULT
) )
1635 // button either default or focused (or both): add an extra border around it
1636 DrawRect(dc
, &rect
, m_penBlack
);
1639 // now draw a normal button
1640 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penBlack
);
1641 DrawHalfRect(dc
, &rect
, m_penDarkGrey
);
1650 // ----------------------------------------------------------------------------
1652 // ----------------------------------------------------------------------------
1654 void wxWin32Renderer::DrawHorizontalLine(wxDC
& dc
,
1655 wxCoord y
, wxCoord x1
, wxCoord x2
)
1657 dc
.SetPen(m_penDarkGrey
);
1658 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1659 dc
.SetPen(m_penHighlight
);
1661 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1664 void wxWin32Renderer::DrawVerticalLine(wxDC
& dc
,
1665 wxCoord x
, wxCoord y1
, wxCoord y2
)
1667 dc
.SetPen(m_penDarkGrey
);
1668 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1669 dc
.SetPen(m_penHighlight
);
1671 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1674 void wxWin32Renderer::DrawFrame(wxDC
& dc
,
1675 const wxString
& label
,
1681 wxCoord height
= 0; // of the label
1682 wxRect rectFrame
= rect
;
1683 if ( !label
.empty() )
1685 // the text should touch the top border of the rect, so the frame
1686 // itself should be lower
1687 dc
.GetTextExtent(label
, NULL
, &height
);
1688 rectFrame
.y
+= height
/ 2;
1689 rectFrame
.height
-= height
/ 2;
1691 // we have to draw each part of the frame individually as we can't
1692 // erase the background beyond the label as it might contain some
1693 // pixmap already, so drawing everything and then overwriting part of
1694 // the frame with label doesn't work
1696 // TODO: the +5 and space insertion should be customizable
1699 rectText
.x
= rectFrame
.x
+ 5;
1700 rectText
.y
= rect
.y
;
1701 rectText
.width
= rectFrame
.width
- 7; // +2 border width
1702 rectText
.height
= height
;
1705 label2
<< _T(' ') << label
<< _T(' ');
1706 if ( indexAccel
!= -1 )
1708 // adjust it as we prepended a space
1713 DrawLabel(dc
, label2
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
1715 StandardDrawFrame(dc
, rectFrame
, rectLabel
);
1719 // just draw the complete frame
1720 DrawShadedRect(dc
, &rectFrame
, m_penDarkGrey
, m_penHighlight
);
1721 DrawShadedRect(dc
, &rectFrame
, m_penHighlight
, m_penDarkGrey
);
1725 // ----------------------------------------------------------------------------
1727 // ----------------------------------------------------------------------------
1729 void wxWin32Renderer::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
1731 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
1732 // pixels each while we really need dots here... PS_ALTERNATE might
1733 // work, but it is for NT 5 only
1735 DrawRect(dc
, &rect
, wxPen(*wxBLACK
, 0, wxDOT
));
1737 // draw the pixels manually: note that to behave in the same manner as
1738 // DrawRect(), we must exclude the bottom and right borders from the
1740 wxCoord x1
= rect
.GetLeft(),
1742 x2
= rect
.GetRight(),
1743 y2
= rect
.GetBottom();
1745 dc
.SetPen(wxPen(*wxBLACK
, 0, wxSOLID
));
1747 // this seems to be closer than what Windows does than wxINVERT although
1748 // I'm still not sure if it's correct
1749 dc
.SetLogicalFunction(wxAND_REVERSE
);
1752 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
1753 dc
.DrawPoint(z
, rect
.GetTop());
1755 wxCoord shift
= z
== x2
? 0 : 1;
1756 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
1757 dc
.DrawPoint(x2
, z
);
1759 shift
= z
== y2
? 0 : 1;
1760 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
1761 dc
.DrawPoint(z
, y2
);
1763 shift
= z
== x1
? 0 : 1;
1764 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
1765 dc
.DrawPoint(x1
, z
);
1767 dc
.SetLogicalFunction(wxCOPY
);
1771 void wxWin32Renderer::DrawLabelShadow(wxDC
& dc
,
1772 const wxString
& label
,
1777 // draw shadow of the text
1778 dc
.SetTextForeground(m_colHighlight
);
1779 wxRect rectShadow
= rect
;
1782 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
1784 // make the text grey
1785 dc
.SetTextForeground(m_colDarkGrey
);
1788 void wxWin32Renderer::DrawLabel(wxDC
& dc
,
1789 const wxString
& label
,
1796 DoDrawLabel(dc
, label
, rect
, flags
, alignment
, indexAccel
, rectBounds
);
1799 void wxWin32Renderer::DoDrawLabel(wxDC
& dc
,
1800 const wxString
& label
,
1806 const wxPoint
& focusOffset
)
1808 // the underscores are not drawn for focused controls in wxMSW
1809 if ( flags
& wxCONTROL_FOCUSED
)
1814 if ( flags
& wxCONTROL_DISABLED
)
1816 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
1817 // currently only can happen for a menu item and it seems that Windows
1818 // doesn't draw the shadow in this case, so we don't do it neither
1819 if ( flags
& wxCONTROL_SELECTED
)
1821 // just make the label text greyed out
1822 dc
.SetTextForeground(m_colDarkGrey
);
1824 else // draw normal disabled label
1826 DrawLabelShadow(dc
, label
, rect
, alignment
, indexAccel
);
1831 dc
.DrawLabel(label
, wxNullBitmap
, rect
, alignment
, indexAccel
, &rectLabel
);
1833 if ( flags
& wxCONTROL_DISABLED
)
1835 // restore the fg colour
1836 dc
.SetTextForeground(*wxBLACK
);
1839 if ( flags
& wxCONTROL_FOCUSED
)
1841 if ( focusOffset
.x
|| focusOffset
.y
)
1843 rectLabel
.Inflate(focusOffset
.x
, focusOffset
.y
);
1846 DrawFocusRect(dc
, rectLabel
);
1850 *rectBounds
= rectLabel
;
1853 void wxWin32Renderer::DrawButtonLabel(wxDC
& dc
,
1854 const wxString
& label
,
1855 const wxBitmap
& image
,
1862 // the underscores are not drawn for focused controls in wxMSW
1863 if ( flags
& wxCONTROL_PRESSED
)
1868 wxRect rectLabel
= rect
;
1869 if ( !label
.empty() )
1871 // shift the label if a button is pressed
1872 if ( flags
& wxCONTROL_PRESSED
)
1878 if ( flags
& wxCONTROL_DISABLED
)
1880 DrawLabelShadow(dc
, label
, rectLabel
, alignment
, indexAccel
);
1883 // leave enough space for the focus rectangle
1884 if ( flags
& wxCONTROL_FOCUSED
)
1886 rectLabel
.Inflate(-2);
1890 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
1892 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
1894 if ( flags
& wxCONTROL_PRESSED
)
1896 // the focus rectangle is never pressed, so undo the shift done
1904 DrawFocusRect(dc
, rectLabel
);
1908 // ----------------------------------------------------------------------------
1909 // (check)listbox items
1910 // ----------------------------------------------------------------------------
1912 void wxWin32Renderer::DrawItem(wxDC
& dc
,
1913 const wxString
& label
,
1917 wxDCTextColourChanger
colChanger(dc
);
1919 if ( flags
& wxCONTROL_SELECTED
)
1921 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
1923 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
1924 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
1925 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
1926 dc
.DrawRectangle(rect
);
1929 wxRect rectText
= rect
;
1931 rectText
.width
-= 2;
1932 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
1934 if ( flags
& wxCONTROL_FOCUSED
)
1936 DrawFocusRect(dc
, rect
);
1940 void wxWin32Renderer::DrawCheckItem(wxDC
& dc
,
1941 const wxString
& label
,
1942 const wxBitmap
& bitmap
,
1951 else // use default bitmap
1953 bmp
= wxBitmap(flags
& wxCONTROL_CHECKED
? checked_item_xpm
1954 : unchecked_item_xpm
);
1957 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2 - 1,
1958 TRUE
/* use mask */);
1960 wxRect rectLabel
= rect
;
1961 int bmpWidth
= bmp
.GetWidth();
1962 rectLabel
.x
+= bmpWidth
;
1963 rectLabel
.width
-= bmpWidth
;
1965 DrawItem(dc
, label
, rectLabel
, flags
);
1968 // ----------------------------------------------------------------------------
1969 // check/radio buttons
1970 // ----------------------------------------------------------------------------
1972 wxBitmap
wxWin32Renderer::GetIndicator(IndicatorType indType
, int flags
)
1974 IndicatorState indState
;
1975 if ( flags
& wxCONTROL_SELECTED
)
1976 indState
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
1977 : IndicatorState_Selected
;
1978 else if ( flags
& wxCONTROL_DISABLED
)
1979 indState
= IndicatorState_Disabled
;
1980 else if ( flags
& wxCONTROL_PRESSED
)
1981 indState
= IndicatorState_Pressed
;
1983 indState
= IndicatorState_Normal
;
1985 IndicatorStatus indStatus
= flags
& wxCONTROL_CHECKED
1986 ? IndicatorStatus_Checked
1987 : IndicatorStatus_Unchecked
;
1989 const char **xpm
= bmpIndicators
[indType
][indState
][indStatus
];
1990 return xpm
? wxBitmap(xpm
) : wxNullBitmap
;
1993 void wxWin32Renderer::DrawCheckOrRadioButton(wxDC
& dc
,
1994 const wxString
& label
,
1995 const wxBitmap
& bitmap
,
2000 wxCoord focusOffsetY
)
2002 // calculate the position of the bitmap and of the label
2003 wxCoord heightBmp
= bitmap
.GetHeight();
2005 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
2008 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
2009 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
2011 // align label vertically with the bitmap - looks nicer like this
2012 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
2014 // calc horz position
2015 if ( align
== wxALIGN_RIGHT
)
2017 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
2018 rectLabel
.x
= rect
.x
+ 3;
2019 rectLabel
.SetRight(xBmp
);
2021 else // normal (checkbox to the left of the text) case
2024 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
2025 rectLabel
.SetRight(rect
.GetRight());
2028 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, TRUE
/* use mask */);
2031 dc
, label
, rectLabel
,
2033 wxALIGN_LEFT
| wxALIGN_TOP
,
2035 NULL
, // we don't need bounding rect
2036 // use custom vert focus rect offset
2037 wxPoint(FOCUS_RECT_OFFSET_X
, focusOffsetY
)
2041 void wxWin32Renderer::DrawRadioButton(wxDC
& dc
,
2042 const wxString
& label
,
2043 const wxBitmap
& bitmap
,
2049 DrawCheckOrRadioButton(dc
, label
,
2050 bitmap
.Ok() ? bitmap
: GetRadioBitmap(flags
),
2051 rect
, flags
, align
, indexAccel
,
2052 FOCUS_RECT_OFFSET_Y
); // default focus rect offset
2055 void wxWin32Renderer::DrawCheckButton(wxDC
& dc
,
2056 const wxString
& label
,
2057 const wxBitmap
& bitmap
,
2063 DrawCheckOrRadioButton(dc
, label
,
2064 bitmap
.Ok() ? bitmap
: GetCheckBitmap(flags
),
2065 rect
, flags
, align
, indexAccel
,
2066 0); // no focus rect offset for checkboxes
2069 // ----------------------------------------------------------------------------
2071 // ----------------------------------------------------------------------------
2073 void wxWin32Renderer::DrawTextLine(wxDC
& dc
,
2074 const wxString
& text
,
2080 // nothing special to do here
2081 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
2084 void wxWin32Renderer::DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
)
2086 // we don't draw them
2089 // ----------------------------------------------------------------------------
2091 // ----------------------------------------------------------------------------
2093 void wxWin32Renderer::DrawTab(wxDC
& dc
,
2094 const wxRect
& rectOrig
,
2096 const wxString
& label
,
2097 const wxBitmap
& bitmap
,
2101 wxRect rect
= rectOrig
;
2103 // the current tab is drawn indented (to the top for default case) and
2104 // bigger than the other ones
2105 const wxSize indent
= GetTabIndent();
2106 if ( flags
& wxCONTROL_SELECTED
)
2111 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2115 rect
.Inflate(indent
.x
, 0);
2117 rect
.height
+= indent
.y
;
2121 rect
.Inflate(indent
.x
, 0);
2122 rect
.height
+= indent
.y
;
2127 wxFAIL_MSG(_T("TODO"));
2132 // draw the text, image and the focus around them (if necessary)
2133 wxRect rectLabel
= rect
;
2134 rectLabel
.Deflate(1, 1);
2135 DrawButtonLabel(dc
, label
, bitmap
, rectLabel
,
2136 flags
, wxALIGN_CENTRE
, indexAccel
);
2138 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2139 static const wxCoord CUTOFF
= 2; // radius of the rounded corner
2142 x2
= rect
.GetRight(),
2143 y2
= rect
.GetBottom();
2145 // FIXME: all this code will break if the tab indent or the border width,
2146 // it is tied to the fact that both of them are equal to 2
2151 dc
.SetPen(m_penHighlight
);
2152 dc
.DrawLine(x
, y2
, x
, y
+ CUTOFF
);
2153 dc
.DrawLine(x
, y
+ CUTOFF
, x
+ CUTOFF
, y
);
2154 dc
.DrawLine(x
+ CUTOFF
, y
, x2
- CUTOFF
+ 1, y
);
2156 dc
.SetPen(m_penBlack
);
2157 dc
.DrawLine(x2
, y2
, x2
, y
+ CUTOFF
);
2158 dc
.DrawLine(x2
, y
+ CUTOFF
, x2
- CUTOFF
, y
);
2160 dc
.SetPen(m_penDarkGrey
);
2161 dc
.DrawLine(x2
- 1, y2
, x2
- 1, y
+ CUTOFF
- 1);
2163 if ( flags
& wxCONTROL_SELECTED
)
2165 dc
.SetPen(m_penLightGrey
);
2167 // overwrite the part of the border below this tab
2168 dc
.DrawLine(x
+ 1, y2
+ 1, x2
- 1, y2
+ 1);
2170 // and the shadow of the tab to the left of us
2171 dc
.DrawLine(x
+ 1, y
+ CUTOFF
+ 1, x
+ 1, y2
+ 1);
2176 dc
.SetPen(m_penHighlight
);
2177 // we need to continue one pixel further to overwrite the corner of
2178 // the border for the selected tab
2179 dc
.DrawLine(x
, y
- (flags
& wxCONTROL_SELECTED
? 1 : 0),
2181 dc
.DrawLine(x
, y2
- CUTOFF
, x
+ CUTOFF
, y2
);
2183 dc
.SetPen(m_penBlack
);
2184 dc
.DrawLine(x
+ CUTOFF
, y2
, x2
- CUTOFF
+ 1, y2
);
2185 dc
.DrawLine(x2
, y
, x2
, y2
- CUTOFF
);
2186 dc
.DrawLine(x2
, y2
- CUTOFF
, x2
- CUTOFF
, y2
);
2188 dc
.SetPen(m_penDarkGrey
);
2189 dc
.DrawLine(x
+ CUTOFF
, y2
- 1, x2
- CUTOFF
+ 1, y2
- 1);
2190 dc
.DrawLine(x2
- 1, y
, x2
- 1, y2
- CUTOFF
+ 1);
2192 if ( flags
& wxCONTROL_SELECTED
)
2194 dc
.SetPen(m_penLightGrey
);
2196 // overwrite the part of the (double!) border above this tab
2197 dc
.DrawLine(x
+ 1, y
- 1, x2
- 1, y
- 1);
2198 dc
.DrawLine(x
+ 1, y
- 2, x2
- 1, y
- 2);
2200 // and the shadow of the tab to the left of us
2201 dc
.DrawLine(x
+ 1, y2
- CUTOFF
, x
+ 1, y
- 1);
2207 wxFAIL_MSG(_T("TODO"));
2211 // ----------------------------------------------------------------------------
2213 // ----------------------------------------------------------------------------
2215 wxSize
wxWin32Renderer::GetSliderThumbSize(const wxRect
& rect
,
2216 wxOrientation orient
) const
2220 wxRect rectShaft
= GetSliderShaftRect(rect
, orient
);
2221 if ( orient
== wxHORIZONTAL
)
2223 size
.y
= rect
.height
- 6;
2224 size
.x
= wxMin(size
.y
/ 2, rectShaft
.width
);
2228 size
.x
= rect
.width
- 6;
2229 size
.y
= wxMin(size
.x
/ 2, rectShaft
.height
);
2235 wxRect
wxWin32Renderer::GetSliderShaftRect(const wxRect
& rectOrig
,
2236 wxOrientation orient
) const
2238 static const wxCoord SLIDER_MARGIN
= 6;
2240 wxRect rect
= rectOrig
;
2242 if ( orient
== wxHORIZONTAL
)
2244 // make the rect of minimal width and centre it
2245 rect
.height
= 2*BORDER_THICKNESS
;
2246 rect
.y
= rectOrig
.y
+ (rectOrig
.height
- rect
.height
) / 2;
2250 // leave margins on the sides
2251 rect
.Deflate(SLIDER_MARGIN
, 0);
2255 // same as above but in other direction
2256 rect
.width
= 2*BORDER_THICKNESS
;
2257 rect
.x
= rectOrig
.x
+ (rectOrig
.width
- rect
.width
) / 2;
2261 rect
.Deflate(0, SLIDER_MARGIN
);
2267 void wxWin32Renderer::DrawSliderShaft(wxDC
& dc
,
2268 const wxRect
& rectOrig
,
2269 wxOrientation orient
,
2273 if ( flags
& wxCONTROL_FOCUSED
)
2275 DrawFocusRect(dc
, rectOrig
);
2278 wxRect rect
= GetSliderShaftRect(rectOrig
, orient
);
2283 DrawSunkenBorder(dc
, &rect
);
2286 void wxWin32Renderer::DrawSliderThumb(wxDC
& dc
,
2288 wxOrientation orient
,
2292 we are drawing a shape of this form
2297 H DB where H is hightlight colour
2310 The interior of this shape is filled with the hatched brush if the thumb
2314 DrawBackground(dc
, wxNullColour
, rect
, flags
);
2316 bool transpose
= orient
== wxVERTICAL
;
2318 wxCoord x
, y
, x2
, y2
;
2323 x2
= rect
.GetBottom();
2324 y2
= rect
.GetRight();
2330 x2
= rect
.GetRight();
2331 y2
= rect
.GetBottom();
2334 // the size of the pointed part of the thumb
2335 wxCoord sizeArrow
= (transpose
? rect
.height
: rect
.width
) / 2;
2337 wxCoord x3
= x
+ sizeArrow
,
2338 y3
= y2
- sizeArrow
;
2340 dc
.SetPen(m_penHighlight
);
2341 DrawLine(dc
, x
, y
, x2
, y
, transpose
);
2342 DrawLine(dc
, x
, y
+ 1, x
, y2
- sizeArrow
, transpose
);
2343 DrawLine(dc
, x
, y3
, x3
, y2
, transpose
);
2345 dc
.SetPen(m_penBlack
);
2346 DrawLine(dc
, x3
, y2
, x2
, y3
, transpose
);
2347 DrawLine(dc
, x2
, y3
, x2
, y
- 1, transpose
);
2349 dc
.SetPen(m_penDarkGrey
);
2350 DrawLine(dc
, x3
, y2
- 1, x2
- 1, y3
, transpose
);
2351 DrawLine(dc
, x2
- 1, y3
, x2
- 1, y
, transpose
);
2353 if ( flags
& wxCONTROL_PRESSED
)
2355 // TODO: MSW fills the entire area inside, not just the rect
2356 wxRect rectInt
= rect
;
2358 rectInt
.SetRight(y3
);
2360 rectInt
.SetBottom(y3
);
2363 static const char *stipple_xpm
[] = {
2364 /* columns rows colors chars-per-pixel */
2372 dc
.SetBrush(wxBrush(stipple_xpm
));
2374 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, SHADOW_HIGHLIGHT
));
2375 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, CONTROL
));
2376 dc
.SetPen(*wxTRANSPARENT_PEN
);
2377 dc
.DrawRectangle(rectInt
);
2381 void wxWin32Renderer::DrawSliderTicks(wxDC
& dc
,
2383 const wxSize
& sizeThumb
,
2384 wxOrientation orient
,
2396 // the variable names correspond to horizontal case, but they can be used
2397 // for both orientations
2398 wxCoord x1
, x2
, y1
, y2
, len
, widthThumb
;
2399 if ( orient
== wxHORIZONTAL
)
2401 x1
= rect
.GetLeft();
2402 x2
= rect
.GetRight();
2404 // draw from bottom to top to leave one pixel space between the ticks
2405 // and the slider as Windows do
2406 y1
= rect
.GetBottom();
2411 widthThumb
= sizeThumb
.x
;
2416 x2
= rect
.GetBottom();
2418 y1
= rect
.GetRight();
2419 y2
= rect
.GetLeft();
2423 widthThumb
= sizeThumb
.y
;
2426 // the first tick should be positioned in such way that a thumb drawn in
2427 // the first position points down directly to it
2428 x1
+= widthThumb
/ 2;
2429 x2
-= widthThumb
/ 2;
2431 // this also means that we have slightly less space for the ticks in
2432 // between the first and the last
2435 dc
.SetPen(m_penBlack
);
2437 int range
= end
- start
;
2438 for ( int n
= 0; n
< range
; n
+= step
)
2440 wxCoord x
= x1
+ (len
*n
) / range
;
2442 DrawLine(dc
, x
, y1
, x
, y2
, orient
== wxVERTICAL
);
2445 // always draw the line at the end position
2446 DrawLine(dc
, x2
, y1
, x2
, y2
, orient
== wxVERTICAL
);
2449 // ----------------------------------------------------------------------------
2451 // ----------------------------------------------------------------------------
2455 // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2456 class WXDLLEXPORT wxWin32MenuGeometryInfo
: public wxMenuGeometryInfo
2459 virtual wxSize
GetSize() const { return m_size
; }
2461 wxCoord
GetLabelOffset() const { return m_ofsLabel
; }
2462 wxCoord
GetAccelOffset() const { return m_ofsAccel
; }
2464 wxCoord
GetItemHeight() const { return m_heightItem
; }
2467 // the total size of the menu
2470 // the offset of the start of the menu item label
2473 // the offset of the start of the accel label
2476 // the height of a normal (not separator) item
2477 wxCoord m_heightItem
;
2479 friend wxMenuGeometryInfo
*wxWin32Renderer::
2480 GetMenuGeometry(wxWindow
*, const wxMenu
&) const;
2483 #endif // wxUSE_MENUS
2485 // FIXME: all constants are hardcoded but shouldn't be
2486 static const wxCoord MENU_LEFT_MARGIN
= 9;
2487 static const wxCoord MENU_RIGHT_MARGIN
= 18;
2488 static const wxCoord MENU_VERT_MARGIN
= 3;
2490 // the margin around bitmap/check marks (on each side)
2491 static const wxCoord MENU_BMP_MARGIN
= 2;
2493 // the margin between the labels and accel strings
2494 static const wxCoord MENU_ACCEL_MARGIN
= 8;
2496 // the separator height in pixels: in fact, strangely enough, the real height
2497 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2499 static const wxCoord MENU_SEPARATOR_HEIGHT
= 3;
2501 // the size of the standard checkmark bitmap
2502 static const wxCoord MENU_CHECK_SIZE
= 9;
2504 // we can't implement these methods without wxMenuGeometryInfo implementation
2505 // which we don't have if !wxUSE_MENUS
2508 void wxWin32Renderer::DrawMenuBarItem(wxDC
& dc
,
2509 const wxRect
& rectOrig
,
2510 const wxString
& label
,
2514 wxRect rect
= rectOrig
;
2517 wxDCTextColourChanger
colChanger(dc
);
2519 if ( flags
& wxCONTROL_SELECTED
)
2521 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2523 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2524 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2525 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2526 dc
.DrawRectangle(rect
);
2529 // don't draw the focus rect around menu bar items
2530 DrawLabel(dc
, label
, rect
, flags
& ~wxCONTROL_FOCUSED
,
2531 wxALIGN_CENTRE
, indexAccel
);
2534 void wxWin32Renderer::DrawMenuItem(wxDC
& dc
,
2536 const wxMenuGeometryInfo
& gi
,
2537 const wxString
& label
,
2538 const wxString
& accel
,
2539 const wxBitmap
& bitmap
,
2543 const wxWin32MenuGeometryInfo
& geometryInfo
=
2544 (const wxWin32MenuGeometryInfo
&)gi
;
2549 rect
.width
= geometryInfo
.GetSize().x
;
2550 rect
.height
= geometryInfo
.GetItemHeight();
2552 // draw the selected item specially
2553 wxDCTextColourChanger
colChanger(dc
);
2554 if ( flags
& wxCONTROL_SELECTED
)
2556 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2558 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2559 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2560 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2561 dc
.DrawRectangle(rect
);
2564 // draw the bitmap: use the bitmap provided or the standard checkmark for
2565 // the checkable items
2566 wxBitmap bmp
= bitmap
;
2567 if ( !bmp
.Ok() && (flags
& wxCONTROL_CHECKED
) )
2569 bmp
= GetIndicator(IndicatorType_Menu
, flags
);
2574 rect
.SetRight(geometryInfo
.GetLabelOffset());
2575 wxControlRenderer::DrawBitmap(dc
, bmp
, rect
);
2579 rect
.x
= geometryInfo
.GetLabelOffset();
2580 rect
.SetRight(geometryInfo
.GetAccelOffset());
2582 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
, indexAccel
);
2584 // draw the accel string
2585 rect
.x
= geometryInfo
.GetAccelOffset();
2586 rect
.SetRight(geometryInfo
.GetSize().x
);
2588 // NB: no accel index here
2589 DrawLabel(dc
, accel
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
);
2591 // draw the submenu indicator
2592 if ( flags
& wxCONTROL_ISSUBMENU
)
2594 rect
.x
= geometryInfo
.GetSize().x
- MENU_RIGHT_MARGIN
;
2595 rect
.width
= MENU_RIGHT_MARGIN
;
2597 wxArrowStyle arrowStyle
;
2598 if ( flags
& wxCONTROL_DISABLED
)
2599 arrowStyle
= flags
& wxCONTROL_SELECTED
? Arrow_InversedDisabled
2601 else if ( flags
& wxCONTROL_SELECTED
)
2602 arrowStyle
= Arrow_Inversed
;
2604 arrowStyle
= Arrow_Normal
;
2606 DrawArrow(dc
, rect
, Arrow_Right
, arrowStyle
);
2610 void wxWin32Renderer::DrawMenuSeparator(wxDC
& dc
,
2612 const wxMenuGeometryInfo
& geomInfo
)
2614 DrawHorizontalLine(dc
, y
+ MENU_VERT_MARGIN
, 0, geomInfo
.GetSize().x
);
2617 wxSize
wxWin32Renderer::GetMenuBarItemSize(const wxSize
& sizeText
) const
2619 wxSize size
= sizeText
;
2621 // FIXME: menubar height is configurable under Windows
2628 wxMenuGeometryInfo
*wxWin32Renderer::GetMenuGeometry(wxWindow
*win
,
2629 const wxMenu
& menu
) const
2631 // prepare the dc: for now we draw all the items with the system font
2633 dc
.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
));
2635 // the height of a normal item
2636 wxCoord heightText
= dc
.GetCharHeight();
2641 // the max length of label and accel strings: the menu width is the sum of
2642 // them, even if they're for different items (as the accels should be
2645 // the max length of the bitmap is never 0 as Windows always leaves enough
2646 // space for a check mark indicator
2647 wxCoord widthLabelMax
= 0,
2649 widthBmpMax
= MENU_LEFT_MARGIN
;
2651 for ( wxMenuItemList::Node
*node
= menu
.GetMenuItems().GetFirst();
2653 node
= node
->GetNext() )
2655 // height of this item
2658 wxMenuItem
*item
= node
->GetData();
2659 if ( item
->IsSeparator() )
2661 h
= MENU_SEPARATOR_HEIGHT
;
2663 else // not separator
2668 dc
.GetTextExtent(item
->GetLabel(), &widthLabel
, NULL
);
2669 if ( widthLabel
> widthLabelMax
)
2671 widthLabelMax
= widthLabel
;
2675 dc
.GetTextExtent(item
->GetAccelString(), &widthAccel
, NULL
);
2676 if ( widthAccel
> widthAccelMax
)
2678 widthAccelMax
= widthAccel
;
2681 const wxBitmap
& bmp
= item
->GetBitmap();
2684 wxCoord widthBmp
= bmp
.GetWidth();
2685 if ( widthBmp
> widthBmpMax
)
2686 widthBmpMax
= widthBmp
;
2688 //else if ( item->IsCheckable() ): no need to check for this as
2689 // MENU_LEFT_MARGIN is big enough to show the check mark
2692 h
+= 2*MENU_VERT_MARGIN
;
2694 // remember the item position and height
2695 item
->SetGeometry(height
, h
);
2700 // bundle the metrics into a struct and return it
2701 wxWin32MenuGeometryInfo
*gi
= new wxWin32MenuGeometryInfo
;
2703 gi
->m_ofsLabel
= widthBmpMax
+ 2*MENU_BMP_MARGIN
;
2704 gi
->m_ofsAccel
= gi
->m_ofsLabel
+ widthLabelMax
;
2705 if ( widthAccelMax
> 0 )
2707 // if we actually have any accesl, add a margin
2708 gi
->m_ofsAccel
+= MENU_ACCEL_MARGIN
;
2711 gi
->m_heightItem
= heightText
+ 2*MENU_VERT_MARGIN
;
2713 gi
->m_size
.x
= gi
->m_ofsAccel
+ widthAccelMax
+ MENU_RIGHT_MARGIN
;
2714 gi
->m_size
.y
= height
;
2719 #else // !wxUSE_MENUS
2722 void wxWin32Renderer::DrawMenuBarItem(wxDC& WXUNUSED(dc),
2723 const wxRect& WXUNUSED(rectOrig),
2724 const wxString& WXUNUSED(label),
2725 int WXUNUSED(flags),
2726 int WXUNUSED(indexAccel))
2730 void wxWin32Renderer::DrawMenuItem(wxDC& WXUNUSED(dc),
2731 wxCoord WXUNUSED(y),
2732 const wxMenuGeometryInfo& WXUNUSED(gi),
2733 const wxString& WXUNUSED(label),
2734 const wxString& WXUNUSED(accel),
2735 const wxBitmap& WXUNUSED(bitmap),
2736 int WXUNUSED(flags),
2737 int WXUNUSED(indexAccel))
2741 void wxWin32Renderer::DrawMenuSeparator(wxDC& WXUNUSED(dc),
2742 wxCoord WXUNUSED(y),
2743 const wxMenuGeometryInfo& WXUNUSED(gi))
2747 wxSize wxWin32Renderer::GetMenuBarItemSize(const wxSize& size) const
2752 wxMenuGeometryInfo *
2753 wxWin32Renderer::GetMenuGeometry(wxWindow *WXUNUSED(win),
2754 const wxMenu& WXUNUSED(menu)) const
2760 #endif // wxUSE_MENUS/!wxUSE_MENUS
2762 // ----------------------------------------------------------------------------
2764 // ----------------------------------------------------------------------------
2766 void wxWin32Renderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
2768 wxBitmap
*bmpPressed
,
2769 wxBitmap
*bmpDisabled
)
2771 static const wxCoord widthCombo
= 16;
2772 static const wxCoord heightCombo
= 17;
2778 bmpNormal
->Create(widthCombo
, heightCombo
);
2779 dcMem
.SelectObject(*bmpNormal
);
2780 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2781 Arrow_Down
, Arrow_Normal
);
2786 bmpPressed
->Create(widthCombo
, heightCombo
);
2787 dcMem
.SelectObject(*bmpPressed
);
2788 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2789 Arrow_Down
, Arrow_Pressed
);
2794 bmpDisabled
->Create(widthCombo
, heightCombo
);
2795 dcMem
.SelectObject(*bmpDisabled
);
2796 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2797 Arrow_Down
, Arrow_Disabled
);
2801 // ----------------------------------------------------------------------------
2803 // ----------------------------------------------------------------------------
2805 void wxWin32Renderer::DoDrawBackground(wxDC
& dc
,
2806 const wxColour
& col
,
2809 wxBrush
brush(col
, wxSOLID
);
2811 dc
.SetPen(*wxTRANSPARENT_PEN
);
2812 dc
.DrawRectangle(rect
);
2815 void wxWin32Renderer::DrawBackground(wxDC
& dc
,
2816 const wxColour
& col
,
2820 // just fill it with the given or default bg colour
2821 wxColour colBg
= col
.Ok() ? col
: wxSCHEME_COLOUR(m_scheme
, CONTROL
);
2822 DoDrawBackground(dc
, colBg
, rect
);
2825 // ----------------------------------------------------------------------------
2827 // ----------------------------------------------------------------------------
2829 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2834 // get the bitmap for this arrow
2835 wxArrowDirection arrowDir
;
2838 case wxLEFT
: arrowDir
= Arrow_Left
; break;
2839 case wxRIGHT
: arrowDir
= Arrow_Right
; break;
2840 case wxUP
: arrowDir
= Arrow_Up
; break;
2841 case wxDOWN
: arrowDir
= Arrow_Down
; break;
2844 wxFAIL_MSG(_T("unknown arrow direction"));
2848 wxArrowStyle arrowStyle
;
2849 if ( flags
& wxCONTROL_PRESSED
)
2851 // can't be pressed and disabled
2852 arrowStyle
= Arrow_Pressed
;
2856 arrowStyle
= flags
& wxCONTROL_DISABLED
? Arrow_Disabled
: Arrow_Normal
;
2859 DrawArrowButton(dc
, rect
, arrowDir
, arrowStyle
);
2862 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2864 wxArrowDirection arrowDir
,
2865 wxArrowStyle arrowStyle
)
2867 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
2869 // under Windows the arrows always have the same size so just centre it in
2870 // the provided rectangle
2871 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
2872 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
2874 // Windows does it like this...
2875 if ( arrowDir
== Arrow_Left
)
2879 dc
.DrawBitmap(bmp
, x
, y
, TRUE
/* use mask */);
2882 void wxWin32Renderer::DrawArrowButton(wxDC
& dc
,
2883 const wxRect
& rectAll
,
2884 wxArrowDirection arrowDir
,
2885 wxArrowStyle arrowStyle
)
2887 wxRect rect
= rectAll
;
2888 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2889 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
2890 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
2893 void wxWin32Renderer::DrawScrollbarThumb(wxDC
& dc
,
2894 wxOrientation orient
,
2898 // we don't use the flags, the thumb never changes appearance
2899 wxRect rectThumb
= rect
;
2900 DrawArrowBorder(dc
, &rectThumb
);
2901 DrawBackground(dc
, wxNullColour
, rectThumb
);
2904 void wxWin32Renderer::DrawScrollbarShaft(wxDC
& dc
,
2905 wxOrientation orient
,
2906 const wxRect
& rectBar
,
2909 wxColourScheme::StdColour col
= flags
& wxCONTROL_PRESSED
2910 ? wxColourScheme::SCROLLBAR_PRESSED
2911 : wxColourScheme::SCROLLBAR
;
2912 DoDrawBackground(dc
, m_scheme
->Get(col
), rectBar
);
2915 void wxWin32Renderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
2917 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2920 wxRect
wxWin32Renderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
2921 wxScrollBar::Element elem
,
2924 return StandardGetScrollbarRect(scrollbar
, elem
,
2925 thumbPos
, m_sizeScrollbarArrow
);
2928 wxCoord
wxWin32Renderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
2930 return StandardScrollBarSize(scrollbar
, m_sizeScrollbarArrow
);
2933 wxHitTest
wxWin32Renderer::HitTestScrollbar(const wxScrollBar
*scrollbar
,
2934 const wxPoint
& pt
) const
2936 return StandardHitTestScrollbar(scrollbar
, pt
, m_sizeScrollbarArrow
);
2939 wxCoord
wxWin32Renderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
2942 return StandardScrollbarToPixel(scrollbar
, thumbPos
, m_sizeScrollbarArrow
);
2945 int wxWin32Renderer::PixelToScrollbar(const wxScrollBar
*scrollbar
,
2948 return StandardPixelToScrollbar(scrollbar
, coord
, m_sizeScrollbarArrow
);
2951 // ----------------------------------------------------------------------------
2952 // text control geometry
2953 // ----------------------------------------------------------------------------
2955 static inline int GetTextBorderWidth()
2960 wxRect
wxWin32Renderer::GetTextTotalArea(const wxTextCtrl
*text
,
2963 wxRect rectTotal
= rect
;
2965 wxCoord widthBorder
= GetTextBorderWidth();
2966 rectTotal
.Inflate(widthBorder
);
2968 // this is what Windows does
2974 wxRect
wxWin32Renderer::GetTextClientArea(const wxTextCtrl
*text
,
2976 wxCoord
*extraSpaceBeyond
)
2978 wxRect rectText
= rect
;
2980 // undo GetTextTotalArea()
2981 if ( rectText
.height
> 0 )
2984 wxCoord widthBorder
= GetTextBorderWidth();
2985 rectText
.Inflate(-widthBorder
);
2987 if ( extraSpaceBeyond
)
2988 *extraSpaceBeyond
= 0;
2993 // ----------------------------------------------------------------------------
2995 // ----------------------------------------------------------------------------
2997 void wxWin32Renderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
3000 if ( wxDynamicCast(window
, wxScrollBar
) )
3002 // we only set the width of vert scrollbars and height of the
3004 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
3005 size
->y
= m_sizeScrollbarArrow
.y
;
3007 size
->x
= m_sizeScrollbarArrow
.x
;
3009 // skip border width adjustments, they don't make sense for us
3012 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
3015 if ( wxDynamicCast(window
, wxButton
) )
3017 if ( !(window
->GetWindowStyle() & wxBU_EXACTFIT
) )
3019 // TODO: don't harcode all this
3020 size
->x
+= 3*window
->GetCharWidth();
3022 wxCoord heightBtn
= (11*(window
->GetCharHeight() + 8))/10;
3023 if ( size
->y
< heightBtn
- 8 )
3024 size
->y
= heightBtn
;
3029 // no border width adjustments for buttons
3032 #endif // wxUSE_BUTTON
3034 // take into account the border width
3035 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
3036 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
3037 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
3040 // ============================================================================
3042 // ============================================================================
3044 // ----------------------------------------------------------------------------
3045 // wxWin32InputHandler
3046 // ----------------------------------------------------------------------------
3048 wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer
*renderer
)
3050 m_renderer
= renderer
;
3053 bool wxWin32InputHandler::HandleKey(wxControl
*control
,
3054 const wxKeyEvent
& event
,
3060 bool wxWin32InputHandler::HandleMouse(wxControl
*control
,
3061 const wxMouseEvent
& event
)
3063 // clicking on the control gives it focus
3064 if ( event
.ButtonDown() && wxWindow::FindFocus() != control
)
3066 control
->SetFocus();
3074 // ----------------------------------------------------------------------------
3075 // wxWin32ScrollBarInputHandler
3076 // ----------------------------------------------------------------------------
3078 wxWin32ScrollBarInputHandler::
3079 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
3080 wxInputHandler
*handler
)
3081 : wxStdScrollBarInputHandler(renderer
, handler
)
3083 m_scrollPaused
= FALSE
;
3087 bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar
*scrollbar
,
3088 const wxControlAction
& action
)
3090 // stop if went beyond the position of the original click (this can only
3091 // happen when we scroll by pages)
3093 if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
3095 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3096 != wxHT_SCROLLBAR_BAR_2
;
3098 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
3100 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3101 != wxHT_SCROLLBAR_BAR_1
;
3106 StopScrolling(scrollbar
);
3108 scrollbar
->Refresh();
3113 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar
, action
);
3116 bool wxWin32ScrollBarInputHandler::HandleMouse(wxControl
*control
,
3117 const wxMouseEvent
& event
)
3119 // remember the current state
3120 bool wasDraggingThumb
= m_htLast
== wxHT_SCROLLBAR_THUMB
;
3122 // do process the message
3123 bool rc
= wxStdScrollBarInputHandler::HandleMouse(control
, event
);
3125 // analyse the changes
3126 if ( !wasDraggingThumb
&& (m_htLast
== wxHT_SCROLLBAR_THUMB
) )
3128 // we just started dragging the thumb, remember its initial position to
3129 // be able to restore it if the drag is cancelled later
3130 m_eventStartDrag
= event
;
3136 bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl
*control
,
3137 const wxMouseEvent
& event
)
3139 // we don't highlight scrollbar elements, so there is no need to process
3140 // mouse move events normally - only do it while mouse is captured (i.e.
3141 // when we're dragging the thumb or pressing on something)
3142 if ( !m_winCapture
)
3145 if ( event
.Entering() )
3147 // we're not interested in this at all
3151 wxScrollBar
*scrollbar
= wxStaticCast(control
, wxScrollBar
);
3153 if ( m_scrollPaused
)
3155 // check if the mouse returned to its original location
3157 if ( event
.Leaving() )
3163 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3164 if ( ht
== m_htLast
)
3166 // yes it did, resume scrolling
3167 m_scrollPaused
= FALSE
;
3168 if ( m_timerScroll
)
3170 // we were scrolling by line/page, restart timer
3171 m_timerScroll
->Start(m_interval
);
3173 Press(scrollbar
, TRUE
);
3175 else // we were dragging the thumb
3177 // restore its last location
3178 HandleThumbMove(scrollbar
, m_eventLastDrag
);
3184 else // normal case, scrolling hasn't been paused
3186 // if we're scrolling the scrollbar because the arrow or the shaft was
3187 // pressed, check that the mouse stays on the same scrollbar element
3189 if ( event
.Moving() )
3191 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3193 else // event.Leaving()
3198 // if we're dragging the thumb and the mouse stays in the scrollbar, it
3199 // is still ok - we only want to catch the case when the mouse leaves
3200 // the scrollbar here
3201 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
&& ht
!= wxHT_NOWHERE
)
3203 ht
= wxHT_SCROLLBAR_THUMB
;
3206 if ( ht
!= m_htLast
)
3208 // what were we doing? 2 possibilities: either an arrow/shaft was
3209 // pressed in which case we have a timer and so we just stop it or
3210 // we were dragging the thumb
3211 if ( m_timerScroll
)
3214 m_interval
= m_timerScroll
->GetInterval();
3215 m_timerScroll
->Stop();
3216 m_scrollPaused
= TRUE
;
3218 // unpress the arrow
3219 Press(scrollbar
, FALSE
);
3221 else // we were dragging the thumb
3223 // remember the current thumb position to be able to restore it
3224 // if the mouse returns to it later
3225 m_eventLastDrag
= event
;
3227 // and restore the original position (before dragging) of the
3229 HandleThumbMove(scrollbar
, m_eventStartDrag
);
3236 return wxStdScrollBarInputHandler::HandleMouseMove(control
, event
);
3239 // ----------------------------------------------------------------------------
3240 // wxWin32CheckboxInputHandler
3241 // ----------------------------------------------------------------------------
3243 bool wxWin32CheckboxInputHandler::HandleKey(wxControl
*control
,
3244 const wxKeyEvent
& event
,
3249 wxControlAction action
;
3250 int keycode
= event
.GetKeyCode();
3254 action
= wxACTION_CHECKBOX_TOGGLE
;
3258 case WXK_NUMPAD_SUBTRACT
:
3259 action
= wxACTION_CHECKBOX_CHECK
;
3263 case WXK_NUMPAD_ADD
:
3264 case WXK_NUMPAD_EQUAL
:
3265 action
= wxACTION_CHECKBOX_CLEAR
;
3271 control
->PerformAction(action
);
3280 // ----------------------------------------------------------------------------
3281 // wxWin32TextCtrlInputHandler
3282 // ----------------------------------------------------------------------------
3284 bool wxWin32TextCtrlInputHandler::HandleKey(wxControl
*control
,
3285 const wxKeyEvent
& event
,
3288 // handle only MSW-specific text bindings here, the others are handled in
3292 int keycode
= event
.GetKeyCode();
3294 wxControlAction action
;
3295 if ( keycode
== WXK_DELETE
&& event
.ShiftDown() )
3297 action
= wxACTION_TEXT_CUT
;
3299 else if ( keycode
== WXK_INSERT
)
3301 if ( event
.ControlDown() )
3302 action
= wxACTION_TEXT_COPY
;
3303 else if ( event
.ShiftDown() )
3304 action
= wxACTION_TEXT_PASTE
;
3307 if ( action
!= wxACTION_NONE
)
3309 control
->PerformAction(action
);
3315 return wxStdTextCtrlInputHandler::HandleKey(control
, event
, pressed
);