1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: univ/themes/win32.cpp
3 // Purpose: wxUniversal theme implementing Win32-like LNF
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2000 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
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/scrolbar.h"
39 #include "wx/slider.h"
40 #include "wx/textctrl.h"
43 #include "wx/notebook.h"
44 #include "wx/spinbutt.h"
46 #include "wx/univ/scrtimer.h"
48 #include "wx/univ/renderer.h"
49 #include "wx/univ/inphand.h"
50 #include "wx/univ/colschem.h"
51 #include "wx/univ/theme.h"
53 // ----------------------------------------------------------------------------
55 // ----------------------------------------------------------------------------
57 static const int BORDER_THICKNESS
= 2;
59 // the offset between the label and focus rect around it
60 static const int FOCUS_RECT_OFFSET_X
= 1;
61 static const int FOCUS_RECT_OFFSET_Y
= 1;
73 IndicatorState_Normal
,
74 IndicatorState_Pressed
, // this one is for check/radioboxes
75 IndicatorState_Selected
= IndicatorState_Pressed
, // for menus
76 IndicatorState_Disabled
,
77 IndicatorState_SelectedDisabled
, // only for the menus
83 IndicatorStatus_Checked
,
84 IndicatorStatus_Unchecked
,
88 // ----------------------------------------------------------------------------
89 // wxWin32Renderer: draw the GUI elements in Win32 style
90 // ----------------------------------------------------------------------------
92 class wxWin32Renderer
: public wxRenderer
111 Arrow_InversedDisabled
,
116 wxWin32Renderer(const wxColourScheme
*scheme
);
118 // implement the base class pure virtuals
119 virtual void DrawBackground(wxDC
& dc
,
123 virtual void DrawLabel(wxDC
& dc
,
124 const wxString
& label
,
127 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
129 wxRect
*rectBounds
= NULL
);
130 virtual void DrawButtonLabel(wxDC
& dc
,
131 const wxString
& label
,
132 const wxBitmap
& image
,
135 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
137 wxRect
*rectBounds
= NULL
);
138 virtual void DrawBorder(wxDC
& dc
,
142 wxRect
*rectIn
= (wxRect
*)NULL
);
143 virtual void DrawHorizontalLine(wxDC
& dc
,
144 wxCoord y
, wxCoord x1
, wxCoord x2
);
145 virtual void DrawVerticalLine(wxDC
& dc
,
146 wxCoord x
, wxCoord y1
, wxCoord y2
);
147 virtual void DrawFrame(wxDC
& dc
,
148 const wxString
& label
,
151 int alignment
= wxALIGN_LEFT
,
152 int indexAccel
= -1);
153 virtual void DrawTextBorder(wxDC
& dc
,
157 wxRect
*rectIn
= (wxRect
*)NULL
);
158 virtual void DrawButtonBorder(wxDC
& dc
,
161 wxRect
*rectIn
= (wxRect
*)NULL
);
162 virtual void DrawArrow(wxDC
& dc
,
166 virtual void DrawScrollbarArrow(wxDC
& dc
,
170 { DrawArrow(dc
, dir
, rect
, flags
); }
171 virtual void DrawScrollbarThumb(wxDC
& dc
,
172 wxOrientation orient
,
175 virtual void DrawScrollbarShaft(wxDC
& dc
,
176 wxOrientation orient
,
179 virtual void DrawScrollCorner(wxDC
& dc
,
181 virtual void DrawItem(wxDC
& dc
,
182 const wxString
& label
,
185 virtual void DrawCheckItem(wxDC
& dc
,
186 const wxString
& label
,
187 const wxBitmap
& bitmap
,
190 virtual void DrawCheckButton(wxDC
& dc
,
191 const wxString
& label
,
192 const wxBitmap
& bitmap
,
195 wxAlignment align
= wxALIGN_LEFT
,
196 int indexAccel
= -1);
197 virtual void DrawRadioButton(wxDC
& dc
,
198 const wxString
& label
,
199 const wxBitmap
& bitmap
,
202 wxAlignment align
= wxALIGN_LEFT
,
203 int indexAccel
= -1);
204 virtual void DrawTextLine(wxDC
& dc
,
205 const wxString
& text
,
210 virtual void DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
);
211 virtual void DrawTab(wxDC
& dc
,
214 const wxString
& label
,
215 const wxBitmap
& bitmap
= wxNullBitmap
,
217 int indexAccel
= -1);
219 virtual void DrawSliderShaft(wxDC
& dc
,
221 wxOrientation orient
,
223 wxRect
*rectShaft
= NULL
);
224 virtual void DrawSliderThumb(wxDC
& dc
,
226 wxOrientation orient
,
228 virtual void DrawSliderTicks(wxDC
& dc
,
230 const wxSize
& sizeThumb
,
231 wxOrientation orient
,
237 virtual void DrawMenuBarItem(wxDC
& dc
,
239 const wxString
& label
,
241 int indexAccel
= -1);
242 virtual void DrawMenuItem(wxDC
& dc
,
244 const wxMenuGeometryInfo
& geometryInfo
,
245 const wxString
& label
,
246 const wxString
& accel
,
247 const wxBitmap
& bitmap
= wxNullBitmap
,
249 int indexAccel
= -1);
250 virtual void DrawMenuSeparator(wxDC
& dc
,
252 const wxMenuGeometryInfo
& geomInfo
);
254 virtual void GetComboBitmaps(wxBitmap
*bmpNormal
,
255 wxBitmap
*bmpPressed
,
256 wxBitmap
*bmpDisabled
);
258 virtual void AdjustSize(wxSize
*size
, const wxWindow
*window
);
259 virtual wxRect
GetBorderDimensions(wxBorder border
) const;
260 virtual bool AreScrollbarsInsideBorder() const;
262 virtual wxSize
GetScrollbarArrowSize() const
263 { return m_sizeScrollbarArrow
; }
264 virtual wxRect
GetScrollbarRect(const wxScrollBar
*scrollbar
,
265 wxScrollBar::Element elem
,
266 int thumbPos
= -1) const;
267 virtual wxCoord
GetScrollbarSize(const wxScrollBar
*scrollbar
);
268 virtual wxHitTest
HitTestScrollbar(const wxScrollBar
*scrollbar
,
269 const wxPoint
& pt
) const;
270 virtual wxCoord
ScrollbarToPixel(const wxScrollBar
*scrollbar
,
272 virtual int PixelToScrollbar(const wxScrollBar
*scrollbar
, wxCoord coord
);
273 virtual wxCoord
GetListboxItemHeight(wxCoord fontHeight
)
274 { return fontHeight
+ 2; }
275 virtual wxSize
GetCheckBitmapSize() const
276 { return wxSize(13, 13); }
277 virtual wxSize
GetRadioBitmapSize() const
278 { return wxSize(12, 12); }
279 virtual wxCoord
GetCheckItemMargin() const
282 virtual wxRect
GetTextTotalArea(const wxTextCtrl
*text
,
284 virtual wxRect
GetTextClientArea(const wxTextCtrl
*text
,
286 wxCoord
*extraSpaceBeyond
);
288 virtual wxSize
GetTabIndent() const { return wxSize(2, 2); }
289 virtual wxSize
GetTabPadding() const { return wxSize(6, 5); }
291 virtual wxCoord
GetSliderDim() const { return 20; }
292 virtual wxCoord
GetSliderTickLen() const { return 4; }
293 virtual wxRect
GetSliderShaftRect(const wxRect
& rect
,
294 wxOrientation orient
) const;
295 virtual wxSize
GetSliderThumbSize(const wxRect
& rect
,
296 wxOrientation orient
) const;
297 virtual wxSize
GetProgressBarStep() const { return wxSize(16, 32); }
299 virtual wxSize
GetMenuBarItemSize(const wxSize
& sizeText
) const;
300 virtual wxMenuGeometryInfo
*GetMenuGeometry(wxWindow
*win
,
301 const wxMenu
& menu
) const;
304 // helper of DrawLabel() and DrawCheckOrRadioButton()
305 void DoDrawLabel(wxDC
& dc
,
306 const wxString
& label
,
309 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
311 wxRect
*rectBounds
= NULL
,
312 const wxPoint
& focusOffset
313 = wxPoint(FOCUS_RECT_OFFSET_X
, FOCUS_RECT_OFFSET_Y
));
315 // common part of DrawLabel() and DrawItem()
316 void DrawFocusRect(wxDC
& dc
, const wxRect
& rect
);
318 // DrawLabel() and DrawButtonLabel() helper
319 void DrawLabelShadow(wxDC
& dc
,
320 const wxString
& label
,
325 // DrawButtonBorder() helper
326 void DoDrawBackground(wxDC
& dc
,
330 // DrawBorder() helpers: all of them shift and clip the DC after drawing
333 // just draw a rectangle with the given pen
334 void DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
336 // draw the lower left part of rectangle
337 void DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
339 // draw the rectange using the first brush for the left and top sides and
340 // the second one for the bottom and right ones
341 void DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
342 const wxPen
& pen1
, const wxPen
& pen2
);
344 // draw the normal 3D border
345 void DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
);
347 // draw the sunken 3D border
348 void DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
);
350 // draw the border used for scrollbar arrows
351 void DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
= FALSE
);
353 // public DrawArrow()s helper
354 void DrawArrow(wxDC
& dc
, const wxRect
& rect
,
355 wxArrowDirection arrowDir
, wxArrowStyle arrowStyle
);
357 // DrawArrowButton is used by DrawScrollbar and DrawComboButton
358 void DrawArrowButton(wxDC
& dc
, const wxRect
& rect
,
359 wxArrowDirection arrowDir
,
360 wxArrowStyle arrowStyle
);
362 // DrawCheckButton/DrawRadioButton helper
363 void DrawCheckOrRadioButton(wxDC
& dc
,
364 const wxString
& label
,
365 const wxBitmap
& bitmap
,
370 wxCoord focusOffsetY
);
372 // draw a normal or transposed line (useful for using the same code fo both
373 // horizontal and vertical widgets)
374 void DrawLine(wxDC
& dc
,
375 wxCoord x1
, wxCoord y1
,
376 wxCoord x2
, wxCoord y2
,
377 bool transpose
= FALSE
)
380 dc
.DrawLine(y1
, x1
, y2
, x2
);
382 dc
.DrawLine(x1
, y1
, x2
, y2
);
385 // get the standard check/radio button bitmap
386 wxBitmap
GetIndicator(IndicatorType indType
, int flags
);
387 wxBitmap
GetCheckBitmap(int flags
)
388 { return GetIndicator(IndicatorType_Check
, flags
); }
389 wxBitmap
GetRadioBitmap(int flags
)
390 { return GetIndicator(IndicatorType_Radio
, flags
); }
393 const wxColourScheme
*m_scheme
;
395 // the sizing parameters (TODO make them changeable)
396 wxSize m_sizeScrollbarArrow
;
398 // GDI objects we use for drawing
399 wxColour m_colDarkGrey
,
407 // first row is for the normal state, second - for the disabled
408 wxBitmap m_bmpArrows
[Arrow_StateMax
][Arrow_Max
];
411 // ----------------------------------------------------------------------------
412 // wxWin32InputHandler and derived classes: process the keyboard and mouse
413 // messages according to Windows standards
414 // ----------------------------------------------------------------------------
416 class wxWin32InputHandler
: public wxInputHandler
419 wxWin32InputHandler(wxWin32Renderer
*renderer
);
421 virtual bool HandleKey(wxControl
*control
,
422 const wxKeyEvent
& event
,
424 virtual bool HandleMouse(wxControl
*control
,
425 const wxMouseEvent
& event
);
428 wxWin32Renderer
*m_renderer
;
431 class wxWin32ScrollBarInputHandler
: public wxStdScrollBarInputHandler
434 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
435 wxInputHandler
*handler
);
437 virtual bool HandleMouse(wxControl
*control
, const wxMouseEvent
& event
);
438 virtual bool HandleMouseMove(wxControl
*control
, const wxMouseEvent
& event
);
440 virtual bool OnScrollTimer(wxScrollBar
*scrollbar
,
441 const wxControlAction
& action
);
444 virtual bool IsAllowedButton(int button
) { return button
== 1; }
446 virtual void Highlight(wxScrollBar
*scrollbar
, bool doIt
)
448 // we don't highlight anything
451 // the first and last event which caused the thumb to move
452 wxMouseEvent m_eventStartDrag
,
455 // have we paused the scrolling because the mouse moved?
458 // we remember the interval of the timer to be able to restart it
462 class wxWin32CheckboxInputHandler
: public wxStdCheckboxInputHandler
465 wxWin32CheckboxInputHandler(wxInputHandler
*handler
)
466 : wxStdCheckboxInputHandler(handler
) { }
468 virtual bool HandleKey(wxControl
*control
,
469 const wxKeyEvent
& event
,
473 class wxWin32TextCtrlInputHandler
: public wxStdTextCtrlInputHandler
476 wxWin32TextCtrlInputHandler(wxInputHandler
*handler
)
477 : wxStdTextCtrlInputHandler(handler
) { }
479 virtual bool HandleKey(wxControl
*control
,
480 const wxKeyEvent
& event
,
484 // ----------------------------------------------------------------------------
485 // wxWin32ColourScheme: uses (default) Win32 colours
486 // ----------------------------------------------------------------------------
488 class wxWin32ColourScheme
: public wxColourScheme
491 virtual wxColour
Get(StdColour col
) const;
492 virtual wxColour
GetBackground(wxWindow
*win
) const;
495 // ----------------------------------------------------------------------------
497 // ----------------------------------------------------------------------------
499 WX_DEFINE_ARRAY(wxInputHandler
*, wxArrayHandlers
);
501 class wxWin32Theme
: public wxTheme
505 virtual ~wxWin32Theme();
507 virtual wxRenderer
*GetRenderer() { return m_renderer
; }
508 virtual wxInputHandler
*GetInputHandler(const wxString
& control
);
509 virtual wxColourScheme
*GetColourScheme();
512 // get the default input handler
513 wxInputHandler
*GetDefaultInputHandler();
515 wxWin32Renderer
*m_renderer
;
517 // the names of the already created handlers and the handlers themselves
518 // (these arrays are synchronized)
519 wxSortedArrayString m_handlerNames
;
520 wxArrayHandlers m_handlers
;
522 wxWin32InputHandler
*m_handlerDefault
;
524 wxWin32ColourScheme
*m_scheme
;
526 WX_DECLARE_THEME(win32
)
529 // ----------------------------------------------------------------------------
531 // ----------------------------------------------------------------------------
535 static const char *checked_menu_xpm
[] = {
536 /* columns rows colors chars-per-pixel */
552 static const char *selected_checked_menu_xpm
[] = {
553 /* columns rows colors chars-per-pixel */
569 static const char *disabled_checked_menu_xpm
[] = {
570 /* columns rows colors chars-per-pixel */
587 static const char *selected_disabled_checked_menu_xpm
[] = {
588 /* columns rows colors chars-per-pixel */
604 // checkbox and radiobox bitmaps below
606 static const char *checked_xpm
[] = {
607 /* columns rows colors chars-per-pixel */
630 static const char *pressed_checked_xpm
[] = {
631 /* columns rows colors chars-per-pixel */
653 static const char *pressed_disabled_checked_xpm
[] = {
654 /* columns rows colors chars-per-pixel */
676 static const char *checked_item_xpm
[] = {
677 /* columns rows colors chars-per-pixel */
698 static const char *unchecked_xpm
[] = {
699 /* columns rows colors chars-per-pixel */
722 static const char *pressed_unchecked_xpm
[] = {
723 /* columns rows colors chars-per-pixel */
745 static const char *unchecked_item_xpm
[] = {
746 /* columns rows colors chars-per-pixel */
766 static const char *checked_radio_xpm
[] = {
767 /* columns rows colors chars-per-pixel */
790 static const char *pressed_checked_radio_xpm
[] = {
791 /* columns rows colors chars-per-pixel */
814 static const char *pressed_disabled_checked_radio_xpm
[] = {
815 /* columns rows colors chars-per-pixel */
838 static const char *unchecked_radio_xpm
[] = {
839 /* columns rows colors chars-per-pixel */
862 static const char *pressed_unchecked_radio_xpm
[] = {
863 /* columns rows colors chars-per-pixel */
887 bmpIndicators
[IndicatorType_Max
][IndicatorState_Max
][IndicatorStatus_Max
] =
892 { checked_xpm
, unchecked_xpm
},
895 { pressed_checked_xpm
, pressed_unchecked_xpm
},
898 { pressed_disabled_checked_xpm
, pressed_unchecked_xpm
},
904 { checked_radio_xpm
, unchecked_radio_xpm
},
907 { pressed_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
910 { pressed_disabled_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
916 { checked_menu_xpm
, NULL
},
919 { selected_checked_menu_xpm
, NULL
},
922 { disabled_checked_menu_xpm
, NULL
},
924 // disabled selected state
925 { selected_disabled_checked_menu_xpm
, NULL
},
929 // ============================================================================
931 // ============================================================================
933 WX_IMPLEMENT_THEME(wxWin32Theme
, win32
, wxTRANSLATE("Win32 theme"));
935 // ----------------------------------------------------------------------------
937 // ----------------------------------------------------------------------------
939 wxWin32Theme::wxWin32Theme()
941 m_scheme
= new wxWin32ColourScheme
;
942 m_renderer
= new wxWin32Renderer(m_scheme
);
943 m_handlerDefault
= NULL
;
946 wxWin32Theme::~wxWin32Theme()
948 size_t count
= m_handlers
.GetCount();
949 for ( size_t n
= 0; n
< count
; n
++ )
951 if ( m_handlers
[n
] != m_handlerDefault
)
952 delete m_handlers
[n
];
955 delete m_handlerDefault
;
961 wxInputHandler
*wxWin32Theme::GetDefaultInputHandler()
963 if ( !m_handlerDefault
)
965 m_handlerDefault
= new wxWin32InputHandler(m_renderer
);
968 return m_handlerDefault
;
971 wxInputHandler
*wxWin32Theme::GetInputHandler(const wxString
& control
)
973 wxInputHandler
*handler
;
974 int n
= m_handlerNames
.Index(control
);
975 if ( n
== wxNOT_FOUND
)
977 // create a new handler
978 if ( control
== wxINP_HANDLER_SCROLLBAR
)
979 handler
= new wxWin32ScrollBarInputHandler(m_renderer
,
980 GetDefaultInputHandler());
982 else if ( control
== wxINP_HANDLER_BUTTON
)
983 handler
= new wxStdButtonInputHandler(GetDefaultInputHandler());
984 #endif // wxUSE_BUTTON
986 else if ( control
== wxINP_HANDLER_CHECKBOX
)
987 handler
= new wxWin32CheckboxInputHandler(GetDefaultInputHandler());
988 #endif // wxUSE_CHECKBOX
990 else if ( control
== wxINP_HANDLER_COMBOBOX
)
991 handler
= new wxStdComboBoxInputHandler(GetDefaultInputHandler());
992 #endif // wxUSE_COMBOBOX
994 else if ( control
== wxINP_HANDLER_LISTBOX
)
995 handler
= new wxStdListboxInputHandler(GetDefaultInputHandler());
996 #endif // wxUSE_LISTBOX
997 #if wxUSE_CHECKLISTBOX
998 else if ( control
== wxINP_HANDLER_CHECKLISTBOX
)
999 handler
= new wxStdCheckListboxInputHandler(GetDefaultInputHandler());
1000 #endif // wxUSE_CHECKLISTBOX
1002 else if ( control
== wxINP_HANDLER_TEXTCTRL
)
1003 handler
= new wxWin32TextCtrlInputHandler(GetDefaultInputHandler());
1004 #endif // wxUSE_TEXTCTRL
1006 else if ( control
== wxINP_HANDLER_SLIDER
)
1007 handler
= new wxStdSliderButtonInputHandler(GetDefaultInputHandler());
1008 #endif // wxUSE_SLIDER
1010 else if ( control
== wxINP_HANDLER_SPINBTN
)
1011 handler
= new wxStdSpinButtonInputHandler(GetDefaultInputHandler());
1012 #endif // wxUSE_SPINBTN
1014 else if ( control
== wxINP_HANDLER_NOTEBOOK
)
1015 handler
= new wxStdNotebookInputHandler(GetDefaultInputHandler());
1016 #endif // wxUSE_NOTEBOOK
1018 handler
= GetDefaultInputHandler();
1020 n
= m_handlerNames
.Add(control
);
1021 m_handlers
.Insert(handler
, n
);
1023 else // we already have it
1025 handler
= m_handlers
[n
];
1031 wxColourScheme
*wxWin32Theme::GetColourScheme()
1036 // ============================================================================
1037 // wxWin32ColourScheme
1038 // ============================================================================
1040 wxColour
wxWin32ColourScheme::GetBackground(wxWindow
*win
) const
1043 if ( win
->UseBgCol() )
1045 // use the user specified colour
1046 col
= win
->GetBackgroundColour();
1049 if ( win
->IsContainerWindow() )
1051 wxTextCtrl
*text
= wxDynamicCast(win
, wxTextCtrl
);
1054 if ( !text
->IsEnabled() ) // not IsEditable()
1056 //else: execute code below
1061 // doesn't depend on the state
1067 int flags
= win
->GetStateFlags();
1069 // the colour set by the user should be used for the normal state
1070 // and for the states for which we don't have any specific colours
1071 if ( !col
.Ok() || (flags
!= 0) )
1073 if ( wxDynamicCast(win
, wxScrollBar
) )
1074 col
= Get(flags
& wxCONTROL_PRESSED
? SCROLLBAR_PRESSED
1084 wxColour
wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col
) const
1088 case WINDOW
: return *wxWHITE
;
1090 case CONTROL_PRESSED
:
1091 case CONTROL_CURRENT
:
1092 case CONTROL
: return wxColour(0xc0c0c0);
1094 case CONTROL_TEXT
: return *wxBLACK
;
1096 case SCROLLBAR
: return wxColour(0xe0e0e0);
1097 case SCROLLBAR_PRESSED
: return *wxBLACK
;
1099 case HIGHLIGHT
: return wxColour(0x800000);
1100 case HIGHLIGHT_TEXT
: return wxColour(0xffffff);
1102 case SHADOW_DARK
: return *wxBLACK
;
1104 case CONTROL_TEXT_DISABLED
:
1105 case SHADOW_HIGHLIGHT
: return wxColour(0xe0e0e0);
1107 case SHADOW_IN
: return wxColour(0xc0c0c0);
1109 case CONTROL_TEXT_DISABLED_SHADOW
:
1110 case SHADOW_OUT
: return wxColour(0x7f7f7f);
1114 wxFAIL_MSG(_T("invalid standard colour"));
1119 // ============================================================================
1121 // ============================================================================
1123 // ----------------------------------------------------------------------------
1125 // ----------------------------------------------------------------------------
1127 wxWin32Renderer::wxWin32Renderer(const wxColourScheme
*scheme
)
1131 m_sizeScrollbarArrow
= wxSize(16, 16);
1133 // init colours and pens
1134 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
), 0, wxSOLID
);
1136 m_colDarkGrey
= wxSCHEME_COLOUR(scheme
, SHADOW_OUT
);
1137 m_penDarkGrey
= wxPen(m_colDarkGrey
, 0, wxSOLID
);
1139 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
), 0, wxSOLID
);
1141 m_colHighlight
= wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
);
1142 m_penHighlight
= wxPen(m_colHighlight
, 0, wxSOLID
);
1144 // init the arrow bitmaps
1145 static const size_t ARROW_WIDTH
= 7;
1146 static const size_t ARROW_LENGTH
= 4;
1149 wxMemoryDC dcNormal
,
1152 for ( size_t n
= 0; n
< Arrow_Max
; n
++ )
1154 bool isVertical
= n
> Arrow_Right
;
1167 // disabled arrow is larger because of the shadow
1168 m_bmpArrows
[Arrow_Normal
][n
].Create(w
, h
);
1169 m_bmpArrows
[Arrow_Disabled
][n
].Create(w
+ 1, h
+ 1);
1171 dcNormal
.SelectObject(m_bmpArrows
[Arrow_Normal
][n
]);
1172 dcDisabled
.SelectObject(m_bmpArrows
[Arrow_Disabled
][n
]);
1174 dcNormal
.SetBackground(*wxWHITE_BRUSH
);
1175 dcDisabled
.SetBackground(*wxWHITE_BRUSH
);
1179 dcNormal
.SetPen(m_penBlack
);
1180 dcDisabled
.SetPen(m_penDarkGrey
);
1182 // calculate the position of the point of the arrow
1186 x1
= (ARROW_WIDTH
- 1)/2;
1187 y1
= n
== Arrow_Up
? 0 : ARROW_LENGTH
- 1;
1191 x1
= n
== Arrow_Left
? 0 : ARROW_LENGTH
- 1;
1192 y1
= (ARROW_WIDTH
- 1)/2;
1203 for ( size_t i
= 0; i
< ARROW_LENGTH
; i
++ )
1205 dcNormal
.DrawLine(x1
, y1
, x2
, y2
);
1206 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1213 if ( n
== Arrow_Up
)
1224 else // left or right arrow
1229 if ( n
== Arrow_Left
)
1242 // draw the shadow for the disabled one
1243 dcDisabled
.SetPen(m_penHighlight
);
1248 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1252 x1
= ARROW_LENGTH
- 1;
1253 y1
= (ARROW_WIDTH
- 1)/2 + 1;
1256 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1257 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1262 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1266 x1
= ARROW_WIDTH
- 1;
1268 x2
= (ARROW_WIDTH
- 1)/2;
1270 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1271 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1276 // create the inversed bitmap but only for the right arrow as we only
1277 // use it for the menus
1278 if ( n
== Arrow_Right
)
1280 m_bmpArrows
[Arrow_Inversed
][n
].Create(w
, h
);
1281 dcInverse
.SelectObject(m_bmpArrows
[Arrow_Inversed
][n
]);
1283 dcInverse
.Blit(0, 0, w
, h
,
1286 dcInverse
.SelectObject(wxNullBitmap
);
1288 mask
= new wxMask(m_bmpArrows
[Arrow_Inversed
][n
], *wxBLACK
);
1289 m_bmpArrows
[Arrow_Inversed
][n
].SetMask(mask
);
1291 m_bmpArrows
[Arrow_InversedDisabled
][n
].Create(w
, h
);
1292 dcInverse
.SelectObject(m_bmpArrows
[Arrow_InversedDisabled
][n
]);
1294 dcInverse
.Blit(0, 0, w
, h
,
1297 dcInverse
.SelectObject(wxNullBitmap
);
1299 mask
= new wxMask(m_bmpArrows
[Arrow_InversedDisabled
][n
], *wxBLACK
);
1300 m_bmpArrows
[Arrow_InversedDisabled
][n
].SetMask(mask
);
1303 dcNormal
.SelectObject(wxNullBitmap
);
1304 dcDisabled
.SelectObject(wxNullBitmap
);
1306 mask
= new wxMask(m_bmpArrows
[Arrow_Normal
][n
], *wxWHITE
);
1307 m_bmpArrows
[Arrow_Normal
][n
].SetMask(mask
);
1308 mask
= new wxMask(m_bmpArrows
[Arrow_Disabled
][n
], *wxWHITE
);
1309 m_bmpArrows
[Arrow_Disabled
][n
].SetMask(mask
);
1311 m_bmpArrows
[Arrow_Pressed
][n
] = m_bmpArrows
[Arrow_Normal
][n
];
1315 // ----------------------------------------------------------------------------
1317 // ----------------------------------------------------------------------------
1320 The raised border in Win32 looks like this:
1322 IIIIIIIIIIIIIIIIIIIIIIB
1324 I GB I = white (HILIGHT)
1325 I GB H = light grey (LIGHT)
1326 I GB G = dark grey (SHADOI)
1327 I GB B = black (DKSHADOI)
1328 I GB I = hIghlight (COLOR_3DHILIGHT)
1330 IGGGGGGGGGGGGGGGGGGGGGB
1331 BBBBBBBBBBBBBBBBBBBBBBB
1333 The sunken border looks like this:
1335 GGGGGGGGGGGGGGGGGGGGGGI
1336 GBBBBBBBBBBBBBBBBBBBBHI
1343 GHHHHHHHHHHHHHHHHHHHHHI
1344 IIIIIIIIIIIIIIIIIIIIIII
1346 The static border (used for the controls which don't get focus) is like
1349 GGGGGGGGGGGGGGGGGGGGGGW
1357 WWWWWWWWWWWWWWWWWWWWWWW
1359 The most complicated is the double border:
1361 HHHHHHHHHHHHHHHHHHHHHHB
1362 HWWWWWWWWWWWWWWWWWWWWGB
1363 HWHHHHHHHHHHHHHHHHHHHGB
1368 HWHHHHHHHHHHHHHHHHHHHGB
1369 HGGGGGGGGGGGGGGGGGGGGGB
1370 BBBBBBBBBBBBBBBBBBBBBBB
1372 And the simple border is, well, simple:
1374 BBBBBBBBBBBBBBBBBBBBBBB
1383 BBBBBBBBBBBBBBBBBBBBBBB
1386 void wxWin32Renderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1390 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1391 dc
.DrawRectangle(*rect
);
1397 void wxWin32Renderer::DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1399 // draw the bottom and right sides
1401 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1402 rect
->GetRight() + 1, rect
->GetBottom());
1403 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1404 rect
->GetRight(), rect
->GetBottom());
1411 void wxWin32Renderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
1412 const wxPen
& pen1
, const wxPen
& pen2
)
1414 // draw the rectangle
1416 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
1417 rect
->GetLeft(), rect
->GetBottom());
1418 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
1419 rect
->GetRight(), rect
->GetTop());
1421 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1422 rect
->GetRight(), rect
->GetBottom());
1423 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1424 rect
->GetRight() + 1, rect
->GetBottom());
1430 void wxWin32Renderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
1432 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
1433 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
1436 void wxWin32Renderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
1438 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
1439 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
1442 void wxWin32Renderer::DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
)
1446 DrawRect(dc
, rect
, m_penDarkGrey
);
1448 // the arrow is usually drawn inside border of width 2 and is offset by
1449 // another pixel in both directions when it's pressed - as the border
1450 // in this case is more narrow as well, we have to adjust rect like
1458 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
1459 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
1463 void wxWin32Renderer::DrawBorder(wxDC
& dc
,
1465 const wxRect
& rectTotal
,
1466 int WXUNUSED(flags
),
1471 wxRect rect
= rectTotal
;
1475 case wxBORDER_SUNKEN
:
1476 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1478 DrawSunkenBorder(dc
, &rect
);
1482 case wxBORDER_STATIC
:
1483 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1486 case wxBORDER_RAISED
:
1487 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1489 DrawRaisedBorder(dc
, &rect
);
1493 case wxBORDER_DOUBLE
:
1494 DrawArrowBorder(dc
, &rect
);
1495 DrawRect(dc
, &rect
, m_penLightGrey
);
1498 case wxBORDER_SIMPLE
:
1499 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1501 DrawRect(dc
, &rect
, m_penBlack
);
1506 wxFAIL_MSG(_T("unknown border type"));
1509 case wxBORDER_DEFAULT
:
1518 wxRect
wxWin32Renderer::GetBorderDimensions(wxBorder border
) const
1523 case wxBORDER_RAISED
:
1524 case wxBORDER_SUNKEN
:
1525 width
= BORDER_THICKNESS
;
1528 case wxBORDER_SIMPLE
:
1529 case wxBORDER_STATIC
:
1533 case wxBORDER_DOUBLE
:
1538 wxFAIL_MSG(_T("unknown border type"));
1541 case wxBORDER_DEFAULT
:
1551 rect
.height
= width
;
1556 bool wxWin32Renderer::AreScrollbarsInsideBorder() const
1561 // ----------------------------------------------------------------------------
1563 // ----------------------------------------------------------------------------
1565 void wxWin32Renderer::DrawTextBorder(wxDC
& dc
,
1571 // text controls are not special under windows
1572 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
1575 void wxWin32Renderer::DrawButtonBorder(wxDC
& dc
,
1576 const wxRect
& rectTotal
,
1580 wxRect rect
= rectTotal
;
1582 if ( flags
& wxCONTROL_PRESSED
)
1584 // button pressed: draw a double border around it
1585 DrawRect(dc
, &rect
, m_penBlack
);
1586 DrawRect(dc
, &rect
, m_penDarkGrey
);
1590 // button not pressed
1592 if ( flags
& (wxCONTROL_FOCUSED
| wxCONTROL_ISDEFAULT
) )
1594 // button either default or focused (or both): add an extra border around it
1595 DrawRect(dc
, &rect
, m_penBlack
);
1598 // now draw a normal button
1599 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penBlack
);
1600 DrawHalfRect(dc
, &rect
, m_penDarkGrey
);
1609 // ----------------------------------------------------------------------------
1611 // ----------------------------------------------------------------------------
1613 void wxWin32Renderer::DrawHorizontalLine(wxDC
& dc
,
1614 wxCoord y
, wxCoord x1
, wxCoord x2
)
1616 dc
.SetPen(m_penDarkGrey
);
1617 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1618 dc
.SetPen(m_penHighlight
);
1620 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1623 void wxWin32Renderer::DrawVerticalLine(wxDC
& dc
,
1624 wxCoord x
, wxCoord y1
, wxCoord y2
)
1626 dc
.SetPen(m_penDarkGrey
);
1627 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1628 dc
.SetPen(m_penHighlight
);
1630 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1633 void wxWin32Renderer::DrawFrame(wxDC
& dc
,
1634 const wxString
& label
,
1640 wxCoord height
= 0; // of the label
1641 wxRect rectFrame
= rect
;
1642 if ( !label
.empty() )
1644 // the text should touch the top border of the rect, so the frame
1645 // itself should be lower
1646 dc
.GetTextExtent(label
, NULL
, &height
);
1647 rectFrame
.y
+= height
/ 2;
1648 rectFrame
.height
-= height
/ 2;
1650 // we have to draw each part of the frame individually as we can't
1651 // erase the background beyond the label as it might contain some
1652 // pixmap already, so drawing everything and then overwriting part of
1653 // the frame with label doesn't work
1655 // TODO: the +5 and space insertion should be customizable
1658 rectText
.x
= rectFrame
.x
+ 5;
1659 rectText
.y
= rect
.y
;
1660 rectText
.width
= rectFrame
.width
- 7; // +2 border width
1661 rectText
.height
= height
;
1664 label2
<< _T(' ') << label
<< _T(' ');
1665 if ( indexAccel
!= -1 )
1667 // adjust it as we prepended a space
1672 DrawLabel(dc
, label2
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
1674 StandardDrawFrame(dc
, rectFrame
, rectLabel
);
1678 // just draw the complete frame
1679 DrawShadedRect(dc
, &rectFrame
, m_penDarkGrey
, m_penHighlight
);
1680 DrawShadedRect(dc
, &rectFrame
, m_penHighlight
, m_penDarkGrey
);
1684 // ----------------------------------------------------------------------------
1686 // ----------------------------------------------------------------------------
1688 void wxWin32Renderer::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
1690 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
1691 // pixels each while we really need dots here... PS_ALTERNATE might
1692 // work, but it is for NT 5 only
1694 DrawRect(dc
, &rect
, wxPen(*wxBLACK
, 0, wxDOT
));
1696 // draw the pixels manually: note that to behave in the same manner as
1697 // DrawRect(), we must exclude the bottom and right borders from the
1699 wxCoord x1
= rect
.GetLeft(),
1701 x2
= rect
.GetRight(),
1702 y2
= rect
.GetBottom();
1704 dc
.SetPen(wxPen(*wxBLACK
, 0, wxSOLID
));
1706 // this seems to be closer than what Windows does than wxINVERT although
1707 // I'm still not sure if it's correct
1708 dc
.SetLogicalFunction(wxAND_REVERSE
);
1711 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
1712 dc
.DrawPoint(z
, rect
.GetTop());
1714 wxCoord shift
= z
== x2
? 0 : 1;
1715 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
1716 dc
.DrawPoint(x2
, z
);
1718 shift
= z
== y2
? 0 : 1;
1719 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
1720 dc
.DrawPoint(z
, y2
);
1722 shift
= z
== x1
? 0 : 1;
1723 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
1724 dc
.DrawPoint(x1
, z
);
1726 dc
.SetLogicalFunction(wxCOPY
);
1730 void wxWin32Renderer::DrawLabelShadow(wxDC
& dc
,
1731 const wxString
& label
,
1736 // draw shadow of the text
1737 dc
.SetTextForeground(m_colHighlight
);
1738 wxRect rectShadow
= rect
;
1741 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
1743 // make the text grey
1744 dc
.SetTextForeground(m_colDarkGrey
);
1747 void wxWin32Renderer::DrawLabel(wxDC
& dc
,
1748 const wxString
& label
,
1755 DoDrawLabel(dc
, label
, rect
, flags
, alignment
, indexAccel
, rectBounds
);
1758 void wxWin32Renderer::DoDrawLabel(wxDC
& dc
,
1759 const wxString
& label
,
1765 const wxPoint
& focusOffset
)
1767 // the underscores are not drawn for focused controls in wxMSW
1768 if ( flags
& wxCONTROL_FOCUSED
)
1773 if ( flags
& wxCONTROL_DISABLED
)
1775 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
1776 // currently only can happen for a menu item and it seems that Windows
1777 // doesn't draw the shadow in this case, so we don't do it neither
1778 if ( flags
& wxCONTROL_SELECTED
)
1780 // just make the label text greyed out
1781 dc
.SetTextForeground(m_colDarkGrey
);
1783 else // draw normal disabled label
1785 DrawLabelShadow(dc
, label
, rect
, alignment
, indexAccel
);
1790 dc
.DrawLabel(label
, wxNullBitmap
, rect
, alignment
, indexAccel
, &rectLabel
);
1792 if ( flags
& wxCONTROL_DISABLED
)
1794 // restore the fg colour
1795 dc
.SetTextForeground(*wxBLACK
);
1798 if ( flags
& wxCONTROL_FOCUSED
)
1800 if ( focusOffset
.x
|| focusOffset
.y
)
1802 // before calling Inflate(), ensure that we will have a valid rect
1804 if ( rectLabel
.x
< focusOffset
.x
)
1805 rectLabel
.x
= focusOffset
.x
;
1807 if ( rectLabel
.y
< focusOffset
.y
)
1808 rectLabel
.y
= focusOffset
.y
;
1810 rectLabel
.Inflate(focusOffset
.x
, focusOffset
.y
);
1813 DrawFocusRect(dc
, rectLabel
);
1817 *rectBounds
= rectLabel
;
1820 void wxWin32Renderer::DrawButtonLabel(wxDC
& dc
,
1821 const wxString
& label
,
1822 const wxBitmap
& image
,
1829 // the underscores are not drawn for focused controls in wxMSW
1830 if ( flags
& wxCONTROL_PRESSED
)
1835 wxRect rectLabel
= rect
;
1836 if ( !label
.empty() )
1838 // shift the label if a button is pressed
1839 if ( flags
& wxCONTROL_PRESSED
)
1845 if ( flags
& wxCONTROL_DISABLED
)
1847 DrawLabelShadow(dc
, label
, rectLabel
, alignment
, indexAccel
);
1850 // leave enough space for the focus rectangle
1851 if ( flags
& wxCONTROL_FOCUSED
)
1853 rectLabel
.Inflate(-2);
1857 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
1859 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
1861 if ( flags
& wxCONTROL_PRESSED
)
1863 // the focus rectangle is never pressed, so undo the shift done
1871 DrawFocusRect(dc
, rectLabel
);
1875 // ----------------------------------------------------------------------------
1876 // (check)listbox items
1877 // ----------------------------------------------------------------------------
1879 void wxWin32Renderer::DrawItem(wxDC
& dc
,
1880 const wxString
& label
,
1884 wxDCTextColourChanger
colChanger(dc
);
1886 if ( flags
& wxCONTROL_SELECTED
)
1888 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
1890 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
1891 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
1892 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
1893 dc
.DrawRectangle(rect
);
1896 wxRect rectText
= rect
;
1898 rectText
.width
-= 2;
1899 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
1901 if ( flags
& wxCONTROL_FOCUSED
)
1903 DrawFocusRect(dc
, rect
);
1907 void wxWin32Renderer::DrawCheckItem(wxDC
& dc
,
1908 const wxString
& label
,
1909 const wxBitmap
& bitmap
,
1918 else // use default bitmap
1920 bmp
= wxBitmap(flags
& wxCONTROL_CHECKED
? checked_item_xpm
1921 : unchecked_item_xpm
);
1924 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2 - 1,
1925 TRUE
/* use mask */);
1927 wxRect rectLabel
= rect
;
1928 int bmpWidth
= bmp
.GetWidth();
1929 rectLabel
.x
+= bmpWidth
;
1930 rectLabel
.width
-= bmpWidth
;
1932 DrawItem(dc
, label
, rectLabel
, flags
);
1935 // ----------------------------------------------------------------------------
1936 // check/radio buttons
1937 // ----------------------------------------------------------------------------
1939 wxBitmap
wxWin32Renderer::GetIndicator(IndicatorType indType
, int flags
)
1941 IndicatorState indState
;
1942 if ( flags
& wxCONTROL_SELECTED
)
1943 indState
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
1944 : IndicatorState_Selected
;
1945 else if ( flags
& wxCONTROL_DISABLED
)
1946 indState
= IndicatorState_Disabled
;
1947 else if ( flags
& wxCONTROL_PRESSED
)
1948 indState
= IndicatorState_Pressed
;
1950 indState
= IndicatorState_Normal
;
1952 IndicatorStatus indStatus
= flags
& wxCONTROL_CHECKED
1953 ? IndicatorStatus_Checked
1954 : IndicatorStatus_Unchecked
;
1956 const char **xpm
= bmpIndicators
[indType
][indState
][indStatus
];
1957 return xpm
? wxBitmap(xpm
) : wxNullBitmap
;
1960 void wxWin32Renderer::DrawCheckOrRadioButton(wxDC
& dc
,
1961 const wxString
& label
,
1962 const wxBitmap
& bitmap
,
1967 wxCoord focusOffsetY
)
1969 // calculate the position of the bitmap and of the label
1970 wxCoord heightBmp
= bitmap
.GetHeight();
1972 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
1975 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
1976 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
1978 // align label vertically with the bitmap - looks nicer like this
1979 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
1981 // calc horz position
1982 if ( align
== wxALIGN_RIGHT
)
1984 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
1985 rectLabel
.x
= rect
.x
+ 3;
1986 rectLabel
.SetRight(xBmp
);
1988 else // normal (checkbox to the left of the text) case
1991 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
1992 rectLabel
.SetRight(rect
.GetRight());
1995 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, TRUE
/* use mask */);
1998 dc
, label
, rectLabel
,
2000 wxALIGN_LEFT
| wxALIGN_TOP
,
2002 NULL
, // we don't need bounding rect
2003 // use custom vert focus rect offset
2004 wxPoint(FOCUS_RECT_OFFSET_X
, focusOffsetY
)
2008 void wxWin32Renderer::DrawRadioButton(wxDC
& dc
,
2009 const wxString
& label
,
2010 const wxBitmap
& bitmap
,
2016 DrawCheckOrRadioButton(dc
, label
,
2017 bitmap
.Ok() ? bitmap
: GetRadioBitmap(flags
),
2018 rect
, flags
, align
, indexAccel
,
2019 FOCUS_RECT_OFFSET_Y
); // default focus rect offset
2022 void wxWin32Renderer::DrawCheckButton(wxDC
& dc
,
2023 const wxString
& label
,
2024 const wxBitmap
& bitmap
,
2030 DrawCheckOrRadioButton(dc
, label
,
2031 bitmap
.Ok() ? bitmap
: GetCheckBitmap(flags
),
2032 rect
, flags
, align
, indexAccel
,
2033 0); // no focus rect offset for checkboxes
2036 // ----------------------------------------------------------------------------
2038 // ----------------------------------------------------------------------------
2040 void wxWin32Renderer::DrawTextLine(wxDC
& dc
,
2041 const wxString
& text
,
2047 // nothing special to do here
2048 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
2051 void wxWin32Renderer::DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
)
2053 // we don't draw them
2056 // ----------------------------------------------------------------------------
2058 // ----------------------------------------------------------------------------
2060 void wxWin32Renderer::DrawTab(wxDC
& dc
,
2061 const wxRect
& rectOrig
,
2063 const wxString
& label
,
2064 const wxBitmap
& bitmap
,
2068 wxRect rect
= rectOrig
;
2070 // the current tab is drawn indented (to the top for default case) and
2071 // bigger than the other ones
2072 const wxSize indent
= GetTabIndent();
2073 if ( flags
& wxCONTROL_SELECTED
)
2078 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2082 rect
.Inflate(indent
.x
, 0);
2084 rect
.height
+= indent
.y
;
2088 rect
.Inflate(indent
.x
, 0);
2089 rect
.height
+= indent
.y
;
2094 wxFAIL_MSG(_T("TODO"));
2099 // draw the text, image and the focus around them (if necessary)
2100 wxRect rectLabel
= rect
;
2101 rectLabel
.Deflate(1, 1);
2102 DrawButtonLabel(dc
, label
, bitmap
, rectLabel
,
2103 flags
, wxALIGN_CENTRE
, indexAccel
);
2105 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2106 static const wxCoord CUTOFF
= 2; // radius of the rounded corner
2109 x2
= rect
.GetRight(),
2110 y2
= rect
.GetBottom();
2112 // FIXME: all this code will break if the tab indent or the border width,
2113 // it is tied to the fact that both of them are equal to 2
2118 dc
.SetPen(m_penHighlight
);
2119 dc
.DrawLine(x
, y2
, x
, y
+ CUTOFF
);
2120 dc
.DrawLine(x
, y
+ CUTOFF
, x
+ CUTOFF
, y
);
2121 dc
.DrawLine(x
+ CUTOFF
, y
, x2
- CUTOFF
+ 1, y
);
2123 dc
.SetPen(m_penBlack
);
2124 dc
.DrawLine(x2
, y2
, x2
, y
+ CUTOFF
);
2125 dc
.DrawLine(x2
, y
+ CUTOFF
, x2
- CUTOFF
, y
);
2127 dc
.SetPen(m_penDarkGrey
);
2128 dc
.DrawLine(x2
- 1, y2
, x2
- 1, y
+ CUTOFF
- 1);
2130 if ( flags
& wxCONTROL_SELECTED
)
2132 dc
.SetPen(m_penLightGrey
);
2134 // overwrite the part of the border below this tab
2135 dc
.DrawLine(x
+ 1, y2
+ 1, x2
- 1, y2
+ 1);
2137 // and the shadow of the tab to the left of us
2138 dc
.DrawLine(x
+ 1, y
+ CUTOFF
+ 1, x
+ 1, y2
+ 1);
2143 dc
.SetPen(m_penHighlight
);
2144 // we need to continue one pixel further to overwrite the corner of
2145 // the border for the selected tab
2146 dc
.DrawLine(x
, y
- (flags
& wxCONTROL_SELECTED
? 1 : 0),
2148 dc
.DrawLine(x
, y2
- CUTOFF
, x
+ CUTOFF
, y2
);
2150 dc
.SetPen(m_penBlack
);
2151 dc
.DrawLine(x
+ CUTOFF
, y2
, x2
- CUTOFF
+ 1, y2
);
2152 dc
.DrawLine(x2
, y
, x2
, y2
- CUTOFF
);
2153 dc
.DrawLine(x2
, y2
- CUTOFF
, x2
- CUTOFF
, y2
);
2155 dc
.SetPen(m_penDarkGrey
);
2156 dc
.DrawLine(x
+ CUTOFF
, y2
- 1, x2
- CUTOFF
+ 1, y2
- 1);
2157 dc
.DrawLine(x2
- 1, y
, x2
- 1, y2
- CUTOFF
+ 1);
2159 if ( flags
& wxCONTROL_SELECTED
)
2161 dc
.SetPen(m_penLightGrey
);
2163 // overwrite the part of the (double!) border above this tab
2164 dc
.DrawLine(x
+ 1, y
- 1, x2
- 1, y
- 1);
2165 dc
.DrawLine(x
+ 1, y
- 2, x2
- 1, y
- 2);
2167 // and the shadow of the tab to the left of us
2168 dc
.DrawLine(x
+ 1, y2
- CUTOFF
, x
+ 1, y
- 1);
2174 wxFAIL_MSG(_T("TODO"));
2178 // ----------------------------------------------------------------------------
2180 // ----------------------------------------------------------------------------
2182 wxSize
wxWin32Renderer::GetSliderThumbSize(const wxRect
& rect
,
2183 wxOrientation orient
) const
2187 wxRect rectShaft
= GetSliderShaftRect(rect
, orient
);
2188 if ( orient
== wxHORIZONTAL
)
2190 size
.y
= rect
.height
- 6;
2191 size
.x
= wxMin(size
.y
/ 2, rectShaft
.width
);
2195 size
.x
= rect
.width
- 6;
2196 size
.y
= wxMin(size
.x
/ 2, rectShaft
.height
);
2202 wxRect
wxWin32Renderer::GetSliderShaftRect(const wxRect
& rectOrig
,
2203 wxOrientation orient
) const
2205 static const wxCoord SLIDER_MARGIN
= 6;
2207 wxRect rect
= rectOrig
;
2209 if ( orient
== wxHORIZONTAL
)
2211 // make the rect of minimal width and centre it
2212 rect
.height
= 2*BORDER_THICKNESS
;
2213 rect
.y
= rectOrig
.y
+ (rectOrig
.height
- rect
.height
) / 2;
2217 // leave margins on the sides
2218 rect
.Deflate(SLIDER_MARGIN
, 0);
2222 // same as above but in other direction
2223 rect
.width
= 2*BORDER_THICKNESS
;
2224 rect
.x
= rectOrig
.x
+ (rectOrig
.width
- rect
.width
) / 2;
2228 rect
.Deflate(0, SLIDER_MARGIN
);
2234 void wxWin32Renderer::DrawSliderShaft(wxDC
& dc
,
2235 const wxRect
& rectOrig
,
2236 wxOrientation orient
,
2240 if ( flags
& wxCONTROL_FOCUSED
)
2242 DrawFocusRect(dc
, rectOrig
);
2245 wxRect rect
= GetSliderShaftRect(rectOrig
, orient
);
2250 DrawSunkenBorder(dc
, &rect
);
2253 void wxWin32Renderer::DrawSliderThumb(wxDC
& dc
,
2255 wxOrientation orient
,
2259 we are drawing a shape of this form
2264 H DB where H is hightlight colour
2277 The interior of this shape is filled with the hatched brush if the thumb
2281 DrawBackground(dc
, wxNullColour
, rect
, flags
);
2283 bool transpose
= orient
== wxVERTICAL
;
2285 wxCoord x
, y
, x2
, y2
;
2290 x2
= rect
.GetBottom();
2291 y2
= rect
.GetRight();
2297 x2
= rect
.GetRight();
2298 y2
= rect
.GetBottom();
2301 // the size of the pointed part of the thumb
2302 wxCoord sizeArrow
= (transpose
? rect
.height
: rect
.width
) / 2;
2304 wxCoord x3
= x
+ sizeArrow
,
2305 y3
= y2
- sizeArrow
;
2307 dc
.SetPen(m_penHighlight
);
2308 DrawLine(dc
, x
, y
, x2
, y
, transpose
);
2309 DrawLine(dc
, x
, y
+ 1, x
, y2
- sizeArrow
, transpose
);
2310 DrawLine(dc
, x
, y3
, x3
, y2
, transpose
);
2312 dc
.SetPen(m_penBlack
);
2313 DrawLine(dc
, x3
, y2
, x2
, y3
, transpose
);
2314 DrawLine(dc
, x2
, y3
, x2
, y
- 1, transpose
);
2316 dc
.SetPen(m_penDarkGrey
);
2317 DrawLine(dc
, x3
, y2
- 1, x2
- 1, y3
, transpose
);
2318 DrawLine(dc
, x2
- 1, y3
, x2
- 1, y
, transpose
);
2320 if ( flags
& wxCONTROL_PRESSED
)
2322 // TODO: MSW fills the entire area inside, not just the rect
2323 wxRect rectInt
= rect
;
2325 rectInt
.SetRight(y3
);
2327 rectInt
.SetBottom(y3
);
2330 static const char *stipple_xpm
[] = {
2331 /* columns rows colors chars-per-pixel */
2339 dc
.SetBrush(wxBrush(stipple_xpm
));
2341 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, SHADOW_HIGHLIGHT
));
2342 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, CONTROL
));
2343 dc
.SetPen(*wxTRANSPARENT_PEN
);
2344 dc
.DrawRectangle(rectInt
);
2348 void wxWin32Renderer::DrawSliderTicks(wxDC
& dc
,
2350 const wxSize
& sizeThumb
,
2351 wxOrientation orient
,
2363 // the variable names correspond to horizontal case, but they can be used
2364 // for both orientations
2365 wxCoord x1
, x2
, y1
, y2
, len
, widthThumb
;
2366 if ( orient
== wxHORIZONTAL
)
2368 x1
= rect
.GetLeft();
2369 x2
= rect
.GetRight();
2371 // draw from bottom to top to leave one pixel space between the ticks
2372 // and the slider as Windows do
2373 y1
= rect
.GetBottom();
2378 widthThumb
= sizeThumb
.x
;
2383 x2
= rect
.GetBottom();
2385 y1
= rect
.GetRight();
2386 y2
= rect
.GetLeft();
2390 widthThumb
= sizeThumb
.y
;
2393 // the first tick should be positioned in such way that a thumb drawn in
2394 // the first position points down directly to it
2395 x1
+= widthThumb
/ 2;
2396 x2
-= widthThumb
/ 2;
2398 // this also means that we have slightly less space for the ticks in
2399 // between the first and the last
2402 dc
.SetPen(m_penBlack
);
2404 int range
= end
- start
;
2405 for ( int n
= 0; n
< range
; n
+= step
)
2407 wxCoord x
= x1
+ (len
*n
) / range
;
2409 DrawLine(dc
, x
, y1
, x
, y2
, orient
== wxVERTICAL
);
2412 // always draw the line at the end position
2413 DrawLine(dc
, x2
, y1
, x2
, y2
, orient
== wxVERTICAL
);
2416 // ----------------------------------------------------------------------------
2418 // ----------------------------------------------------------------------------
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 // FIXME: all constants are hardcoded but shouldn't be
2449 static const wxCoord MENU_LEFT_MARGIN
= 9;
2450 static const wxCoord MENU_RIGHT_MARGIN
= 18;
2451 static const wxCoord MENU_VERT_MARGIN
= 3;
2453 // the margin around bitmap/check marks (on each side)
2454 static const wxCoord MENU_BMP_MARGIN
= 2;
2456 // the margin between the labels and accel strings
2457 static const wxCoord MENU_ACCEL_MARGIN
= 8;
2459 // the separator height in pixels: in fact, strangely enough, the real height
2460 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2462 static const wxCoord MENU_SEPARATOR_HEIGHT
= 3;
2464 // the size of the standard checkmark bitmap
2465 static const wxCoord MENU_CHECK_SIZE
= 9;
2467 void wxWin32Renderer::DrawMenuBarItem(wxDC
& dc
,
2468 const wxRect
& rectOrig
,
2469 const wxString
& label
,
2473 wxRect rect
= rectOrig
;
2476 wxDCTextColourChanger
colChanger(dc
);
2478 if ( flags
& wxCONTROL_SELECTED
)
2480 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2482 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2483 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2484 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2485 dc
.DrawRectangle(rect
);
2488 // don't draw the focus rect around menu bar items
2489 DrawLabel(dc
, label
, rect
, flags
& ~wxCONTROL_FOCUSED
,
2490 wxALIGN_CENTRE
, indexAccel
);
2493 void wxWin32Renderer::DrawMenuItem(wxDC
& dc
,
2495 const wxMenuGeometryInfo
& gi
,
2496 const wxString
& label
,
2497 const wxString
& accel
,
2498 const wxBitmap
& bitmap
,
2502 const wxWin32MenuGeometryInfo
& geometryInfo
=
2503 (const wxWin32MenuGeometryInfo
&)gi
;
2508 rect
.width
= geometryInfo
.GetSize().x
;
2509 rect
.height
= geometryInfo
.GetItemHeight();
2511 // draw the selected item specially
2512 wxDCTextColourChanger
colChanger(dc
);
2513 if ( flags
& wxCONTROL_SELECTED
)
2515 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2517 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2518 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2519 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2520 dc
.DrawRectangle(rect
);
2523 // draw the bitmap: use the bitmap provided or the standard checkmark for
2524 // the checkable items
2525 wxBitmap bmp
= bitmap
;
2526 if ( !bmp
.Ok() && (flags
& wxCONTROL_CHECKED
) )
2528 bmp
= GetIndicator(IndicatorType_Menu
, flags
);
2533 rect
.SetRight(geometryInfo
.GetLabelOffset());
2534 wxControlRenderer::DrawBitmap(dc
, bmp
, rect
);
2538 rect
.x
= geometryInfo
.GetLabelOffset();
2539 rect
.SetRight(geometryInfo
.GetAccelOffset());
2541 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
, indexAccel
);
2543 // draw the accel string
2544 rect
.x
= geometryInfo
.GetAccelOffset();
2545 rect
.SetRight(geometryInfo
.GetSize().x
);
2547 // NB: no accel index here
2548 DrawLabel(dc
, accel
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
);
2550 // draw the submenu indicator
2551 if ( flags
& wxCONTROL_ISSUBMENU
)
2553 rect
.x
= geometryInfo
.GetSize().x
- MENU_RIGHT_MARGIN
;
2554 rect
.width
= MENU_RIGHT_MARGIN
;
2556 wxArrowStyle arrowStyle
;
2557 if ( flags
& wxCONTROL_DISABLED
)
2558 arrowStyle
= flags
& wxCONTROL_SELECTED
? Arrow_InversedDisabled
2560 else if ( flags
& wxCONTROL_SELECTED
)
2561 arrowStyle
= Arrow_Inversed
;
2563 arrowStyle
= Arrow_Normal
;
2565 DrawArrow(dc
, rect
, Arrow_Right
, arrowStyle
);
2569 void wxWin32Renderer::DrawMenuSeparator(wxDC
& dc
,
2571 const wxMenuGeometryInfo
& geomInfo
)
2573 DrawHorizontalLine(dc
, y
+ MENU_VERT_MARGIN
, 0, geomInfo
.GetSize().x
);
2576 wxSize
wxWin32Renderer::GetMenuBarItemSize(const wxSize
& sizeText
) const
2578 wxSize size
= sizeText
;
2580 // FIXME: menubar height is configurable under Windows
2587 wxMenuGeometryInfo
*wxWin32Renderer::GetMenuGeometry(wxWindow
*win
,
2588 const wxMenu
& menu
) const
2590 // prepare the dc: for now we draw all the items with the system font
2592 dc
.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
));
2594 // the height of a normal item
2595 wxCoord heightText
= dc
.GetCharHeight();
2600 // the max length of label and accel strings: the menu width is the sum of
2601 // them, even if they're for different items (as the accels should be
2604 // the max length of the bitmap is never 0 as Windows always leaves enough
2605 // space for a check mark indicator
2606 wxCoord widthLabelMax
= 0,
2608 widthBmpMax
= MENU_LEFT_MARGIN
;
2610 for ( wxMenuItemList::Node
*node
= menu
.GetMenuItems().GetFirst();
2612 node
= node
->GetNext() )
2614 // height of this item
2617 wxMenuItem
*item
= node
->GetData();
2618 if ( item
->IsSeparator() )
2620 h
= MENU_SEPARATOR_HEIGHT
;
2622 else // not separator
2627 dc
.GetTextExtent(item
->GetLabel(), &widthLabel
, NULL
);
2628 if ( widthLabel
> widthLabelMax
)
2630 widthLabelMax
= widthLabel
;
2634 dc
.GetTextExtent(item
->GetAccelString(), &widthAccel
, NULL
);
2635 if ( widthAccel
> widthAccelMax
)
2637 widthAccelMax
= widthAccel
;
2640 const wxBitmap
& bmp
= item
->GetBitmap();
2643 wxCoord widthBmp
= bmp
.GetWidth();
2644 if ( widthBmp
> widthBmpMax
)
2645 widthBmpMax
= widthBmp
;
2647 //else if ( item->IsCheckable() ): no need to check for this as
2648 // MENU_LEFT_MARGIN is big enough to show the check mark
2651 h
+= 2*MENU_VERT_MARGIN
;
2653 // remember the item position and height
2654 item
->SetGeometry(height
, h
);
2659 // bundle the metrics into a struct and return it
2660 wxWin32MenuGeometryInfo
*gi
= new wxWin32MenuGeometryInfo
;
2662 gi
->m_ofsLabel
= widthBmpMax
+ 2*MENU_BMP_MARGIN
;
2663 gi
->m_ofsAccel
= gi
->m_ofsLabel
+ widthLabelMax
;
2664 if ( widthAccelMax
> 0 )
2666 // if we actually have any accesl, add a margin
2667 gi
->m_ofsAccel
+= MENU_ACCEL_MARGIN
;
2670 gi
->m_heightItem
= heightText
+ 2*MENU_VERT_MARGIN
;
2672 gi
->m_size
.x
= gi
->m_ofsAccel
+ widthAccelMax
+ MENU_RIGHT_MARGIN
;
2673 gi
->m_size
.y
= height
;
2678 // ----------------------------------------------------------------------------
2680 // ----------------------------------------------------------------------------
2682 void wxWin32Renderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
2683 wxBitmap
*bmpPressed
,
2684 wxBitmap
*bmpDisabled
)
2686 static const wxCoord widthCombo
= 16;
2687 static const wxCoord heightCombo
= 17;
2693 bmpNormal
->Create(widthCombo
, heightCombo
);
2694 dcMem
.SelectObject(*bmpNormal
);
2695 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2696 Arrow_Down
, Arrow_Normal
);
2701 bmpPressed
->Create(widthCombo
, heightCombo
);
2702 dcMem
.SelectObject(*bmpPressed
);
2703 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2704 Arrow_Down
, Arrow_Pressed
);
2709 bmpDisabled
->Create(widthCombo
, heightCombo
);
2710 dcMem
.SelectObject(*bmpDisabled
);
2711 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2712 Arrow_Down
, Arrow_Disabled
);
2716 // ----------------------------------------------------------------------------
2718 // ----------------------------------------------------------------------------
2720 void wxWin32Renderer::DoDrawBackground(wxDC
& dc
,
2721 const wxColour
& col
,
2724 wxBrush
brush(col
, wxSOLID
);
2726 dc
.SetPen(*wxTRANSPARENT_PEN
);
2727 dc
.DrawRectangle(rect
);
2730 void wxWin32Renderer::DrawBackground(wxDC
& dc
,
2731 const wxColour
& col
,
2735 // just fill it with the given or default bg colour
2736 wxColour colBg
= col
.Ok() ? col
: wxSCHEME_COLOUR(m_scheme
, CONTROL
);
2737 DoDrawBackground(dc
, colBg
, rect
);
2740 // ----------------------------------------------------------------------------
2742 // ----------------------------------------------------------------------------
2744 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2749 // get the bitmap for this arrow
2750 wxArrowDirection arrowDir
;
2753 case wxLEFT
: arrowDir
= Arrow_Left
; break;
2754 case wxRIGHT
: arrowDir
= Arrow_Right
; break;
2755 case wxUP
: arrowDir
= Arrow_Up
; break;
2756 case wxDOWN
: arrowDir
= Arrow_Down
; break;
2759 wxFAIL_MSG(_T("unknown arrow direction"));
2763 wxArrowStyle arrowStyle
;
2764 if ( flags
& wxCONTROL_PRESSED
)
2766 // can't be pressed and disabled
2767 arrowStyle
= Arrow_Pressed
;
2771 arrowStyle
= flags
& wxCONTROL_DISABLED
? Arrow_Disabled
: Arrow_Normal
;
2774 DrawArrowButton(dc
, rect
, arrowDir
, arrowStyle
);
2777 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2779 wxArrowDirection arrowDir
,
2780 wxArrowStyle arrowStyle
)
2782 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
2784 // under Windows the arrows always have the same size so just centre it in
2785 // the provided rectangle
2786 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
2787 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
2789 // Windows does it like this...
2790 if ( arrowDir
== Arrow_Left
)
2794 dc
.DrawBitmap(bmp
, x
, y
, TRUE
/* use mask */);
2797 void wxWin32Renderer::DrawArrowButton(wxDC
& dc
,
2798 const wxRect
& rectAll
,
2799 wxArrowDirection arrowDir
,
2800 wxArrowStyle arrowStyle
)
2802 wxRect rect
= rectAll
;
2803 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2804 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
2805 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
2808 void wxWin32Renderer::DrawScrollbarThumb(wxDC
& dc
,
2809 wxOrientation orient
,
2813 // we don't use the flags, the thumb never changes appearance
2814 wxRect rectThumb
= rect
;
2815 DrawArrowBorder(dc
, &rectThumb
);
2816 DrawBackground(dc
, wxNullColour
, rectThumb
);
2819 void wxWin32Renderer::DrawScrollbarShaft(wxDC
& dc
,
2820 wxOrientation orient
,
2821 const wxRect
& rectBar
,
2824 wxColourScheme::StdColour col
= flags
& wxCONTROL_PRESSED
2825 ? wxColourScheme::SCROLLBAR_PRESSED
2826 : wxColourScheme::SCROLLBAR
;
2827 DoDrawBackground(dc
, m_scheme
->Get(col
), rectBar
);
2830 void wxWin32Renderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
2832 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2835 wxRect
wxWin32Renderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
2836 wxScrollBar::Element elem
,
2839 return StandardGetScrollbarRect(scrollbar
, elem
,
2840 thumbPos
, m_sizeScrollbarArrow
);
2843 wxCoord
wxWin32Renderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
2845 return StandardScrollBarSize(scrollbar
, m_sizeScrollbarArrow
);
2848 wxHitTest
wxWin32Renderer::HitTestScrollbar(const wxScrollBar
*scrollbar
,
2849 const wxPoint
& pt
) const
2851 return StandardHitTestScrollbar(scrollbar
, pt
, m_sizeScrollbarArrow
);
2854 wxCoord
wxWin32Renderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
2857 return StandardScrollbarToPixel(scrollbar
, thumbPos
, m_sizeScrollbarArrow
);
2860 int wxWin32Renderer::PixelToScrollbar(const wxScrollBar
*scrollbar
,
2863 return StandardPixelToScrollbar(scrollbar
, coord
, m_sizeScrollbarArrow
);
2866 // ----------------------------------------------------------------------------
2867 // text control geometry
2868 // ----------------------------------------------------------------------------
2870 static inline int GetTextBorderWidth()
2875 wxRect
wxWin32Renderer::GetTextTotalArea(const wxTextCtrl
*text
,
2878 wxRect rectTotal
= rect
;
2880 wxCoord widthBorder
= GetTextBorderWidth();
2881 if ( rectTotal
.x
< widthBorder
)
2882 rectTotal
.x
= widthBorder
;
2883 if ( rectTotal
.y
< widthBorder
)
2884 rectTotal
.y
= widthBorder
;
2886 rectTotal
.Inflate(widthBorder
);
2888 // this is what Windows does
2894 wxRect
wxWin32Renderer::GetTextClientArea(const wxTextCtrl
*text
,
2896 wxCoord
*extraSpaceBeyond
)
2898 wxRect rectText
= rect
;
2900 // undo GetTextTotalArea()
2901 if ( rectText
.height
> 0 )
2904 wxCoord widthBorder
= GetTextBorderWidth();
2905 if ( rectText
.width
< 2*widthBorder
)
2906 rectText
.width
= 2*widthBorder
;
2907 if ( rectText
.height
< 2*widthBorder
)
2908 rectText
.height
= 2*widthBorder
;
2910 rectText
.Inflate(-widthBorder
);
2912 if ( extraSpaceBeyond
)
2913 *extraSpaceBeyond
= 0;
2918 // ----------------------------------------------------------------------------
2920 // ----------------------------------------------------------------------------
2922 void wxWin32Renderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
2925 if ( wxDynamicCast(window
, wxScrollBar
) )
2927 // we only set the width of vert scrollbars and height of the
2929 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
2930 size
->y
= m_sizeScrollbarArrow
.y
;
2932 size
->x
= m_sizeScrollbarArrow
.x
;
2934 // skip border width adjustments, they don't make sense for us
2937 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
2940 if ( wxDynamicCast(window
, wxButton
) )
2943 size
->x
+= 3*window
->GetCharWidth();
2944 #if 0 // do allow creating small buttons if wanted
2945 wxSize sizeDef
= wxButton::GetDefaultSize();
2946 if ( size
->x
< sizeDef
.x
)
2947 size
->x
= sizeDef
.x
;
2950 wxCoord heightBtn
= (11*(window
->GetCharHeight() + 8))/10;
2951 if ( size
->y
< heightBtn
- 8 )
2952 size
->y
= heightBtn
;
2956 // no border width adjustments for buttons
2959 #endif // wxUSE_BUTTON
2961 // take into account the border width
2962 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
2963 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
2964 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
2967 // ============================================================================
2969 // ============================================================================
2971 // ----------------------------------------------------------------------------
2972 // wxWin32InputHandler
2973 // ----------------------------------------------------------------------------
2975 wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer
*renderer
)
2977 m_renderer
= renderer
;
2980 bool wxWin32InputHandler::HandleKey(wxControl
*control
,
2981 const wxKeyEvent
& event
,
2987 bool wxWin32InputHandler::HandleMouse(wxControl
*control
,
2988 const wxMouseEvent
& event
)
2993 // ----------------------------------------------------------------------------
2994 // wxWin32ScrollBarInputHandler
2995 // ----------------------------------------------------------------------------
2997 wxWin32ScrollBarInputHandler::
2998 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
2999 wxInputHandler
*handler
)
3000 : wxStdScrollBarInputHandler(renderer
, handler
)
3002 m_scrollPaused
= FALSE
;
3006 bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar
*scrollbar
,
3007 const wxControlAction
& action
)
3009 // stop if went beyond the position of the original click (this can only
3010 // happen when we scroll by pages)
3012 if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
3014 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3015 != wxHT_SCROLLBAR_BAR_2
;
3017 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
3019 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3020 != wxHT_SCROLLBAR_BAR_1
;
3025 StopScrolling(scrollbar
);
3027 scrollbar
->Refresh();
3032 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar
, action
);
3035 bool wxWin32ScrollBarInputHandler::HandleMouse(wxControl
*control
,
3036 const wxMouseEvent
& event
)
3038 // remember the current state
3039 bool wasDraggingThumb
= m_htLast
== wxHT_SCROLLBAR_THUMB
;
3041 // do process the message
3042 bool rc
= wxStdScrollBarInputHandler::HandleMouse(control
, event
);
3044 // analyse the changes
3045 if ( !wasDraggingThumb
&& (m_htLast
== wxHT_SCROLLBAR_THUMB
) )
3047 // we just started dragging the thumb, remember its initial position to
3048 // be able to restore it if the drag is cancelled later
3049 m_eventStartDrag
= event
;
3055 bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl
*control
,
3056 const wxMouseEvent
& event
)
3058 // we don't highlight scrollbar elements, so there is no need to process
3059 // mouse move events normally - only do it while mouse is captured (i.e.
3060 // when we're dragging the thumb or pressing on something)
3061 if ( !m_winCapture
)
3064 if ( event
.Entering() )
3066 // we're not interested in this at all
3070 wxScrollBar
*scrollbar
= wxStaticCast(control
, wxScrollBar
);
3072 if ( m_scrollPaused
)
3074 // check if the mouse returned to its original location
3076 if ( event
.Leaving() )
3082 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3083 if ( ht
== m_htLast
)
3085 // yes it did, resume scrolling
3086 m_scrollPaused
= FALSE
;
3087 if ( m_timerScroll
)
3089 // we were scrolling by line/page, restart timer
3090 m_timerScroll
->Start(m_interval
);
3092 Press(scrollbar
, TRUE
);
3094 else // we were dragging the thumb
3096 // restore its last location
3097 HandleThumbMove(scrollbar
, m_eventLastDrag
);
3103 else // normal case, scrolling hasn't been paused
3105 // if we're scrolling the scrollbar because the arrow or the shaft was
3106 // pressed, check that the mouse stays on the same scrollbar element
3108 if ( event
.Moving() )
3110 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3112 else // event.Leaving()
3117 // if we're dragging the thumb and the mouse stays in the scrollbar, it
3118 // is still ok - we only want to catch the case when the mouse leaves
3119 // the scrollbar here
3120 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
&& ht
!= wxHT_NOWHERE
)
3122 ht
= wxHT_SCROLLBAR_THUMB
;
3125 if ( ht
!= m_htLast
)
3127 // what were we doing? 2 possibilities: either an arrow/shaft was
3128 // pressed in which case we have a timer and so we just stop it or
3129 // we were dragging the thumb
3130 if ( m_timerScroll
)
3133 m_interval
= m_timerScroll
->GetInterval();
3134 m_timerScroll
->Stop();
3135 m_scrollPaused
= TRUE
;
3137 // unpress the arrow
3138 Press(scrollbar
, FALSE
);
3140 else // we were dragging the thumb
3142 // remember the current thumb position to be able to restore it
3143 // if the mouse returns to it later
3144 m_eventLastDrag
= event
;
3146 // and restore the original position (before dragging) of the
3148 HandleThumbMove(scrollbar
, m_eventStartDrag
);
3155 return wxStdScrollBarInputHandler::HandleMouseMove(control
, event
);
3158 // ----------------------------------------------------------------------------
3159 // wxWin32CheckboxInputHandler
3160 // ----------------------------------------------------------------------------
3162 bool wxWin32CheckboxInputHandler::HandleKey(wxControl
*control
,
3163 const wxKeyEvent
& event
,
3168 wxControlAction action
;
3169 int keycode
= event
.GetKeyCode();
3173 action
= wxACTION_CHECKBOX_TOGGLE
;
3177 case WXK_NUMPAD_SUBTRACT
:
3178 action
= wxACTION_CHECKBOX_CHECK
;
3182 case WXK_NUMPAD_ADD
:
3183 case WXK_NUMPAD_EQUAL
:
3184 action
= wxACTION_CHECKBOX_CLEAR
;
3190 control
->PerformAction(action
);
3199 // ----------------------------------------------------------------------------
3200 // wxWin32TextCtrlInputHandler
3201 // ----------------------------------------------------------------------------
3203 bool wxWin32TextCtrlInputHandler::HandleKey(wxControl
*control
,
3204 const wxKeyEvent
& event
,
3207 // handle only MSW-specific text bindings here, the others are handled in
3211 int keycode
= event
.GetKeyCode();
3213 wxControlAction action
;
3214 if ( keycode
== WXK_DELETE
&& event
.ShiftDown() )
3216 action
= wxACTION_TEXT_CUT
;
3218 else if ( keycode
== WXK_INSERT
)
3220 if ( event
.ControlDown() )
3221 action
= wxACTION_TEXT_COPY
;
3222 else if ( event
.ShiftDown() )
3223 action
= wxACTION_TEXT_PASTE
;
3226 if ( action
!= wxACTION_NONE
)
3228 control
->PerformAction(action
);
3234 return wxStdTextCtrlInputHandler::HandleKey(control
, event
, pressed
);