1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: univ/themes/win32.cpp
3 // Purpose: wxUniversal theme implementing Win32-like LNF
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
31 #include "wx/window.h"
33 #include "wx/dcmemory.h"
35 #include "wx/button.h"
36 #include "wx/listbox.h"
37 #include "wx/checklst.h"
38 #include "wx/combobox.h"
39 #include "wx/scrolbar.h"
40 #include "wx/slider.h"
41 #include "wx/textctrl.h"
44 #include "wx/notebook.h"
45 #include "wx/spinbutt.h"
46 #include "wx/settings.h"
49 #include "wx/univ/scrtimer.h"
51 #include "wx/univ/renderer.h"
52 #include "wx/univ/inphand.h"
53 #include "wx/univ/colschem.h"
54 #include "wx/univ/theme.h"
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 static const int BORDER_THICKNESS
= 2;
62 // the offset between the label and focus rect around it
63 static const int FOCUS_RECT_OFFSET_X
= 1;
64 static const int FOCUS_RECT_OFFSET_Y
= 1;
76 IndicatorState_Normal
,
77 IndicatorState_Pressed
, // this one is for check/radioboxes
78 IndicatorState_Selected
= IndicatorState_Pressed
, // for menus
79 IndicatorState_Disabled
,
80 IndicatorState_SelectedDisabled
, // only for the menus
86 IndicatorStatus_Checked
,
87 IndicatorStatus_Unchecked
,
91 // ----------------------------------------------------------------------------
92 // wxWin32Renderer: draw the GUI elements in Win32 style
93 // ----------------------------------------------------------------------------
95 class wxWin32Renderer
: public wxRenderer
114 Arrow_InversedDisabled
,
119 wxWin32Renderer(const wxColourScheme
*scheme
);
121 // implement the base class pure virtuals
122 virtual void DrawBackground(wxDC
& dc
,
126 virtual void DrawLabel(wxDC
& dc
,
127 const wxString
& label
,
130 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
132 wxRect
*rectBounds
= NULL
);
133 virtual void DrawButtonLabel(wxDC
& dc
,
134 const wxString
& label
,
135 const wxBitmap
& image
,
138 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
140 wxRect
*rectBounds
= NULL
);
141 virtual void DrawBorder(wxDC
& dc
,
145 wxRect
*rectIn
= (wxRect
*)NULL
);
146 virtual void DrawHorizontalLine(wxDC
& dc
,
147 wxCoord y
, wxCoord x1
, wxCoord x2
);
148 virtual void DrawVerticalLine(wxDC
& dc
,
149 wxCoord x
, wxCoord y1
, wxCoord y2
);
150 virtual void DrawFrame(wxDC
& dc
,
151 const wxString
& label
,
154 int alignment
= wxALIGN_LEFT
,
155 int indexAccel
= -1);
156 virtual void DrawTextBorder(wxDC
& dc
,
160 wxRect
*rectIn
= (wxRect
*)NULL
);
161 virtual void DrawButtonBorder(wxDC
& dc
,
164 wxRect
*rectIn
= (wxRect
*)NULL
);
165 virtual void DrawArrow(wxDC
& dc
,
169 virtual void DrawScrollbarArrow(wxDC
& dc
,
173 { DrawArrow(dc
, dir
, rect
, flags
); }
174 virtual void DrawScrollbarThumb(wxDC
& dc
,
175 wxOrientation orient
,
178 virtual void DrawScrollbarShaft(wxDC
& dc
,
179 wxOrientation orient
,
182 virtual void DrawScrollCorner(wxDC
& dc
,
184 virtual void DrawItem(wxDC
& dc
,
185 const wxString
& label
,
188 virtual void DrawCheckItem(wxDC
& dc
,
189 const wxString
& label
,
190 const wxBitmap
& bitmap
,
193 virtual void DrawCheckButton(wxDC
& dc
,
194 const wxString
& label
,
195 const wxBitmap
& bitmap
,
198 wxAlignment align
= wxALIGN_LEFT
,
199 int indexAccel
= -1);
200 virtual void DrawRadioButton(wxDC
& dc
,
201 const wxString
& label
,
202 const wxBitmap
& bitmap
,
205 wxAlignment align
= wxALIGN_LEFT
,
206 int indexAccel
= -1);
207 virtual void DrawTextLine(wxDC
& dc
,
208 const wxString
& text
,
213 virtual void DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
);
214 virtual void DrawTab(wxDC
& dc
,
217 const wxString
& label
,
218 const wxBitmap
& bitmap
= wxNullBitmap
,
220 int indexAccel
= -1);
222 virtual void DrawSliderShaft(wxDC
& dc
,
224 wxOrientation orient
,
226 wxRect
*rectShaft
= NULL
);
227 virtual void DrawSliderThumb(wxDC
& dc
,
229 wxOrientation orient
,
231 virtual void DrawSliderTicks(wxDC
& dc
,
233 const wxSize
& sizeThumb
,
234 wxOrientation orient
,
241 virtual void DrawMenuBarItem(wxDC
& dc
,
243 const wxString
& label
,
245 int indexAccel
= -1);
246 virtual void DrawMenuItem(wxDC
& dc
,
248 const wxMenuGeometryInfo
& geometryInfo
,
249 const wxString
& label
,
250 const wxString
& accel
,
251 const wxBitmap
& bitmap
= wxNullBitmap
,
253 int indexAccel
= -1);
254 virtual void DrawMenuSeparator(wxDC
& dc
,
256 const wxMenuGeometryInfo
& geomInfo
);
258 virtual void GetComboBitmaps(wxBitmap
*bmpNormal
,
259 wxBitmap
*bmpPressed
,
260 wxBitmap
*bmpDisabled
);
262 virtual void AdjustSize(wxSize
*size
, const wxWindow
*window
);
263 virtual wxRect
GetBorderDimensions(wxBorder border
) const;
264 virtual bool AreScrollbarsInsideBorder() const;
266 virtual wxSize
GetScrollbarArrowSize() const
267 { return m_sizeScrollbarArrow
; }
268 virtual wxRect
GetScrollbarRect(const wxScrollBar
*scrollbar
,
269 wxScrollBar::Element elem
,
270 int thumbPos
= -1) const;
271 virtual wxCoord
GetScrollbarSize(const wxScrollBar
*scrollbar
);
272 virtual wxHitTest
HitTestScrollbar(const wxScrollBar
*scrollbar
,
273 const wxPoint
& pt
) const;
274 virtual wxCoord
ScrollbarToPixel(const wxScrollBar
*scrollbar
,
276 virtual int PixelToScrollbar(const wxScrollBar
*scrollbar
, wxCoord coord
);
277 virtual wxCoord
GetListboxItemHeight(wxCoord fontHeight
)
278 { return fontHeight
+ 2; }
279 virtual wxSize
GetCheckBitmapSize() const
280 { return wxSize(13, 13); }
281 virtual wxSize
GetRadioBitmapSize() const
282 { return wxSize(12, 12); }
283 virtual wxCoord
GetCheckItemMargin() const
286 virtual wxRect
GetTextTotalArea(const wxTextCtrl
*text
,
288 virtual wxRect
GetTextClientArea(const wxTextCtrl
*text
,
290 wxCoord
*extraSpaceBeyond
);
292 virtual wxSize
GetTabIndent() const { return wxSize(2, 2); }
293 virtual wxSize
GetTabPadding() const { return wxSize(6, 5); }
295 virtual wxCoord
GetSliderDim() const { return 20; }
296 virtual wxCoord
GetSliderTickLen() const { return 4; }
297 virtual wxRect
GetSliderShaftRect(const wxRect
& rect
,
298 wxOrientation orient
) const;
299 virtual wxSize
GetSliderThumbSize(const wxRect
& rect
,
300 wxOrientation orient
) const;
301 virtual wxSize
GetProgressBarStep() const { return wxSize(16, 32); }
304 virtual wxSize
GetMenuBarItemSize(const wxSize
& sizeText
) const;
305 virtual wxMenuGeometryInfo
*GetMenuGeometry(wxWindow
*win
,
306 const wxMenu
& menu
) const;
309 // helper of DrawLabel() and DrawCheckOrRadioButton()
310 void DoDrawLabel(wxDC
& dc
,
311 const wxString
& label
,
314 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
316 wxRect
*rectBounds
= NULL
,
317 const wxPoint
& focusOffset
318 = wxPoint(FOCUS_RECT_OFFSET_X
, FOCUS_RECT_OFFSET_Y
));
320 // common part of DrawLabel() and DrawItem()
321 void DrawFocusRect(wxDC
& dc
, const wxRect
& rect
);
323 // DrawLabel() and DrawButtonLabel() helper
324 void DrawLabelShadow(wxDC
& dc
,
325 const wxString
& label
,
330 // DrawButtonBorder() helper
331 void DoDrawBackground(wxDC
& dc
,
335 // DrawBorder() helpers: all of them shift and clip the DC after drawing
338 // just draw a rectangle with the given pen
339 void DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
341 // draw the lower left part of rectangle
342 void DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
344 // draw the rectange using the first brush for the left and top sides and
345 // the second one for the bottom and right ones
346 void DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
347 const wxPen
& pen1
, const wxPen
& pen2
);
349 // draw the normal 3D border
350 void DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
);
352 // draw the sunken 3D border
353 void DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
);
355 // draw the border used for scrollbar arrows
356 void DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
= FALSE
);
358 // public DrawArrow()s helper
359 void DrawArrow(wxDC
& dc
, const wxRect
& rect
,
360 wxArrowDirection arrowDir
, wxArrowStyle arrowStyle
);
362 // DrawArrowButton is used by DrawScrollbar and DrawComboButton
363 void DrawArrowButton(wxDC
& dc
, const wxRect
& rect
,
364 wxArrowDirection arrowDir
,
365 wxArrowStyle arrowStyle
);
367 // DrawCheckButton/DrawRadioButton helper
368 void DrawCheckOrRadioButton(wxDC
& dc
,
369 const wxString
& label
,
370 const wxBitmap
& bitmap
,
375 wxCoord focusOffsetY
);
377 // draw a normal or transposed line (useful for using the same code fo both
378 // horizontal and vertical widgets)
379 void DrawLine(wxDC
& dc
,
380 wxCoord x1
, wxCoord y1
,
381 wxCoord x2
, wxCoord y2
,
382 bool transpose
= FALSE
)
385 dc
.DrawLine(y1
, x1
, y2
, x2
);
387 dc
.DrawLine(x1
, y1
, x2
, y2
);
390 // get the standard check/radio button bitmap
391 wxBitmap
GetIndicator(IndicatorType indType
, int flags
);
392 wxBitmap
GetCheckBitmap(int flags
)
393 { return GetIndicator(IndicatorType_Check
, flags
); }
394 wxBitmap
GetRadioBitmap(int flags
)
395 { return GetIndicator(IndicatorType_Radio
, flags
); }
398 const wxColourScheme
*m_scheme
;
400 // the sizing parameters (TODO make them changeable)
401 wxSize m_sizeScrollbarArrow
;
403 // GDI objects we use for drawing
404 wxColour m_colDarkGrey
,
412 // first row is for the normal state, second - for the disabled
413 wxBitmap m_bmpArrows
[Arrow_StateMax
][Arrow_Max
];
416 // ----------------------------------------------------------------------------
417 // wxWin32InputHandler and derived classes: process the keyboard and mouse
418 // messages according to Windows standards
419 // ----------------------------------------------------------------------------
421 class wxWin32InputHandler
: public wxInputHandler
424 wxWin32InputHandler(wxWin32Renderer
*renderer
);
426 virtual bool HandleKey(wxControl
*control
,
427 const wxKeyEvent
& event
,
429 virtual bool HandleMouse(wxControl
*control
,
430 const wxMouseEvent
& event
);
433 wxWin32Renderer
*m_renderer
;
436 class wxWin32ScrollBarInputHandler
: public wxStdScrollBarInputHandler
439 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
440 wxInputHandler
*handler
);
442 virtual bool HandleMouse(wxControl
*control
, const wxMouseEvent
& event
);
443 virtual bool HandleMouseMove(wxControl
*control
, const wxMouseEvent
& event
);
445 virtual bool OnScrollTimer(wxScrollBar
*scrollbar
,
446 const wxControlAction
& action
);
449 virtual bool IsAllowedButton(int button
) { return button
== 1; }
451 virtual void Highlight(wxScrollBar
*scrollbar
, bool doIt
)
453 // we don't highlight anything
456 // the first and last event which caused the thumb to move
457 wxMouseEvent m_eventStartDrag
,
460 // have we paused the scrolling because the mouse moved?
463 // we remember the interval of the timer to be able to restart it
467 class wxWin32CheckboxInputHandler
: public wxStdCheckboxInputHandler
470 wxWin32CheckboxInputHandler(wxInputHandler
*handler
)
471 : wxStdCheckboxInputHandler(handler
) { }
473 virtual bool HandleKey(wxControl
*control
,
474 const wxKeyEvent
& event
,
478 class wxWin32TextCtrlInputHandler
: public wxStdTextCtrlInputHandler
481 wxWin32TextCtrlInputHandler(wxInputHandler
*handler
)
482 : wxStdTextCtrlInputHandler(handler
) { }
484 virtual bool HandleKey(wxControl
*control
,
485 const wxKeyEvent
& event
,
489 // ----------------------------------------------------------------------------
490 // wxWin32ColourScheme: uses (default) Win32 colours
491 // ----------------------------------------------------------------------------
493 class wxWin32ColourScheme
: public wxColourScheme
496 virtual wxColour
Get(StdColour col
) const;
497 virtual wxColour
GetBackground(wxWindow
*win
) const;
500 // ----------------------------------------------------------------------------
502 // ----------------------------------------------------------------------------
504 WX_DEFINE_ARRAY(wxInputHandler
*, wxArrayHandlers
);
506 class wxWin32Theme
: public wxTheme
510 virtual ~wxWin32Theme();
512 virtual wxRenderer
*GetRenderer() { return m_renderer
; }
513 virtual wxInputHandler
*GetInputHandler(const wxString
& control
);
514 virtual wxColourScheme
*GetColourScheme();
517 // get the default input handler
518 wxInputHandler
*GetDefaultInputHandler();
520 wxWin32Renderer
*m_renderer
;
522 // the names of the already created handlers and the handlers themselves
523 // (these arrays are synchronized)
524 wxSortedArrayString m_handlerNames
;
525 wxArrayHandlers m_handlers
;
527 wxWin32InputHandler
*m_handlerDefault
;
529 wxWin32ColourScheme
*m_scheme
;
531 WX_DECLARE_THEME(win32
)
534 // ----------------------------------------------------------------------------
536 // ----------------------------------------------------------------------------
540 static const char *checked_menu_xpm
[] = {
541 /* columns rows colors chars-per-pixel */
557 static const char *selected_checked_menu_xpm
[] = {
558 /* columns rows colors chars-per-pixel */
574 static const char *disabled_checked_menu_xpm
[] = {
575 /* columns rows colors chars-per-pixel */
592 static const char *selected_disabled_checked_menu_xpm
[] = {
593 /* columns rows colors chars-per-pixel */
609 // checkbox and radiobox bitmaps below
611 static const char *checked_xpm
[] = {
612 /* columns rows colors chars-per-pixel */
635 static const char *pressed_checked_xpm
[] = {
636 /* columns rows colors chars-per-pixel */
658 static const char *pressed_disabled_checked_xpm
[] = {
659 /* columns rows colors chars-per-pixel */
681 static const char *checked_item_xpm
[] = {
682 /* columns rows colors chars-per-pixel */
703 static const char *unchecked_xpm
[] = {
704 /* columns rows colors chars-per-pixel */
727 static const char *pressed_unchecked_xpm
[] = {
728 /* columns rows colors chars-per-pixel */
750 static const char *unchecked_item_xpm
[] = {
751 /* columns rows colors chars-per-pixel */
771 static const char *checked_radio_xpm
[] = {
772 /* columns rows colors chars-per-pixel */
795 static const char *pressed_checked_radio_xpm
[] = {
796 /* columns rows colors chars-per-pixel */
819 static const char *pressed_disabled_checked_radio_xpm
[] = {
820 /* columns rows colors chars-per-pixel */
843 static const char *unchecked_radio_xpm
[] = {
844 /* columns rows colors chars-per-pixel */
867 static const char *pressed_unchecked_radio_xpm
[] = {
868 /* columns rows colors chars-per-pixel */
892 bmpIndicators
[IndicatorType_Max
][IndicatorState_Max
][IndicatorStatus_Max
] =
897 { checked_xpm
, unchecked_xpm
},
900 { pressed_checked_xpm
, pressed_unchecked_xpm
},
903 { pressed_disabled_checked_xpm
, pressed_unchecked_xpm
},
909 { checked_radio_xpm
, unchecked_radio_xpm
},
912 { pressed_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
915 { pressed_disabled_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
921 { checked_menu_xpm
, NULL
},
924 { selected_checked_menu_xpm
, NULL
},
927 { disabled_checked_menu_xpm
, NULL
},
929 // disabled selected state
930 { selected_disabled_checked_menu_xpm
, NULL
},
934 // ============================================================================
936 // ============================================================================
938 WX_IMPLEMENT_THEME(wxWin32Theme
, win32
, wxTRANSLATE("Win32 theme"));
940 // ----------------------------------------------------------------------------
942 // ----------------------------------------------------------------------------
944 wxWin32Theme::wxWin32Theme()
946 m_scheme
= new wxWin32ColourScheme
;
947 m_renderer
= new wxWin32Renderer(m_scheme
);
948 m_handlerDefault
= NULL
;
951 wxWin32Theme::~wxWin32Theme()
953 size_t count
= m_handlers
.GetCount();
954 for ( size_t n
= 0; n
< count
; n
++ )
956 if ( m_handlers
[n
] != m_handlerDefault
)
957 delete m_handlers
[n
];
960 delete m_handlerDefault
;
966 wxInputHandler
*wxWin32Theme::GetDefaultInputHandler()
968 if ( !m_handlerDefault
)
970 m_handlerDefault
= new wxWin32InputHandler(m_renderer
);
973 return m_handlerDefault
;
976 wxInputHandler
*wxWin32Theme::GetInputHandler(const wxString
& control
)
978 wxInputHandler
*handler
;
979 int n
= m_handlerNames
.Index(control
);
980 if ( n
== wxNOT_FOUND
)
982 // create a new handler
983 if ( control
== wxINP_HANDLER_SCROLLBAR
)
984 handler
= new wxWin32ScrollBarInputHandler(m_renderer
,
985 GetDefaultInputHandler());
987 else if ( control
== wxINP_HANDLER_BUTTON
)
988 handler
= new wxStdButtonInputHandler(GetDefaultInputHandler());
989 #endif // wxUSE_BUTTON
991 else if ( control
== wxINP_HANDLER_CHECKBOX
)
992 handler
= new wxWin32CheckboxInputHandler(GetDefaultInputHandler());
993 #endif // wxUSE_CHECKBOX
995 else if ( control
== wxINP_HANDLER_COMBOBOX
)
996 handler
= new wxStdComboBoxInputHandler(GetDefaultInputHandler());
997 #endif // wxUSE_COMBOBOX
999 else if ( control
== wxINP_HANDLER_LISTBOX
)
1000 handler
= new wxStdListboxInputHandler(GetDefaultInputHandler());
1001 #endif // wxUSE_LISTBOX
1002 #if wxUSE_CHECKLISTBOX
1003 else if ( control
== wxINP_HANDLER_CHECKLISTBOX
)
1004 handler
= new wxStdCheckListboxInputHandler(GetDefaultInputHandler());
1005 #endif // wxUSE_CHECKLISTBOX
1007 else if ( control
== wxINP_HANDLER_TEXTCTRL
)
1008 handler
= new wxWin32TextCtrlInputHandler(GetDefaultInputHandler());
1009 #endif // wxUSE_TEXTCTRL
1011 else if ( control
== wxINP_HANDLER_SLIDER
)
1012 handler
= new wxStdSliderButtonInputHandler(GetDefaultInputHandler());
1013 #endif // wxUSE_SLIDER
1015 else if ( control
== wxINP_HANDLER_SPINBTN
)
1016 handler
= new wxStdSpinButtonInputHandler(GetDefaultInputHandler());
1017 #endif // wxUSE_SPINBTN
1019 else if ( control
== wxINP_HANDLER_NOTEBOOK
)
1020 handler
= new wxStdNotebookInputHandler(GetDefaultInputHandler());
1021 #endif // wxUSE_NOTEBOOK
1023 handler
= GetDefaultInputHandler();
1025 n
= m_handlerNames
.Add(control
);
1026 m_handlers
.Insert(handler
, n
);
1028 else // we already have it
1030 handler
= m_handlers
[n
];
1036 wxColourScheme
*wxWin32Theme::GetColourScheme()
1041 // ============================================================================
1042 // wxWin32ColourScheme
1043 // ============================================================================
1045 wxColour
wxWin32ColourScheme::GetBackground(wxWindow
*win
) const
1048 if ( win
->UseBgCol() )
1050 // use the user specified colour
1051 col
= win
->GetBackgroundColour();
1054 if ( win
->IsContainerWindow() )
1056 wxTextCtrl
*text
= wxDynamicCast(win
, wxTextCtrl
);
1059 if ( !text
->IsEnabled() ) // not IsEditable()
1061 //else: execute code below
1066 // doesn't depend on the state
1072 int flags
= win
->GetStateFlags();
1074 // the colour set by the user should be used for the normal state
1075 // and for the states for which we don't have any specific colours
1076 if ( !col
.Ok() || (flags
!= 0) )
1078 if ( wxDynamicCast(win
, wxScrollBar
) )
1079 col
= Get(flags
& wxCONTROL_PRESSED
? SCROLLBAR_PRESSED
1089 wxColour
wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col
) const
1093 case WINDOW
: return *wxWHITE
;
1095 case CONTROL_PRESSED
:
1096 case CONTROL_CURRENT
:
1097 case CONTROL
: return wxColour(0xc0c0c0);
1099 case CONTROL_TEXT
: return *wxBLACK
;
1101 case SCROLLBAR
: return wxColour(0xe0e0e0);
1102 case SCROLLBAR_PRESSED
: return *wxBLACK
;
1104 case HIGHLIGHT
: return wxColour(0x800000);
1105 case HIGHLIGHT_TEXT
: return wxColour(0xffffff);
1107 case SHADOW_DARK
: return *wxBLACK
;
1109 case CONTROL_TEXT_DISABLED
:
1110 case SHADOW_HIGHLIGHT
: return wxColour(0xe0e0e0);
1112 case SHADOW_IN
: return wxColour(0xc0c0c0);
1114 case CONTROL_TEXT_DISABLED_SHADOW
:
1115 case SHADOW_OUT
: return wxColour(0x7f7f7f);
1119 wxFAIL_MSG(_T("invalid standard colour"));
1124 // ============================================================================
1126 // ============================================================================
1128 // ----------------------------------------------------------------------------
1130 // ----------------------------------------------------------------------------
1132 wxWin32Renderer::wxWin32Renderer(const wxColourScheme
*scheme
)
1136 m_sizeScrollbarArrow
= wxSize(16, 16);
1138 // init colours and pens
1139 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
), 0, wxSOLID
);
1141 m_colDarkGrey
= wxSCHEME_COLOUR(scheme
, SHADOW_OUT
);
1142 m_penDarkGrey
= wxPen(m_colDarkGrey
, 0, wxSOLID
);
1144 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
), 0, wxSOLID
);
1146 m_colHighlight
= wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
);
1147 m_penHighlight
= wxPen(m_colHighlight
, 0, wxSOLID
);
1149 // init the arrow bitmaps
1150 static const size_t ARROW_WIDTH
= 7;
1151 static const size_t ARROW_LENGTH
= 4;
1154 wxMemoryDC dcNormal
,
1157 for ( size_t n
= 0; n
< Arrow_Max
; n
++ )
1159 bool isVertical
= n
> Arrow_Right
;
1172 // disabled arrow is larger because of the shadow
1173 m_bmpArrows
[Arrow_Normal
][n
].Create(w
, h
);
1174 m_bmpArrows
[Arrow_Disabled
][n
].Create(w
+ 1, h
+ 1);
1176 dcNormal
.SelectObject(m_bmpArrows
[Arrow_Normal
][n
]);
1177 dcDisabled
.SelectObject(m_bmpArrows
[Arrow_Disabled
][n
]);
1179 dcNormal
.SetBackground(*wxWHITE_BRUSH
);
1180 dcDisabled
.SetBackground(*wxWHITE_BRUSH
);
1184 dcNormal
.SetPen(m_penBlack
);
1185 dcDisabled
.SetPen(m_penDarkGrey
);
1187 // calculate the position of the point of the arrow
1191 x1
= (ARROW_WIDTH
- 1)/2;
1192 y1
= n
== Arrow_Up
? 0 : ARROW_LENGTH
- 1;
1196 x1
= n
== Arrow_Left
? 0 : ARROW_LENGTH
- 1;
1197 y1
= (ARROW_WIDTH
- 1)/2;
1208 for ( size_t i
= 0; i
< ARROW_LENGTH
; i
++ )
1210 dcNormal
.DrawLine(x1
, y1
, x2
, y2
);
1211 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1218 if ( n
== Arrow_Up
)
1229 else // left or right arrow
1234 if ( n
== Arrow_Left
)
1247 // draw the shadow for the disabled one
1248 dcDisabled
.SetPen(m_penHighlight
);
1253 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1257 x1
= ARROW_LENGTH
- 1;
1258 y1
= (ARROW_WIDTH
- 1)/2 + 1;
1261 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1262 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1267 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1271 x1
= ARROW_WIDTH
- 1;
1273 x2
= (ARROW_WIDTH
- 1)/2;
1275 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1276 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1281 // create the inversed bitmap but only for the right arrow as we only
1282 // use it for the menus
1283 if ( n
== Arrow_Right
)
1285 m_bmpArrows
[Arrow_Inversed
][n
].Create(w
, h
);
1286 dcInverse
.SelectObject(m_bmpArrows
[Arrow_Inversed
][n
]);
1288 dcInverse
.Blit(0, 0, w
, h
,
1291 dcInverse
.SelectObject(wxNullBitmap
);
1293 mask
= new wxMask(m_bmpArrows
[Arrow_Inversed
][n
], *wxBLACK
);
1294 m_bmpArrows
[Arrow_Inversed
][n
].SetMask(mask
);
1296 m_bmpArrows
[Arrow_InversedDisabled
][n
].Create(w
, h
);
1297 dcInverse
.SelectObject(m_bmpArrows
[Arrow_InversedDisabled
][n
]);
1299 dcInverse
.Blit(0, 0, w
, h
,
1302 dcInverse
.SelectObject(wxNullBitmap
);
1304 mask
= new wxMask(m_bmpArrows
[Arrow_InversedDisabled
][n
], *wxBLACK
);
1305 m_bmpArrows
[Arrow_InversedDisabled
][n
].SetMask(mask
);
1308 dcNormal
.SelectObject(wxNullBitmap
);
1309 dcDisabled
.SelectObject(wxNullBitmap
);
1311 mask
= new wxMask(m_bmpArrows
[Arrow_Normal
][n
], *wxWHITE
);
1312 m_bmpArrows
[Arrow_Normal
][n
].SetMask(mask
);
1313 mask
= new wxMask(m_bmpArrows
[Arrow_Disabled
][n
], *wxWHITE
);
1314 m_bmpArrows
[Arrow_Disabled
][n
].SetMask(mask
);
1316 m_bmpArrows
[Arrow_Pressed
][n
] = m_bmpArrows
[Arrow_Normal
][n
];
1320 // ----------------------------------------------------------------------------
1322 // ----------------------------------------------------------------------------
1325 The raised border in Win32 looks like this:
1327 IIIIIIIIIIIIIIIIIIIIIIB
1329 I GB I = white (HILIGHT)
1330 I GB H = light grey (LIGHT)
1331 I GB G = dark grey (SHADOI)
1332 I GB B = black (DKSHADOI)
1333 I GB I = hIghlight (COLOR_3DHILIGHT)
1335 IGGGGGGGGGGGGGGGGGGGGGB
1336 BBBBBBBBBBBBBBBBBBBBBBB
1338 The sunken border looks like this:
1340 GGGGGGGGGGGGGGGGGGGGGGI
1341 GBBBBBBBBBBBBBBBBBBBBHI
1348 GHHHHHHHHHHHHHHHHHHHHHI
1349 IIIIIIIIIIIIIIIIIIIIIII
1351 The static border (used for the controls which don't get focus) is like
1354 GGGGGGGGGGGGGGGGGGGGGGW
1362 WWWWWWWWWWWWWWWWWWWWWWW
1364 The most complicated is the double border:
1366 HHHHHHHHHHHHHHHHHHHHHHB
1367 HWWWWWWWWWWWWWWWWWWWWGB
1368 HWHHHHHHHHHHHHHHHHHHHGB
1373 HWHHHHHHHHHHHHHHHHHHHGB
1374 HGGGGGGGGGGGGGGGGGGGGGB
1375 BBBBBBBBBBBBBBBBBBBBBBB
1377 And the simple border is, well, simple:
1379 BBBBBBBBBBBBBBBBBBBBBBB
1388 BBBBBBBBBBBBBBBBBBBBBBB
1391 void wxWin32Renderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1395 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1396 dc
.DrawRectangle(*rect
);
1402 void wxWin32Renderer::DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1404 // draw the bottom and right sides
1406 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1407 rect
->GetRight() + 1, rect
->GetBottom());
1408 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1409 rect
->GetRight(), rect
->GetBottom());
1416 void wxWin32Renderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
1417 const wxPen
& pen1
, const wxPen
& pen2
)
1419 // draw the rectangle
1421 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
1422 rect
->GetLeft(), rect
->GetBottom());
1423 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
1424 rect
->GetRight(), rect
->GetTop());
1426 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1427 rect
->GetRight(), rect
->GetBottom());
1428 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1429 rect
->GetRight() + 1, rect
->GetBottom());
1435 void wxWin32Renderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
1437 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
1438 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
1441 void wxWin32Renderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
1443 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
1444 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
1447 void wxWin32Renderer::DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
)
1451 DrawRect(dc
, rect
, m_penDarkGrey
);
1453 // the arrow is usually drawn inside border of width 2 and is offset by
1454 // another pixel in both directions when it's pressed - as the border
1455 // in this case is more narrow as well, we have to adjust rect like
1463 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
1464 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
1468 void wxWin32Renderer::DrawBorder(wxDC
& dc
,
1470 const wxRect
& rectTotal
,
1471 int WXUNUSED(flags
),
1476 wxRect rect
= rectTotal
;
1480 case wxBORDER_SUNKEN
:
1481 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1483 DrawSunkenBorder(dc
, &rect
);
1487 case wxBORDER_STATIC
:
1488 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1491 case wxBORDER_RAISED
:
1492 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1494 DrawRaisedBorder(dc
, &rect
);
1498 case wxBORDER_DOUBLE
:
1499 DrawArrowBorder(dc
, &rect
);
1500 DrawRect(dc
, &rect
, m_penLightGrey
);
1503 case wxBORDER_SIMPLE
:
1504 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1506 DrawRect(dc
, &rect
, m_penBlack
);
1511 wxFAIL_MSG(_T("unknown border type"));
1514 case wxBORDER_DEFAULT
:
1523 wxRect
wxWin32Renderer::GetBorderDimensions(wxBorder border
) const
1528 case wxBORDER_RAISED
:
1529 case wxBORDER_SUNKEN
:
1530 width
= BORDER_THICKNESS
;
1533 case wxBORDER_SIMPLE
:
1534 case wxBORDER_STATIC
:
1538 case wxBORDER_DOUBLE
:
1543 wxFAIL_MSG(_T("unknown border type"));
1546 case wxBORDER_DEFAULT
:
1556 rect
.height
= width
;
1561 bool wxWin32Renderer::AreScrollbarsInsideBorder() const
1566 // ----------------------------------------------------------------------------
1568 // ----------------------------------------------------------------------------
1570 void wxWin32Renderer::DrawTextBorder(wxDC
& dc
,
1576 // text controls are not special under windows
1577 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
1580 void wxWin32Renderer::DrawButtonBorder(wxDC
& dc
,
1581 const wxRect
& rectTotal
,
1585 wxRect rect
= rectTotal
;
1587 if ( flags
& wxCONTROL_PRESSED
)
1589 // button pressed: draw a double border around it
1590 DrawRect(dc
, &rect
, m_penBlack
);
1591 DrawRect(dc
, &rect
, m_penDarkGrey
);
1595 // button not pressed
1597 if ( flags
& (wxCONTROL_FOCUSED
| wxCONTROL_ISDEFAULT
) )
1599 // button either default or focused (or both): add an extra border around it
1600 DrawRect(dc
, &rect
, m_penBlack
);
1603 // now draw a normal button
1604 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penBlack
);
1605 DrawHalfRect(dc
, &rect
, m_penDarkGrey
);
1614 // ----------------------------------------------------------------------------
1616 // ----------------------------------------------------------------------------
1618 void wxWin32Renderer::DrawHorizontalLine(wxDC
& dc
,
1619 wxCoord y
, wxCoord x1
, wxCoord x2
)
1621 dc
.SetPen(m_penDarkGrey
);
1622 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1623 dc
.SetPen(m_penHighlight
);
1625 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1628 void wxWin32Renderer::DrawVerticalLine(wxDC
& dc
,
1629 wxCoord x
, wxCoord y1
, wxCoord y2
)
1631 dc
.SetPen(m_penDarkGrey
);
1632 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1633 dc
.SetPen(m_penHighlight
);
1635 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1638 void wxWin32Renderer::DrawFrame(wxDC
& dc
,
1639 const wxString
& label
,
1645 wxCoord height
= 0; // of the label
1646 wxRect rectFrame
= rect
;
1647 if ( !label
.empty() )
1649 // the text should touch the top border of the rect, so the frame
1650 // itself should be lower
1651 dc
.GetTextExtent(label
, NULL
, &height
);
1652 rectFrame
.y
+= height
/ 2;
1653 rectFrame
.height
-= height
/ 2;
1655 // we have to draw each part of the frame individually as we can't
1656 // erase the background beyond the label as it might contain some
1657 // pixmap already, so drawing everything and then overwriting part of
1658 // the frame with label doesn't work
1660 // TODO: the +5 and space insertion should be customizable
1663 rectText
.x
= rectFrame
.x
+ 5;
1664 rectText
.y
= rect
.y
;
1665 rectText
.width
= rectFrame
.width
- 7; // +2 border width
1666 rectText
.height
= height
;
1669 label2
<< _T(' ') << label
<< _T(' ');
1670 if ( indexAccel
!= -1 )
1672 // adjust it as we prepended a space
1677 DrawLabel(dc
, label2
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
1679 StandardDrawFrame(dc
, rectFrame
, rectLabel
);
1683 // just draw the complete frame
1684 DrawShadedRect(dc
, &rectFrame
, m_penDarkGrey
, m_penHighlight
);
1685 DrawShadedRect(dc
, &rectFrame
, m_penHighlight
, m_penDarkGrey
);
1689 // ----------------------------------------------------------------------------
1691 // ----------------------------------------------------------------------------
1693 void wxWin32Renderer::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
1695 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
1696 // pixels each while we really need dots here... PS_ALTERNATE might
1697 // work, but it is for NT 5 only
1699 DrawRect(dc
, &rect
, wxPen(*wxBLACK
, 0, wxDOT
));
1701 // draw the pixels manually: note that to behave in the same manner as
1702 // DrawRect(), we must exclude the bottom and right borders from the
1704 wxCoord x1
= rect
.GetLeft(),
1706 x2
= rect
.GetRight(),
1707 y2
= rect
.GetBottom();
1709 dc
.SetPen(wxPen(*wxBLACK
, 0, wxSOLID
));
1711 // this seems to be closer than what Windows does than wxINVERT although
1712 // I'm still not sure if it's correct
1713 dc
.SetLogicalFunction(wxAND_REVERSE
);
1716 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
1717 dc
.DrawPoint(z
, rect
.GetTop());
1719 wxCoord shift
= z
== x2
? 0 : 1;
1720 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
1721 dc
.DrawPoint(x2
, z
);
1723 shift
= z
== y2
? 0 : 1;
1724 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
1725 dc
.DrawPoint(z
, y2
);
1727 shift
= z
== x1
? 0 : 1;
1728 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
1729 dc
.DrawPoint(x1
, z
);
1731 dc
.SetLogicalFunction(wxCOPY
);
1735 void wxWin32Renderer::DrawLabelShadow(wxDC
& dc
,
1736 const wxString
& label
,
1741 // draw shadow of the text
1742 dc
.SetTextForeground(m_colHighlight
);
1743 wxRect rectShadow
= rect
;
1746 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
1748 // make the text grey
1749 dc
.SetTextForeground(m_colDarkGrey
);
1752 void wxWin32Renderer::DrawLabel(wxDC
& dc
,
1753 const wxString
& label
,
1760 DoDrawLabel(dc
, label
, rect
, flags
, alignment
, indexAccel
, rectBounds
);
1763 void wxWin32Renderer::DoDrawLabel(wxDC
& dc
,
1764 const wxString
& label
,
1770 const wxPoint
& focusOffset
)
1772 // the underscores are not drawn for focused controls in wxMSW
1773 if ( flags
& wxCONTROL_FOCUSED
)
1778 if ( flags
& wxCONTROL_DISABLED
)
1780 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
1781 // currently only can happen for a menu item and it seems that Windows
1782 // doesn't draw the shadow in this case, so we don't do it neither
1783 if ( flags
& wxCONTROL_SELECTED
)
1785 // just make the label text greyed out
1786 dc
.SetTextForeground(m_colDarkGrey
);
1788 else // draw normal disabled label
1790 DrawLabelShadow(dc
, label
, rect
, alignment
, indexAccel
);
1795 dc
.DrawLabel(label
, wxNullBitmap
, rect
, alignment
, indexAccel
, &rectLabel
);
1797 if ( flags
& wxCONTROL_DISABLED
)
1799 // restore the fg colour
1800 dc
.SetTextForeground(*wxBLACK
);
1803 if ( flags
& wxCONTROL_FOCUSED
)
1805 if ( focusOffset
.x
|| focusOffset
.y
)
1807 rectLabel
.Inflate(focusOffset
.x
, focusOffset
.y
);
1810 DrawFocusRect(dc
, rectLabel
);
1814 *rectBounds
= rectLabel
;
1817 void wxWin32Renderer::DrawButtonLabel(wxDC
& dc
,
1818 const wxString
& label
,
1819 const wxBitmap
& image
,
1826 // the underscores are not drawn for focused controls in wxMSW
1827 if ( flags
& wxCONTROL_PRESSED
)
1832 wxRect rectLabel
= rect
;
1833 if ( !label
.empty() )
1835 // shift the label if a button is pressed
1836 if ( flags
& wxCONTROL_PRESSED
)
1842 if ( flags
& wxCONTROL_DISABLED
)
1844 DrawLabelShadow(dc
, label
, rectLabel
, alignment
, indexAccel
);
1847 // leave enough space for the focus rectangle
1848 if ( flags
& wxCONTROL_FOCUSED
)
1850 rectLabel
.Inflate(-2);
1854 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
1856 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
1858 if ( flags
& wxCONTROL_PRESSED
)
1860 // the focus rectangle is never pressed, so undo the shift done
1868 DrawFocusRect(dc
, rectLabel
);
1872 // ----------------------------------------------------------------------------
1873 // (check)listbox items
1874 // ----------------------------------------------------------------------------
1876 void wxWin32Renderer::DrawItem(wxDC
& dc
,
1877 const wxString
& label
,
1881 wxDCTextColourChanger
colChanger(dc
);
1883 if ( flags
& wxCONTROL_SELECTED
)
1885 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
1887 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
1888 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
1889 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
1890 dc
.DrawRectangle(rect
);
1893 wxRect rectText
= rect
;
1895 rectText
.width
-= 2;
1896 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
1898 if ( flags
& wxCONTROL_FOCUSED
)
1900 DrawFocusRect(dc
, rect
);
1904 void wxWin32Renderer::DrawCheckItem(wxDC
& dc
,
1905 const wxString
& label
,
1906 const wxBitmap
& bitmap
,
1915 else // use default bitmap
1917 bmp
= wxBitmap(flags
& wxCONTROL_CHECKED
? checked_item_xpm
1918 : unchecked_item_xpm
);
1921 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2 - 1,
1922 TRUE
/* use mask */);
1924 wxRect rectLabel
= rect
;
1925 int bmpWidth
= bmp
.GetWidth();
1926 rectLabel
.x
+= bmpWidth
;
1927 rectLabel
.width
-= bmpWidth
;
1929 DrawItem(dc
, label
, rectLabel
, flags
);
1932 // ----------------------------------------------------------------------------
1933 // check/radio buttons
1934 // ----------------------------------------------------------------------------
1936 wxBitmap
wxWin32Renderer::GetIndicator(IndicatorType indType
, int flags
)
1938 IndicatorState indState
;
1939 if ( flags
& wxCONTROL_SELECTED
)
1940 indState
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
1941 : IndicatorState_Selected
;
1942 else if ( flags
& wxCONTROL_DISABLED
)
1943 indState
= IndicatorState_Disabled
;
1944 else if ( flags
& wxCONTROL_PRESSED
)
1945 indState
= IndicatorState_Pressed
;
1947 indState
= IndicatorState_Normal
;
1949 IndicatorStatus indStatus
= flags
& wxCONTROL_CHECKED
1950 ? IndicatorStatus_Checked
1951 : IndicatorStatus_Unchecked
;
1953 const char **xpm
= bmpIndicators
[indType
][indState
][indStatus
];
1954 return xpm
? wxBitmap(xpm
) : wxNullBitmap
;
1957 void wxWin32Renderer::DrawCheckOrRadioButton(wxDC
& dc
,
1958 const wxString
& label
,
1959 const wxBitmap
& bitmap
,
1964 wxCoord focusOffsetY
)
1966 // calculate the position of the bitmap and of the label
1967 wxCoord heightBmp
= bitmap
.GetHeight();
1969 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
1972 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
1973 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
1975 // align label vertically with the bitmap - looks nicer like this
1976 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
1978 // calc horz position
1979 if ( align
== wxALIGN_RIGHT
)
1981 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
1982 rectLabel
.x
= rect
.x
+ 3;
1983 rectLabel
.SetRight(xBmp
);
1985 else // normal (checkbox to the left of the text) case
1988 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
1989 rectLabel
.SetRight(rect
.GetRight());
1992 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, TRUE
/* use mask */);
1995 dc
, label
, rectLabel
,
1997 wxALIGN_LEFT
| wxALIGN_TOP
,
1999 NULL
, // we don't need bounding rect
2000 // use custom vert focus rect offset
2001 wxPoint(FOCUS_RECT_OFFSET_X
, focusOffsetY
)
2005 void wxWin32Renderer::DrawRadioButton(wxDC
& dc
,
2006 const wxString
& label
,
2007 const wxBitmap
& bitmap
,
2013 DrawCheckOrRadioButton(dc
, label
,
2014 bitmap
.Ok() ? bitmap
: GetRadioBitmap(flags
),
2015 rect
, flags
, align
, indexAccel
,
2016 FOCUS_RECT_OFFSET_Y
); // default focus rect offset
2019 void wxWin32Renderer::DrawCheckButton(wxDC
& dc
,
2020 const wxString
& label
,
2021 const wxBitmap
& bitmap
,
2027 DrawCheckOrRadioButton(dc
, label
,
2028 bitmap
.Ok() ? bitmap
: GetCheckBitmap(flags
),
2029 rect
, flags
, align
, indexAccel
,
2030 0); // no focus rect offset for checkboxes
2033 // ----------------------------------------------------------------------------
2035 // ----------------------------------------------------------------------------
2037 void wxWin32Renderer::DrawTextLine(wxDC
& dc
,
2038 const wxString
& text
,
2044 // nothing special to do here
2045 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
2048 void wxWin32Renderer::DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
)
2050 // we don't draw them
2053 // ----------------------------------------------------------------------------
2055 // ----------------------------------------------------------------------------
2057 void wxWin32Renderer::DrawTab(wxDC
& dc
,
2058 const wxRect
& rectOrig
,
2060 const wxString
& label
,
2061 const wxBitmap
& bitmap
,
2065 wxRect rect
= rectOrig
;
2067 // the current tab is drawn indented (to the top for default case) and
2068 // bigger than the other ones
2069 const wxSize indent
= GetTabIndent();
2070 if ( flags
& wxCONTROL_SELECTED
)
2075 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2079 rect
.Inflate(indent
.x
, 0);
2081 rect
.height
+= indent
.y
;
2085 rect
.Inflate(indent
.x
, 0);
2086 rect
.height
+= indent
.y
;
2091 wxFAIL_MSG(_T("TODO"));
2096 // draw the text, image and the focus around them (if necessary)
2097 wxRect rectLabel
= rect
;
2098 rectLabel
.Deflate(1, 1);
2099 DrawButtonLabel(dc
, label
, bitmap
, rectLabel
,
2100 flags
, wxALIGN_CENTRE
, indexAccel
);
2102 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2103 static const wxCoord CUTOFF
= 2; // radius of the rounded corner
2106 x2
= rect
.GetRight(),
2107 y2
= rect
.GetBottom();
2109 // FIXME: all this code will break if the tab indent or the border width,
2110 // it is tied to the fact that both of them are equal to 2
2115 dc
.SetPen(m_penHighlight
);
2116 dc
.DrawLine(x
, y2
, x
, y
+ CUTOFF
);
2117 dc
.DrawLine(x
, y
+ CUTOFF
, x
+ CUTOFF
, y
);
2118 dc
.DrawLine(x
+ CUTOFF
, y
, x2
- CUTOFF
+ 1, y
);
2120 dc
.SetPen(m_penBlack
);
2121 dc
.DrawLine(x2
, y2
, x2
, y
+ CUTOFF
);
2122 dc
.DrawLine(x2
, y
+ CUTOFF
, x2
- CUTOFF
, y
);
2124 dc
.SetPen(m_penDarkGrey
);
2125 dc
.DrawLine(x2
- 1, y2
, x2
- 1, y
+ CUTOFF
- 1);
2127 if ( flags
& wxCONTROL_SELECTED
)
2129 dc
.SetPen(m_penLightGrey
);
2131 // overwrite the part of the border below this tab
2132 dc
.DrawLine(x
+ 1, y2
+ 1, x2
- 1, y2
+ 1);
2134 // and the shadow of the tab to the left of us
2135 dc
.DrawLine(x
+ 1, y
+ CUTOFF
+ 1, x
+ 1, y2
+ 1);
2140 dc
.SetPen(m_penHighlight
);
2141 // we need to continue one pixel further to overwrite the corner of
2142 // the border for the selected tab
2143 dc
.DrawLine(x
, y
- (flags
& wxCONTROL_SELECTED
? 1 : 0),
2145 dc
.DrawLine(x
, y2
- CUTOFF
, x
+ CUTOFF
, y2
);
2147 dc
.SetPen(m_penBlack
);
2148 dc
.DrawLine(x
+ CUTOFF
, y2
, x2
- CUTOFF
+ 1, y2
);
2149 dc
.DrawLine(x2
, y
, x2
, y2
- CUTOFF
);
2150 dc
.DrawLine(x2
, y2
- CUTOFF
, x2
- CUTOFF
, y2
);
2152 dc
.SetPen(m_penDarkGrey
);
2153 dc
.DrawLine(x
+ CUTOFF
, y2
- 1, x2
- CUTOFF
+ 1, y2
- 1);
2154 dc
.DrawLine(x2
- 1, y
, x2
- 1, y2
- CUTOFF
+ 1);
2156 if ( flags
& wxCONTROL_SELECTED
)
2158 dc
.SetPen(m_penLightGrey
);
2160 // overwrite the part of the (double!) border above this tab
2161 dc
.DrawLine(x
+ 1, y
- 1, x2
- 1, y
- 1);
2162 dc
.DrawLine(x
+ 1, y
- 2, x2
- 1, y
- 2);
2164 // and the shadow of the tab to the left of us
2165 dc
.DrawLine(x
+ 1, y2
- CUTOFF
, x
+ 1, y
- 1);
2171 wxFAIL_MSG(_T("TODO"));
2175 // ----------------------------------------------------------------------------
2177 // ----------------------------------------------------------------------------
2179 wxSize
wxWin32Renderer::GetSliderThumbSize(const wxRect
& rect
,
2180 wxOrientation orient
) const
2184 wxRect rectShaft
= GetSliderShaftRect(rect
, orient
);
2185 if ( orient
== wxHORIZONTAL
)
2187 size
.y
= rect
.height
- 6;
2188 size
.x
= wxMin(size
.y
/ 2, rectShaft
.width
);
2192 size
.x
= rect
.width
- 6;
2193 size
.y
= wxMin(size
.x
/ 2, rectShaft
.height
);
2199 wxRect
wxWin32Renderer::GetSliderShaftRect(const wxRect
& rectOrig
,
2200 wxOrientation orient
) const
2202 static const wxCoord SLIDER_MARGIN
= 6;
2204 wxRect rect
= rectOrig
;
2206 if ( orient
== wxHORIZONTAL
)
2208 // make the rect of minimal width and centre it
2209 rect
.height
= 2*BORDER_THICKNESS
;
2210 rect
.y
= rectOrig
.y
+ (rectOrig
.height
- rect
.height
) / 2;
2214 // leave margins on the sides
2215 rect
.Deflate(SLIDER_MARGIN
, 0);
2219 // same as above but in other direction
2220 rect
.width
= 2*BORDER_THICKNESS
;
2221 rect
.x
= rectOrig
.x
+ (rectOrig
.width
- rect
.width
) / 2;
2225 rect
.Deflate(0, SLIDER_MARGIN
);
2231 void wxWin32Renderer::DrawSliderShaft(wxDC
& dc
,
2232 const wxRect
& rectOrig
,
2233 wxOrientation orient
,
2237 if ( flags
& wxCONTROL_FOCUSED
)
2239 DrawFocusRect(dc
, rectOrig
);
2242 wxRect rect
= GetSliderShaftRect(rectOrig
, orient
);
2247 DrawSunkenBorder(dc
, &rect
);
2250 void wxWin32Renderer::DrawSliderThumb(wxDC
& dc
,
2252 wxOrientation orient
,
2256 we are drawing a shape of this form
2261 H DB where H is hightlight colour
2274 The interior of this shape is filled with the hatched brush if the thumb
2278 DrawBackground(dc
, wxNullColour
, rect
, flags
);
2280 bool transpose
= orient
== wxVERTICAL
;
2282 wxCoord x
, y
, x2
, y2
;
2287 x2
= rect
.GetBottom();
2288 y2
= rect
.GetRight();
2294 x2
= rect
.GetRight();
2295 y2
= rect
.GetBottom();
2298 // the size of the pointed part of the thumb
2299 wxCoord sizeArrow
= (transpose
? rect
.height
: rect
.width
) / 2;
2301 wxCoord x3
= x
+ sizeArrow
,
2302 y3
= y2
- sizeArrow
;
2304 dc
.SetPen(m_penHighlight
);
2305 DrawLine(dc
, x
, y
, x2
, y
, transpose
);
2306 DrawLine(dc
, x
, y
+ 1, x
, y2
- sizeArrow
, transpose
);
2307 DrawLine(dc
, x
, y3
, x3
, y2
, transpose
);
2309 dc
.SetPen(m_penBlack
);
2310 DrawLine(dc
, x3
, y2
, x2
, y3
, transpose
);
2311 DrawLine(dc
, x2
, y3
, x2
, y
- 1, transpose
);
2313 dc
.SetPen(m_penDarkGrey
);
2314 DrawLine(dc
, x3
, y2
- 1, x2
- 1, y3
, transpose
);
2315 DrawLine(dc
, x2
- 1, y3
, x2
- 1, y
, transpose
);
2317 if ( flags
& wxCONTROL_PRESSED
)
2319 // TODO: MSW fills the entire area inside, not just the rect
2320 wxRect rectInt
= rect
;
2322 rectInt
.SetRight(y3
);
2324 rectInt
.SetBottom(y3
);
2327 static const char *stipple_xpm
[] = {
2328 /* columns rows colors chars-per-pixel */
2336 dc
.SetBrush(wxBrush(stipple_xpm
));
2338 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, SHADOW_HIGHLIGHT
));
2339 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, CONTROL
));
2340 dc
.SetPen(*wxTRANSPARENT_PEN
);
2341 dc
.DrawRectangle(rectInt
);
2345 void wxWin32Renderer::DrawSliderTicks(wxDC
& dc
,
2347 const wxSize
& sizeThumb
,
2348 wxOrientation orient
,
2360 // the variable names correspond to horizontal case, but they can be used
2361 // for both orientations
2362 wxCoord x1
, x2
, y1
, y2
, len
, widthThumb
;
2363 if ( orient
== wxHORIZONTAL
)
2365 x1
= rect
.GetLeft();
2366 x2
= rect
.GetRight();
2368 // draw from bottom to top to leave one pixel space between the ticks
2369 // and the slider as Windows do
2370 y1
= rect
.GetBottom();
2375 widthThumb
= sizeThumb
.x
;
2380 x2
= rect
.GetBottom();
2382 y1
= rect
.GetRight();
2383 y2
= rect
.GetLeft();
2387 widthThumb
= sizeThumb
.y
;
2390 // the first tick should be positioned in such way that a thumb drawn in
2391 // the first position points down directly to it
2392 x1
+= widthThumb
/ 2;
2393 x2
-= widthThumb
/ 2;
2395 // this also means that we have slightly less space for the ticks in
2396 // between the first and the last
2399 dc
.SetPen(m_penBlack
);
2401 int range
= end
- start
;
2402 for ( int n
= 0; n
< range
; n
+= step
)
2404 wxCoord x
= x1
+ (len
*n
) / range
;
2406 DrawLine(dc
, x
, y1
, x
, y2
, orient
== wxVERTICAL
);
2409 // always draw the line at the end position
2410 DrawLine(dc
, x2
, y1
, x2
, y2
, orient
== wxVERTICAL
);
2413 // ----------------------------------------------------------------------------
2415 // ----------------------------------------------------------------------------
2419 // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2420 class WXDLLEXPORT wxWin32MenuGeometryInfo
: public wxMenuGeometryInfo
2423 virtual wxSize
GetSize() const { return m_size
; }
2425 wxCoord
GetLabelOffset() const { return m_ofsLabel
; }
2426 wxCoord
GetAccelOffset() const { return m_ofsAccel
; }
2428 wxCoord
GetItemHeight() const { return m_heightItem
; }
2431 // the total size of the menu
2434 // the offset of the start of the menu item label
2437 // the offset of the start of the accel label
2440 // the height of a normal (not separator) item
2441 wxCoord m_heightItem
;
2443 friend wxMenuGeometryInfo
*wxWin32Renderer::
2444 GetMenuGeometry(wxWindow
*, const wxMenu
&) const;
2447 #endif // wxUSE_MENUS
2449 // FIXME: all constants are hardcoded but shouldn't be
2450 static const wxCoord MENU_LEFT_MARGIN
= 9;
2451 static const wxCoord MENU_RIGHT_MARGIN
= 18;
2452 static const wxCoord MENU_VERT_MARGIN
= 3;
2454 // the margin around bitmap/check marks (on each side)
2455 static const wxCoord MENU_BMP_MARGIN
= 2;
2457 // the margin between the labels and accel strings
2458 static const wxCoord MENU_ACCEL_MARGIN
= 8;
2460 // the separator height in pixels: in fact, strangely enough, the real height
2461 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2463 static const wxCoord MENU_SEPARATOR_HEIGHT
= 3;
2465 // the size of the standard checkmark bitmap
2466 static const wxCoord MENU_CHECK_SIZE
= 9;
2468 // we can't implement these methods without wxMenuGeometryInfo implementation
2469 // which we don't have if !wxUSE_MENUS
2472 void wxWin32Renderer::DrawMenuBarItem(wxDC
& dc
,
2473 const wxRect
& rectOrig
,
2474 const wxString
& label
,
2478 wxRect rect
= rectOrig
;
2481 wxDCTextColourChanger
colChanger(dc
);
2483 if ( flags
& wxCONTROL_SELECTED
)
2485 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2487 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2488 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2489 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2490 dc
.DrawRectangle(rect
);
2493 // don't draw the focus rect around menu bar items
2494 DrawLabel(dc
, label
, rect
, flags
& ~wxCONTROL_FOCUSED
,
2495 wxALIGN_CENTRE
, indexAccel
);
2498 void wxWin32Renderer::DrawMenuItem(wxDC
& dc
,
2500 const wxMenuGeometryInfo
& gi
,
2501 const wxString
& label
,
2502 const wxString
& accel
,
2503 const wxBitmap
& bitmap
,
2507 const wxWin32MenuGeometryInfo
& geometryInfo
=
2508 (const wxWin32MenuGeometryInfo
&)gi
;
2513 rect
.width
= geometryInfo
.GetSize().x
;
2514 rect
.height
= geometryInfo
.GetItemHeight();
2516 // draw the selected item specially
2517 wxDCTextColourChanger
colChanger(dc
);
2518 if ( flags
& wxCONTROL_SELECTED
)
2520 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2522 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2523 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2524 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2525 dc
.DrawRectangle(rect
);
2528 // draw the bitmap: use the bitmap provided or the standard checkmark for
2529 // the checkable items
2530 wxBitmap bmp
= bitmap
;
2531 if ( !bmp
.Ok() && (flags
& wxCONTROL_CHECKED
) )
2533 bmp
= GetIndicator(IndicatorType_Menu
, flags
);
2538 rect
.SetRight(geometryInfo
.GetLabelOffset());
2539 wxControlRenderer::DrawBitmap(dc
, bmp
, rect
);
2543 rect
.x
= geometryInfo
.GetLabelOffset();
2544 rect
.SetRight(geometryInfo
.GetAccelOffset());
2546 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
, indexAccel
);
2548 // draw the accel string
2549 rect
.x
= geometryInfo
.GetAccelOffset();
2550 rect
.SetRight(geometryInfo
.GetSize().x
);
2552 // NB: no accel index here
2553 DrawLabel(dc
, accel
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
);
2555 // draw the submenu indicator
2556 if ( flags
& wxCONTROL_ISSUBMENU
)
2558 rect
.x
= geometryInfo
.GetSize().x
- MENU_RIGHT_MARGIN
;
2559 rect
.width
= MENU_RIGHT_MARGIN
;
2561 wxArrowStyle arrowStyle
;
2562 if ( flags
& wxCONTROL_DISABLED
)
2563 arrowStyle
= flags
& wxCONTROL_SELECTED
? Arrow_InversedDisabled
2565 else if ( flags
& wxCONTROL_SELECTED
)
2566 arrowStyle
= Arrow_Inversed
;
2568 arrowStyle
= Arrow_Normal
;
2570 DrawArrow(dc
, rect
, Arrow_Right
, arrowStyle
);
2574 void wxWin32Renderer::DrawMenuSeparator(wxDC
& dc
,
2576 const wxMenuGeometryInfo
& geomInfo
)
2578 DrawHorizontalLine(dc
, y
+ MENU_VERT_MARGIN
, 0, geomInfo
.GetSize().x
);
2581 wxSize
wxWin32Renderer::GetMenuBarItemSize(const wxSize
& sizeText
) const
2583 wxSize size
= sizeText
;
2585 // FIXME: menubar height is configurable under Windows
2592 wxMenuGeometryInfo
*wxWin32Renderer::GetMenuGeometry(wxWindow
*win
,
2593 const wxMenu
& menu
) const
2595 // prepare the dc: for now we draw all the items with the system font
2597 dc
.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
));
2599 // the height of a normal item
2600 wxCoord heightText
= dc
.GetCharHeight();
2605 // the max length of label and accel strings: the menu width is the sum of
2606 // them, even if they're for different items (as the accels should be
2609 // the max length of the bitmap is never 0 as Windows always leaves enough
2610 // space for a check mark indicator
2611 wxCoord widthLabelMax
= 0,
2613 widthBmpMax
= MENU_LEFT_MARGIN
;
2615 for ( wxMenuItemList::Node
*node
= menu
.GetMenuItems().GetFirst();
2617 node
= node
->GetNext() )
2619 // height of this item
2622 wxMenuItem
*item
= node
->GetData();
2623 if ( item
->IsSeparator() )
2625 h
= MENU_SEPARATOR_HEIGHT
;
2627 else // not separator
2632 dc
.GetTextExtent(item
->GetLabel(), &widthLabel
, NULL
);
2633 if ( widthLabel
> widthLabelMax
)
2635 widthLabelMax
= widthLabel
;
2639 dc
.GetTextExtent(item
->GetAccelString(), &widthAccel
, NULL
);
2640 if ( widthAccel
> widthAccelMax
)
2642 widthAccelMax
= widthAccel
;
2645 const wxBitmap
& bmp
= item
->GetBitmap();
2648 wxCoord widthBmp
= bmp
.GetWidth();
2649 if ( widthBmp
> widthBmpMax
)
2650 widthBmpMax
= widthBmp
;
2652 //else if ( item->IsCheckable() ): no need to check for this as
2653 // MENU_LEFT_MARGIN is big enough to show the check mark
2656 h
+= 2*MENU_VERT_MARGIN
;
2658 // remember the item position and height
2659 item
->SetGeometry(height
, h
);
2664 // bundle the metrics into a struct and return it
2665 wxWin32MenuGeometryInfo
*gi
= new wxWin32MenuGeometryInfo
;
2667 gi
->m_ofsLabel
= widthBmpMax
+ 2*MENU_BMP_MARGIN
;
2668 gi
->m_ofsAccel
= gi
->m_ofsLabel
+ widthLabelMax
;
2669 if ( widthAccelMax
> 0 )
2671 // if we actually have any accesl, add a margin
2672 gi
->m_ofsAccel
+= MENU_ACCEL_MARGIN
;
2675 gi
->m_heightItem
= heightText
+ 2*MENU_VERT_MARGIN
;
2677 gi
->m_size
.x
= gi
->m_ofsAccel
+ widthAccelMax
+ MENU_RIGHT_MARGIN
;
2678 gi
->m_size
.y
= height
;
2683 #else // !wxUSE_MENUS
2685 void wxWin32Renderer::DrawMenuBarItem(wxDC
& WXUNUSED(dc
),
2686 const wxRect
& WXUNUSED(rectOrig
),
2687 const wxString
& WXUNUSED(label
),
2688 int WXUNUSED(flags
),
2689 int WXUNUSED(indexAccel
))
2693 void wxWin32Renderer::DrawMenuItem(wxDC
& WXUNUSED(dc
),
2694 wxCoord
WXUNUSED(y
),
2695 const wxMenuGeometryInfo
& WXUNUSED(gi
),
2696 const wxString
& WXUNUSED(label
),
2697 const wxString
& WXUNUSED(accel
),
2698 const wxBitmap
& WXUNUSED(bitmap
),
2699 int WXUNUSED(flags
),
2700 int WXUNUSED(indexAccel
))
2704 void wxWin32Renderer::DrawMenuSeparator(wxDC
& WXUNUSED(dc
),
2705 wxCoord
WXUNUSED(y
),
2706 const wxMenuGeometryInfo
& WXUNUSED(gi
))
2710 wxSize
wxWin32Renderer::GetMenuBarItemSize(const wxSize
& size
) const
2715 wxMenuGeometryInfo
*
2716 wxWin32Renderer::GetMenuGeometry(wxWindow
*WXUNUSED(win
),
2717 const wxMenu
& WXUNUSED(menu
)) const
2722 #endif // wxUSE_MENUS/!wxUSE_MENUS
2724 // ----------------------------------------------------------------------------
2726 // ----------------------------------------------------------------------------
2728 void wxWin32Renderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
2729 wxBitmap
*bmpPressed
,
2730 wxBitmap
*bmpDisabled
)
2732 static const wxCoord widthCombo
= 16;
2733 static const wxCoord heightCombo
= 17;
2739 bmpNormal
->Create(widthCombo
, heightCombo
);
2740 dcMem
.SelectObject(*bmpNormal
);
2741 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2742 Arrow_Down
, Arrow_Normal
);
2747 bmpPressed
->Create(widthCombo
, heightCombo
);
2748 dcMem
.SelectObject(*bmpPressed
);
2749 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2750 Arrow_Down
, Arrow_Pressed
);
2755 bmpDisabled
->Create(widthCombo
, heightCombo
);
2756 dcMem
.SelectObject(*bmpDisabled
);
2757 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2758 Arrow_Down
, Arrow_Disabled
);
2762 // ----------------------------------------------------------------------------
2764 // ----------------------------------------------------------------------------
2766 void wxWin32Renderer::DoDrawBackground(wxDC
& dc
,
2767 const wxColour
& col
,
2770 wxBrush
brush(col
, wxSOLID
);
2772 dc
.SetPen(*wxTRANSPARENT_PEN
);
2773 dc
.DrawRectangle(rect
);
2776 void wxWin32Renderer::DrawBackground(wxDC
& dc
,
2777 const wxColour
& col
,
2781 // just fill it with the given or default bg colour
2782 wxColour colBg
= col
.Ok() ? col
: wxSCHEME_COLOUR(m_scheme
, CONTROL
);
2783 DoDrawBackground(dc
, colBg
, rect
);
2786 // ----------------------------------------------------------------------------
2788 // ----------------------------------------------------------------------------
2790 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2795 // get the bitmap for this arrow
2796 wxArrowDirection arrowDir
;
2799 case wxLEFT
: arrowDir
= Arrow_Left
; break;
2800 case wxRIGHT
: arrowDir
= Arrow_Right
; break;
2801 case wxUP
: arrowDir
= Arrow_Up
; break;
2802 case wxDOWN
: arrowDir
= Arrow_Down
; break;
2805 wxFAIL_MSG(_T("unknown arrow direction"));
2809 wxArrowStyle arrowStyle
;
2810 if ( flags
& wxCONTROL_PRESSED
)
2812 // can't be pressed and disabled
2813 arrowStyle
= Arrow_Pressed
;
2817 arrowStyle
= flags
& wxCONTROL_DISABLED
? Arrow_Disabled
: Arrow_Normal
;
2820 DrawArrowButton(dc
, rect
, arrowDir
, arrowStyle
);
2823 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2825 wxArrowDirection arrowDir
,
2826 wxArrowStyle arrowStyle
)
2828 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
2830 // under Windows the arrows always have the same size so just centre it in
2831 // the provided rectangle
2832 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
2833 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
2835 // Windows does it like this...
2836 if ( arrowDir
== Arrow_Left
)
2840 dc
.DrawBitmap(bmp
, x
, y
, TRUE
/* use mask */);
2843 void wxWin32Renderer::DrawArrowButton(wxDC
& dc
,
2844 const wxRect
& rectAll
,
2845 wxArrowDirection arrowDir
,
2846 wxArrowStyle arrowStyle
)
2848 wxRect rect
= rectAll
;
2849 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2850 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
2851 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
2854 void wxWin32Renderer::DrawScrollbarThumb(wxDC
& dc
,
2855 wxOrientation orient
,
2859 // we don't use the flags, the thumb never changes appearance
2860 wxRect rectThumb
= rect
;
2861 DrawArrowBorder(dc
, &rectThumb
);
2862 DrawBackground(dc
, wxNullColour
, rectThumb
);
2865 void wxWin32Renderer::DrawScrollbarShaft(wxDC
& dc
,
2866 wxOrientation orient
,
2867 const wxRect
& rectBar
,
2870 wxColourScheme::StdColour col
= flags
& wxCONTROL_PRESSED
2871 ? wxColourScheme::SCROLLBAR_PRESSED
2872 : wxColourScheme::SCROLLBAR
;
2873 DoDrawBackground(dc
, m_scheme
->Get(col
), rectBar
);
2876 void wxWin32Renderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
2878 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2881 wxRect
wxWin32Renderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
2882 wxScrollBar::Element elem
,
2885 return StandardGetScrollbarRect(scrollbar
, elem
,
2886 thumbPos
, m_sizeScrollbarArrow
);
2889 wxCoord
wxWin32Renderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
2891 return StandardScrollBarSize(scrollbar
, m_sizeScrollbarArrow
);
2894 wxHitTest
wxWin32Renderer::HitTestScrollbar(const wxScrollBar
*scrollbar
,
2895 const wxPoint
& pt
) const
2897 return StandardHitTestScrollbar(scrollbar
, pt
, m_sizeScrollbarArrow
);
2900 wxCoord
wxWin32Renderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
2903 return StandardScrollbarToPixel(scrollbar
, thumbPos
, m_sizeScrollbarArrow
);
2906 int wxWin32Renderer::PixelToScrollbar(const wxScrollBar
*scrollbar
,
2909 return StandardPixelToScrollbar(scrollbar
, coord
, m_sizeScrollbarArrow
);
2912 // ----------------------------------------------------------------------------
2913 // text control geometry
2914 // ----------------------------------------------------------------------------
2916 static inline int GetTextBorderWidth()
2921 wxRect
wxWin32Renderer::GetTextTotalArea(const wxTextCtrl
*text
,
2924 wxRect rectTotal
= rect
;
2926 wxCoord widthBorder
= GetTextBorderWidth();
2927 rectTotal
.Inflate(widthBorder
);
2929 // this is what Windows does
2935 wxRect
wxWin32Renderer::GetTextClientArea(const wxTextCtrl
*text
,
2937 wxCoord
*extraSpaceBeyond
)
2939 wxRect rectText
= rect
;
2941 // undo GetTextTotalArea()
2942 if ( rectText
.height
> 0 )
2945 wxCoord widthBorder
= GetTextBorderWidth();
2946 rectText
.Inflate(-widthBorder
);
2948 if ( extraSpaceBeyond
)
2949 *extraSpaceBeyond
= 0;
2954 // ----------------------------------------------------------------------------
2956 // ----------------------------------------------------------------------------
2958 void wxWin32Renderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
2961 if ( wxDynamicCast(window
, wxScrollBar
) )
2963 // we only set the width of vert scrollbars and height of the
2965 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
2966 size
->y
= m_sizeScrollbarArrow
.y
;
2968 size
->x
= m_sizeScrollbarArrow
.x
;
2970 // skip border width adjustments, they don't make sense for us
2973 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
2976 if ( wxDynamicCast(window
, wxButton
) )
2979 size
->x
+= 3*window
->GetCharWidth();
2980 #if 0 // do allow creating small buttons if wanted
2981 wxSize sizeDef
= wxButton::GetDefaultSize();
2982 if ( size
->x
< sizeDef
.x
)
2983 size
->x
= sizeDef
.x
;
2986 wxCoord heightBtn
= (11*(window
->GetCharHeight() + 8))/10;
2987 if ( size
->y
< heightBtn
- 8 )
2988 size
->y
= heightBtn
;
2992 // no border width adjustments for buttons
2995 #endif // wxUSE_BUTTON
2997 // take into account the border width
2998 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
2999 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
3000 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
3003 // ============================================================================
3005 // ============================================================================
3007 // ----------------------------------------------------------------------------
3008 // wxWin32InputHandler
3009 // ----------------------------------------------------------------------------
3011 wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer
*renderer
)
3013 m_renderer
= renderer
;
3016 bool wxWin32InputHandler::HandleKey(wxControl
*control
,
3017 const wxKeyEvent
& event
,
3023 bool wxWin32InputHandler::HandleMouse(wxControl
*control
,
3024 const wxMouseEvent
& event
)
3029 // ----------------------------------------------------------------------------
3030 // wxWin32ScrollBarInputHandler
3031 // ----------------------------------------------------------------------------
3033 wxWin32ScrollBarInputHandler::
3034 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
3035 wxInputHandler
*handler
)
3036 : wxStdScrollBarInputHandler(renderer
, handler
)
3038 m_scrollPaused
= FALSE
;
3042 bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar
*scrollbar
,
3043 const wxControlAction
& action
)
3045 // stop if went beyond the position of the original click (this can only
3046 // happen when we scroll by pages)
3048 if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
3050 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3051 != wxHT_SCROLLBAR_BAR_2
;
3053 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
3055 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3056 != wxHT_SCROLLBAR_BAR_1
;
3061 StopScrolling(scrollbar
);
3063 scrollbar
->Refresh();
3068 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar
, action
);
3071 bool wxWin32ScrollBarInputHandler::HandleMouse(wxControl
*control
,
3072 const wxMouseEvent
& event
)
3074 // remember the current state
3075 bool wasDraggingThumb
= m_htLast
== wxHT_SCROLLBAR_THUMB
;
3077 // do process the message
3078 bool rc
= wxStdScrollBarInputHandler::HandleMouse(control
, event
);
3080 // analyse the changes
3081 if ( !wasDraggingThumb
&& (m_htLast
== wxHT_SCROLLBAR_THUMB
) )
3083 // we just started dragging the thumb, remember its initial position to
3084 // be able to restore it if the drag is cancelled later
3085 m_eventStartDrag
= event
;
3091 bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl
*control
,
3092 const wxMouseEvent
& event
)
3094 // we don't highlight scrollbar elements, so there is no need to process
3095 // mouse move events normally - only do it while mouse is captured (i.e.
3096 // when we're dragging the thumb or pressing on something)
3097 if ( !m_winCapture
)
3100 if ( event
.Entering() )
3102 // we're not interested in this at all
3106 wxScrollBar
*scrollbar
= wxStaticCast(control
, wxScrollBar
);
3108 if ( m_scrollPaused
)
3110 // check if the mouse returned to its original location
3112 if ( event
.Leaving() )
3118 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3119 if ( ht
== m_htLast
)
3121 // yes it did, resume scrolling
3122 m_scrollPaused
= FALSE
;
3123 if ( m_timerScroll
)
3125 // we were scrolling by line/page, restart timer
3126 m_timerScroll
->Start(m_interval
);
3128 Press(scrollbar
, TRUE
);
3130 else // we were dragging the thumb
3132 // restore its last location
3133 HandleThumbMove(scrollbar
, m_eventLastDrag
);
3139 else // normal case, scrolling hasn't been paused
3141 // if we're scrolling the scrollbar because the arrow or the shaft was
3142 // pressed, check that the mouse stays on the same scrollbar element
3144 if ( event
.Moving() )
3146 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3148 else // event.Leaving()
3153 // if we're dragging the thumb and the mouse stays in the scrollbar, it
3154 // is still ok - we only want to catch the case when the mouse leaves
3155 // the scrollbar here
3156 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
&& ht
!= wxHT_NOWHERE
)
3158 ht
= wxHT_SCROLLBAR_THUMB
;
3161 if ( ht
!= m_htLast
)
3163 // what were we doing? 2 possibilities: either an arrow/shaft was
3164 // pressed in which case we have a timer and so we just stop it or
3165 // we were dragging the thumb
3166 if ( m_timerScroll
)
3169 m_interval
= m_timerScroll
->GetInterval();
3170 m_timerScroll
->Stop();
3171 m_scrollPaused
= TRUE
;
3173 // unpress the arrow
3174 Press(scrollbar
, FALSE
);
3176 else // we were dragging the thumb
3178 // remember the current thumb position to be able to restore it
3179 // if the mouse returns to it later
3180 m_eventLastDrag
= event
;
3182 // and restore the original position (before dragging) of the
3184 HandleThumbMove(scrollbar
, m_eventStartDrag
);
3191 return wxStdScrollBarInputHandler::HandleMouseMove(control
, event
);
3194 // ----------------------------------------------------------------------------
3195 // wxWin32CheckboxInputHandler
3196 // ----------------------------------------------------------------------------
3198 bool wxWin32CheckboxInputHandler::HandleKey(wxControl
*control
,
3199 const wxKeyEvent
& event
,
3204 wxControlAction action
;
3205 int keycode
= event
.GetKeyCode();
3209 action
= wxACTION_CHECKBOX_TOGGLE
;
3213 case WXK_NUMPAD_SUBTRACT
:
3214 action
= wxACTION_CHECKBOX_CHECK
;
3218 case WXK_NUMPAD_ADD
:
3219 case WXK_NUMPAD_EQUAL
:
3220 action
= wxACTION_CHECKBOX_CLEAR
;
3226 control
->PerformAction(action
);
3235 // ----------------------------------------------------------------------------
3236 // wxWin32TextCtrlInputHandler
3237 // ----------------------------------------------------------------------------
3239 bool wxWin32TextCtrlInputHandler::HandleKey(wxControl
*control
,
3240 const wxKeyEvent
& event
,
3243 // handle only MSW-specific text bindings here, the others are handled in
3247 int keycode
= event
.GetKeyCode();
3249 wxControlAction action
;
3250 if ( keycode
== WXK_DELETE
&& event
.ShiftDown() )
3252 action
= wxACTION_TEXT_CUT
;
3254 else if ( keycode
== WXK_INSERT
)
3256 if ( event
.ControlDown() )
3257 action
= wxACTION_TEXT_COPY
;
3258 else if ( event
.ShiftDown() )
3259 action
= wxACTION_TEXT_PASTE
;
3262 if ( action
!= wxACTION_NONE
)
3264 control
->PerformAction(action
);
3270 return wxStdTextCtrlInputHandler::HandleKey(control
, event
, pressed
);