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
);
2414 // ----------------------------------------------------------------------------
2416 // ----------------------------------------------------------------------------
2420 // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2421 class WXDLLEXPORT wxWin32MenuGeometryInfo
: public wxMenuGeometryInfo
2424 virtual wxSize
GetSize() const { return m_size
; }
2426 wxCoord
GetLabelOffset() const { return m_ofsLabel
; }
2427 wxCoord
GetAccelOffset() const { return m_ofsAccel
; }
2429 wxCoord
GetItemHeight() const { return m_heightItem
; }
2432 // the total size of the menu
2435 // the offset of the start of the menu item label
2438 // the offset of the start of the accel label
2441 // the height of a normal (not separator) item
2442 wxCoord m_heightItem
;
2444 friend wxMenuGeometryInfo
*wxWin32Renderer::
2445 GetMenuGeometry(wxWindow
*, const wxMenu
&) const;
2448 #endif // wxUSE_WAVE
2450 // FIXME: all constants are hardcoded but shouldn't be
2451 static const wxCoord MENU_LEFT_MARGIN
= 9;
2452 static const wxCoord MENU_RIGHT_MARGIN
= 18;
2453 static const wxCoord MENU_VERT_MARGIN
= 3;
2455 // the margin around bitmap/check marks (on each side)
2456 static const wxCoord MENU_BMP_MARGIN
= 2;
2458 // the margin between the labels and accel strings
2459 static const wxCoord MENU_ACCEL_MARGIN
= 8;
2461 // the separator height in pixels: in fact, strangely enough, the real height
2462 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2464 static const wxCoord MENU_SEPARATOR_HEIGHT
= 3;
2466 // the size of the standard checkmark bitmap
2467 static const wxCoord MENU_CHECK_SIZE
= 9;
2469 // we can't implement these methods without wxMenuGeometryInfo implementation
2470 // which we don't have if !wxUSE_MENUS
2473 void wxWin32Renderer::DrawMenuBarItem(wxDC
& dc
,
2474 const wxRect
& rectOrig
,
2475 const wxString
& label
,
2479 wxRect rect
= rectOrig
;
2482 wxDCTextColourChanger
colChanger(dc
);
2484 if ( flags
& wxCONTROL_SELECTED
)
2486 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2488 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2489 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2490 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2491 dc
.DrawRectangle(rect
);
2494 // don't draw the focus rect around menu bar items
2495 DrawLabel(dc
, label
, rect
, flags
& ~wxCONTROL_FOCUSED
,
2496 wxALIGN_CENTRE
, indexAccel
);
2499 void wxWin32Renderer::DrawMenuItem(wxDC
& dc
,
2501 const wxMenuGeometryInfo
& gi
,
2502 const wxString
& label
,
2503 const wxString
& accel
,
2504 const wxBitmap
& bitmap
,
2508 const wxWin32MenuGeometryInfo
& geometryInfo
=
2509 (const wxWin32MenuGeometryInfo
&)gi
;
2514 rect
.width
= geometryInfo
.GetSize().x
;
2515 rect
.height
= geometryInfo
.GetItemHeight();
2517 // draw the selected item specially
2518 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 // draw the bitmap: use the bitmap provided or the standard checkmark for
2530 // the checkable items
2531 wxBitmap bmp
= bitmap
;
2532 if ( !bmp
.Ok() && (flags
& wxCONTROL_CHECKED
) )
2534 bmp
= GetIndicator(IndicatorType_Menu
, flags
);
2539 rect
.SetRight(geometryInfo
.GetLabelOffset());
2540 wxControlRenderer::DrawBitmap(dc
, bmp
, rect
);
2544 rect
.x
= geometryInfo
.GetLabelOffset();
2545 rect
.SetRight(geometryInfo
.GetAccelOffset());
2547 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
, indexAccel
);
2549 // draw the accel string
2550 rect
.x
= geometryInfo
.GetAccelOffset();
2551 rect
.SetRight(geometryInfo
.GetSize().x
);
2553 // NB: no accel index here
2554 DrawLabel(dc
, accel
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
);
2556 // draw the submenu indicator
2557 if ( flags
& wxCONTROL_ISSUBMENU
)
2559 rect
.x
= geometryInfo
.GetSize().x
- MENU_RIGHT_MARGIN
;
2560 rect
.width
= MENU_RIGHT_MARGIN
;
2562 wxArrowStyle arrowStyle
;
2563 if ( flags
& wxCONTROL_DISABLED
)
2564 arrowStyle
= flags
& wxCONTROL_SELECTED
? Arrow_InversedDisabled
2566 else if ( flags
& wxCONTROL_SELECTED
)
2567 arrowStyle
= Arrow_Inversed
;
2569 arrowStyle
= Arrow_Normal
;
2571 DrawArrow(dc
, rect
, Arrow_Right
, arrowStyle
);
2575 void wxWin32Renderer::DrawMenuSeparator(wxDC
& dc
,
2577 const wxMenuGeometryInfo
& geomInfo
)
2579 DrawHorizontalLine(dc
, y
+ MENU_VERT_MARGIN
, 0, geomInfo
.GetSize().x
);
2582 wxSize
wxWin32Renderer::GetMenuBarItemSize(const wxSize
& sizeText
) const
2584 wxSize size
= sizeText
;
2586 // FIXME: menubar height is configurable under Windows
2593 wxMenuGeometryInfo
*wxWin32Renderer::GetMenuGeometry(wxWindow
*win
,
2594 const wxMenu
& menu
) const
2596 // prepare the dc: for now we draw all the items with the system font
2598 dc
.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
));
2600 // the height of a normal item
2601 wxCoord heightText
= dc
.GetCharHeight();
2606 // the max length of label and accel strings: the menu width is the sum of
2607 // them, even if they're for different items (as the accels should be
2610 // the max length of the bitmap is never 0 as Windows always leaves enough
2611 // space for a check mark indicator
2612 wxCoord widthLabelMax
= 0,
2614 widthBmpMax
= MENU_LEFT_MARGIN
;
2616 for ( wxMenuItemList::Node
*node
= menu
.GetMenuItems().GetFirst();
2618 node
= node
->GetNext() )
2620 // height of this item
2623 wxMenuItem
*item
= node
->GetData();
2624 if ( item
->IsSeparator() )
2626 h
= MENU_SEPARATOR_HEIGHT
;
2628 else // not separator
2633 dc
.GetTextExtent(item
->GetLabel(), &widthLabel
, NULL
);
2634 if ( widthLabel
> widthLabelMax
)
2636 widthLabelMax
= widthLabel
;
2640 dc
.GetTextExtent(item
->GetAccelString(), &widthAccel
, NULL
);
2641 if ( widthAccel
> widthAccelMax
)
2643 widthAccelMax
= widthAccel
;
2646 const wxBitmap
& bmp
= item
->GetBitmap();
2649 wxCoord widthBmp
= bmp
.GetWidth();
2650 if ( widthBmp
> widthBmpMax
)
2651 widthBmpMax
= widthBmp
;
2653 //else if ( item->IsCheckable() ): no need to check for this as
2654 // MENU_LEFT_MARGIN is big enough to show the check mark
2657 h
+= 2*MENU_VERT_MARGIN
;
2659 // remember the item position and height
2660 item
->SetGeometry(height
, h
);
2665 // bundle the metrics into a struct and return it
2666 wxWin32MenuGeometryInfo
*gi
= new wxWin32MenuGeometryInfo
;
2668 gi
->m_ofsLabel
= widthBmpMax
+ 2*MENU_BMP_MARGIN
;
2669 gi
->m_ofsAccel
= gi
->m_ofsLabel
+ widthLabelMax
;
2670 if ( widthAccelMax
> 0 )
2672 // if we actually have any accesl, add a margin
2673 gi
->m_ofsAccel
+= MENU_ACCEL_MARGIN
;
2676 gi
->m_heightItem
= heightText
+ 2*MENU_VERT_MARGIN
;
2678 gi
->m_size
.x
= gi
->m_ofsAccel
+ widthAccelMax
+ MENU_RIGHT_MARGIN
;
2679 gi
->m_size
.y
= height
;
2687 #else // !wxUSE_MENUS
2689 void wxWin32Renderer::DrawMenuBarItem(wxDC
& WXUNUSED(dc
),
2690 const wxRect
& WXUNUSED(rectOrig
),
2691 const wxString
& WXUNUSED(label
),
2692 int WXUNUSED(flags
),
2693 int WXUNUSED(indexAccel
))
2697 void wxWin32Renderer::DrawMenuItem(wxDC
& WXUNUSED(dc
),
2698 wxCoord
WXUNUSED(y
),
2699 const wxMenuGeometryInfo
& WXUNUSED(gi
),
2700 const wxString
& WXUNUSED(label
),
2701 const wxString
& WXUNUSED(accel
),
2702 const wxBitmap
& WXUNUSED(bitmap
),
2703 int WXUNUSED(flags
),
2704 int WXUNUSED(indexAccel
))
2708 void wxWin32Renderer::DrawMenuSeparator(wxDC
& WXUNUSED(dc
),
2709 wxCoord
WXUNUSED(y
),
2710 const wxMenuGeometryInfo
& WXUNUSED(gi
))
2714 wxSize
wxWin32Renderer::GetMenuBarItemSize(const wxSize
& size
) const
2719 wxMenuGeometryInfo
*
2720 wxWin32Renderer::GetMenuGeometry(wxWindow
*WXUNUSED(win
),
2721 const wxMenu
& WXUNUSED(menu
)) const
2726 #endif // wxUSE_MENUS/!wxUSE_MENUS
2729 // ----------------------------------------------------------------------------
2731 // ----------------------------------------------------------------------------
2733 void wxWin32Renderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
2734 wxBitmap
*bmpPressed
,
2735 wxBitmap
*bmpDisabled
)
2737 static const wxCoord widthCombo
= 16;
2738 static const wxCoord heightCombo
= 17;
2744 bmpNormal
->Create(widthCombo
, heightCombo
);
2745 dcMem
.SelectObject(*bmpNormal
);
2746 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2747 Arrow_Down
, Arrow_Normal
);
2752 bmpPressed
->Create(widthCombo
, heightCombo
);
2753 dcMem
.SelectObject(*bmpPressed
);
2754 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2755 Arrow_Down
, Arrow_Pressed
);
2760 bmpDisabled
->Create(widthCombo
, heightCombo
);
2761 dcMem
.SelectObject(*bmpDisabled
);
2762 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2763 Arrow_Down
, Arrow_Disabled
);
2767 // ----------------------------------------------------------------------------
2769 // ----------------------------------------------------------------------------
2771 void wxWin32Renderer::DoDrawBackground(wxDC
& dc
,
2772 const wxColour
& col
,
2775 wxBrush
brush(col
, wxSOLID
);
2777 dc
.SetPen(*wxTRANSPARENT_PEN
);
2778 dc
.DrawRectangle(rect
);
2781 void wxWin32Renderer::DrawBackground(wxDC
& dc
,
2782 const wxColour
& col
,
2786 // just fill it with the given or default bg colour
2787 wxColour colBg
= col
.Ok() ? col
: wxSCHEME_COLOUR(m_scheme
, CONTROL
);
2788 DoDrawBackground(dc
, colBg
, rect
);
2791 // ----------------------------------------------------------------------------
2793 // ----------------------------------------------------------------------------
2795 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2800 // get the bitmap for this arrow
2801 wxArrowDirection arrowDir
;
2804 case wxLEFT
: arrowDir
= Arrow_Left
; break;
2805 case wxRIGHT
: arrowDir
= Arrow_Right
; break;
2806 case wxUP
: arrowDir
= Arrow_Up
; break;
2807 case wxDOWN
: arrowDir
= Arrow_Down
; break;
2810 wxFAIL_MSG(_T("unknown arrow direction"));
2814 wxArrowStyle arrowStyle
;
2815 if ( flags
& wxCONTROL_PRESSED
)
2817 // can't be pressed and disabled
2818 arrowStyle
= Arrow_Pressed
;
2822 arrowStyle
= flags
& wxCONTROL_DISABLED
? Arrow_Disabled
: Arrow_Normal
;
2825 DrawArrowButton(dc
, rect
, arrowDir
, arrowStyle
);
2828 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2830 wxArrowDirection arrowDir
,
2831 wxArrowStyle arrowStyle
)
2833 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
2835 // under Windows the arrows always have the same size so just centre it in
2836 // the provided rectangle
2837 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
2838 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
2840 // Windows does it like this...
2841 if ( arrowDir
== Arrow_Left
)
2845 dc
.DrawBitmap(bmp
, x
, y
, TRUE
/* use mask */);
2848 void wxWin32Renderer::DrawArrowButton(wxDC
& dc
,
2849 const wxRect
& rectAll
,
2850 wxArrowDirection arrowDir
,
2851 wxArrowStyle arrowStyle
)
2853 wxRect rect
= rectAll
;
2854 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2855 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
2856 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
2859 void wxWin32Renderer::DrawScrollbarThumb(wxDC
& dc
,
2860 wxOrientation orient
,
2864 // we don't use the flags, the thumb never changes appearance
2865 wxRect rectThumb
= rect
;
2866 DrawArrowBorder(dc
, &rectThumb
);
2867 DrawBackground(dc
, wxNullColour
, rectThumb
);
2870 void wxWin32Renderer::DrawScrollbarShaft(wxDC
& dc
,
2871 wxOrientation orient
,
2872 const wxRect
& rectBar
,
2875 wxColourScheme::StdColour col
= flags
& wxCONTROL_PRESSED
2876 ? wxColourScheme::SCROLLBAR_PRESSED
2877 : wxColourScheme::SCROLLBAR
;
2878 DoDrawBackground(dc
, m_scheme
->Get(col
), rectBar
);
2881 void wxWin32Renderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
2883 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2886 wxRect
wxWin32Renderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
2887 wxScrollBar::Element elem
,
2890 return StandardGetScrollbarRect(scrollbar
, elem
,
2891 thumbPos
, m_sizeScrollbarArrow
);
2894 wxCoord
wxWin32Renderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
2896 return StandardScrollBarSize(scrollbar
, m_sizeScrollbarArrow
);
2899 wxHitTest
wxWin32Renderer::HitTestScrollbar(const wxScrollBar
*scrollbar
,
2900 const wxPoint
& pt
) const
2902 return StandardHitTestScrollbar(scrollbar
, pt
, m_sizeScrollbarArrow
);
2905 wxCoord
wxWin32Renderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
2908 return StandardScrollbarToPixel(scrollbar
, thumbPos
, m_sizeScrollbarArrow
);
2911 int wxWin32Renderer::PixelToScrollbar(const wxScrollBar
*scrollbar
,
2914 return StandardPixelToScrollbar(scrollbar
, coord
, m_sizeScrollbarArrow
);
2917 // ----------------------------------------------------------------------------
2918 // text control geometry
2919 // ----------------------------------------------------------------------------
2921 static inline int GetTextBorderWidth()
2926 wxRect
wxWin32Renderer::GetTextTotalArea(const wxTextCtrl
*text
,
2929 wxRect rectTotal
= rect
;
2931 wxCoord widthBorder
= GetTextBorderWidth();
2932 rectTotal
.Inflate(widthBorder
);
2934 // this is what Windows does
2940 wxRect
wxWin32Renderer::GetTextClientArea(const wxTextCtrl
*text
,
2942 wxCoord
*extraSpaceBeyond
)
2944 wxRect rectText
= rect
;
2946 // undo GetTextTotalArea()
2947 if ( rectText
.height
> 0 )
2950 wxCoord widthBorder
= GetTextBorderWidth();
2951 rectText
.Inflate(-widthBorder
);
2953 if ( extraSpaceBeyond
)
2954 *extraSpaceBeyond
= 0;
2959 // ----------------------------------------------------------------------------
2961 // ----------------------------------------------------------------------------
2963 void wxWin32Renderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
2966 if ( wxDynamicCast(window
, wxScrollBar
) )
2968 // we only set the width of vert scrollbars and height of the
2970 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
2971 size
->y
= m_sizeScrollbarArrow
.y
;
2973 size
->x
= m_sizeScrollbarArrow
.x
;
2975 // skip border width adjustments, they don't make sense for us
2978 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
2981 if ( wxDynamicCast(window
, wxButton
) )
2984 size
->x
+= 3*window
->GetCharWidth();
2985 #if 0 // do allow creating small buttons if wanted
2986 wxSize sizeDef
= wxButton::GetDefaultSize();
2987 if ( size
->x
< sizeDef
.x
)
2988 size
->x
= sizeDef
.x
;
2991 wxCoord heightBtn
= (11*(window
->GetCharHeight() + 8))/10;
2992 if ( size
->y
< heightBtn
- 8 )
2993 size
->y
= heightBtn
;
2997 // no border width adjustments for buttons
3000 #endif // wxUSE_BUTTON
3002 // take into account the border width
3003 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
3004 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
3005 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
3008 // ============================================================================
3010 // ============================================================================
3012 // ----------------------------------------------------------------------------
3013 // wxWin32InputHandler
3014 // ----------------------------------------------------------------------------
3016 wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer
*renderer
)
3018 m_renderer
= renderer
;
3021 bool wxWin32InputHandler::HandleKey(wxControl
*control
,
3022 const wxKeyEvent
& event
,
3028 bool wxWin32InputHandler::HandleMouse(wxControl
*control
,
3029 const wxMouseEvent
& event
)
3034 // ----------------------------------------------------------------------------
3035 // wxWin32ScrollBarInputHandler
3036 // ----------------------------------------------------------------------------
3038 wxWin32ScrollBarInputHandler::
3039 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
3040 wxInputHandler
*handler
)
3041 : wxStdScrollBarInputHandler(renderer
, handler
)
3043 m_scrollPaused
= FALSE
;
3047 bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar
*scrollbar
,
3048 const wxControlAction
& action
)
3050 // stop if went beyond the position of the original click (this can only
3051 // happen when we scroll by pages)
3053 if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
3055 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3056 != wxHT_SCROLLBAR_BAR_2
;
3058 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
3060 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3061 != wxHT_SCROLLBAR_BAR_1
;
3066 StopScrolling(scrollbar
);
3068 scrollbar
->Refresh();
3073 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar
, action
);
3076 bool wxWin32ScrollBarInputHandler::HandleMouse(wxControl
*control
,
3077 const wxMouseEvent
& event
)
3079 // remember the current state
3080 bool wasDraggingThumb
= m_htLast
== wxHT_SCROLLBAR_THUMB
;
3082 // do process the message
3083 bool rc
= wxStdScrollBarInputHandler::HandleMouse(control
, event
);
3085 // analyse the changes
3086 if ( !wasDraggingThumb
&& (m_htLast
== wxHT_SCROLLBAR_THUMB
) )
3088 // we just started dragging the thumb, remember its initial position to
3089 // be able to restore it if the drag is cancelled later
3090 m_eventStartDrag
= event
;
3096 bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl
*control
,
3097 const wxMouseEvent
& event
)
3099 // we don't highlight scrollbar elements, so there is no need to process
3100 // mouse move events normally - only do it while mouse is captured (i.e.
3101 // when we're dragging the thumb or pressing on something)
3102 if ( !m_winCapture
)
3105 if ( event
.Entering() )
3107 // we're not interested in this at all
3111 wxScrollBar
*scrollbar
= wxStaticCast(control
, wxScrollBar
);
3113 if ( m_scrollPaused
)
3115 // check if the mouse returned to its original location
3117 if ( event
.Leaving() )
3123 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3124 if ( ht
== m_htLast
)
3126 // yes it did, resume scrolling
3127 m_scrollPaused
= FALSE
;
3128 if ( m_timerScroll
)
3130 // we were scrolling by line/page, restart timer
3131 m_timerScroll
->Start(m_interval
);
3133 Press(scrollbar
, TRUE
);
3135 else // we were dragging the thumb
3137 // restore its last location
3138 HandleThumbMove(scrollbar
, m_eventLastDrag
);
3144 else // normal case, scrolling hasn't been paused
3146 // if we're scrolling the scrollbar because the arrow or the shaft was
3147 // pressed, check that the mouse stays on the same scrollbar element
3149 if ( event
.Moving() )
3151 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3153 else // event.Leaving()
3158 // if we're dragging the thumb and the mouse stays in the scrollbar, it
3159 // is still ok - we only want to catch the case when the mouse leaves
3160 // the scrollbar here
3161 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
&& ht
!= wxHT_NOWHERE
)
3163 ht
= wxHT_SCROLLBAR_THUMB
;
3166 if ( ht
!= m_htLast
)
3168 // what were we doing? 2 possibilities: either an arrow/shaft was
3169 // pressed in which case we have a timer and so we just stop it or
3170 // we were dragging the thumb
3171 if ( m_timerScroll
)
3174 m_interval
= m_timerScroll
->GetInterval();
3175 m_timerScroll
->Stop();
3176 m_scrollPaused
= TRUE
;
3178 // unpress the arrow
3179 Press(scrollbar
, FALSE
);
3181 else // we were dragging the thumb
3183 // remember the current thumb position to be able to restore it
3184 // if the mouse returns to it later
3185 m_eventLastDrag
= event
;
3187 // and restore the original position (before dragging) of the
3189 HandleThumbMove(scrollbar
, m_eventStartDrag
);
3196 return wxStdScrollBarInputHandler::HandleMouseMove(control
, event
);
3199 // ----------------------------------------------------------------------------
3200 // wxWin32CheckboxInputHandler
3201 // ----------------------------------------------------------------------------
3203 bool wxWin32CheckboxInputHandler::HandleKey(wxControl
*control
,
3204 const wxKeyEvent
& event
,
3209 wxControlAction action
;
3210 int keycode
= event
.GetKeyCode();
3214 action
= wxACTION_CHECKBOX_TOGGLE
;
3218 case WXK_NUMPAD_SUBTRACT
:
3219 action
= wxACTION_CHECKBOX_CHECK
;
3223 case WXK_NUMPAD_ADD
:
3224 case WXK_NUMPAD_EQUAL
:
3225 action
= wxACTION_CHECKBOX_CLEAR
;
3231 control
->PerformAction(action
);
3240 // ----------------------------------------------------------------------------
3241 // wxWin32TextCtrlInputHandler
3242 // ----------------------------------------------------------------------------
3244 bool wxWin32TextCtrlInputHandler::HandleKey(wxControl
*control
,
3245 const wxKeyEvent
& event
,
3248 // handle only MSW-specific text bindings here, the others are handled in
3252 int keycode
= event
.GetKeyCode();
3254 wxControlAction action
;
3255 if ( keycode
== WXK_DELETE
&& event
.ShiftDown() )
3257 action
= wxACTION_TEXT_CUT
;
3259 else if ( keycode
== WXK_INSERT
)
3261 if ( event
.ControlDown() )
3262 action
= wxACTION_TEXT_COPY
;
3263 else if ( event
.ShiftDown() )
3264 action
= wxACTION_TEXT_PASTE
;
3267 if ( action
!= wxACTION_NONE
)
3269 control
->PerformAction(action
);
3275 return wxStdTextCtrlInputHandler::HandleKey(control
, event
, pressed
);