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"
48 #include "wx/univ/scrtimer.h"
50 #include "wx/univ/renderer.h"
51 #include "wx/univ/inphand.h"
52 #include "wx/univ/colschem.h"
53 #include "wx/univ/theme.h"
55 // ----------------------------------------------------------------------------
57 // ----------------------------------------------------------------------------
59 static const int BORDER_THICKNESS
= 2;
61 // the offset between the label and focus rect around it
62 static const int FOCUS_RECT_OFFSET_X
= 1;
63 static const int FOCUS_RECT_OFFSET_Y
= 1;
75 IndicatorState_Normal
,
76 IndicatorState_Pressed
, // this one is for check/radioboxes
77 IndicatorState_Selected
= IndicatorState_Pressed
, // for menus
78 IndicatorState_Disabled
,
79 IndicatorState_SelectedDisabled
, // only for the menus
85 IndicatorStatus_Checked
,
86 IndicatorStatus_Unchecked
,
90 // ----------------------------------------------------------------------------
91 // wxWin32Renderer: draw the GUI elements in Win32 style
92 // ----------------------------------------------------------------------------
94 class wxWin32Renderer
: public wxRenderer
113 Arrow_InversedDisabled
,
118 wxWin32Renderer(const wxColourScheme
*scheme
);
120 // implement the base class pure virtuals
121 virtual void DrawBackground(wxDC
& dc
,
125 virtual void DrawLabel(wxDC
& dc
,
126 const wxString
& label
,
129 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
131 wxRect
*rectBounds
= NULL
);
132 virtual void DrawButtonLabel(wxDC
& dc
,
133 const wxString
& label
,
134 const wxBitmap
& image
,
137 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
139 wxRect
*rectBounds
= NULL
);
140 virtual void DrawBorder(wxDC
& dc
,
144 wxRect
*rectIn
= (wxRect
*)NULL
);
145 virtual void DrawHorizontalLine(wxDC
& dc
,
146 wxCoord y
, wxCoord x1
, wxCoord x2
);
147 virtual void DrawVerticalLine(wxDC
& dc
,
148 wxCoord x
, wxCoord y1
, wxCoord y2
);
149 virtual void DrawFrame(wxDC
& dc
,
150 const wxString
& label
,
153 int alignment
= wxALIGN_LEFT
,
154 int indexAccel
= -1);
155 virtual void DrawTextBorder(wxDC
& dc
,
159 wxRect
*rectIn
= (wxRect
*)NULL
);
160 virtual void DrawButtonBorder(wxDC
& dc
,
163 wxRect
*rectIn
= (wxRect
*)NULL
);
164 virtual void DrawArrow(wxDC
& dc
,
168 virtual void DrawScrollbarArrow(wxDC
& dc
,
172 { DrawArrow(dc
, dir
, rect
, flags
); }
173 virtual void DrawScrollbarThumb(wxDC
& dc
,
174 wxOrientation orient
,
177 virtual void DrawScrollbarShaft(wxDC
& dc
,
178 wxOrientation orient
,
181 virtual void DrawScrollCorner(wxDC
& dc
,
183 virtual void DrawItem(wxDC
& dc
,
184 const wxString
& label
,
187 virtual void DrawCheckItem(wxDC
& dc
,
188 const wxString
& label
,
189 const wxBitmap
& bitmap
,
192 virtual void DrawCheckButton(wxDC
& dc
,
193 const wxString
& label
,
194 const wxBitmap
& bitmap
,
197 wxAlignment align
= wxALIGN_LEFT
,
198 int indexAccel
= -1);
199 virtual void DrawRadioButton(wxDC
& dc
,
200 const wxString
& label
,
201 const wxBitmap
& bitmap
,
204 wxAlignment align
= wxALIGN_LEFT
,
205 int indexAccel
= -1);
206 virtual void DrawTextLine(wxDC
& dc
,
207 const wxString
& text
,
212 virtual void DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
);
213 virtual void DrawTab(wxDC
& dc
,
216 const wxString
& label
,
217 const wxBitmap
& bitmap
= wxNullBitmap
,
219 int indexAccel
= -1);
221 virtual void DrawSliderShaft(wxDC
& dc
,
223 wxOrientation orient
,
225 wxRect
*rectShaft
= NULL
);
226 virtual void DrawSliderThumb(wxDC
& dc
,
228 wxOrientation orient
,
230 virtual void DrawSliderTicks(wxDC
& dc
,
232 const wxSize
& sizeThumb
,
233 wxOrientation orient
,
239 virtual void DrawMenuBarItem(wxDC
& dc
,
241 const wxString
& label
,
243 int indexAccel
= -1);
244 virtual void DrawMenuItem(wxDC
& dc
,
246 const wxMenuGeometryInfo
& geometryInfo
,
247 const wxString
& label
,
248 const wxString
& accel
,
249 const wxBitmap
& bitmap
= wxNullBitmap
,
251 int indexAccel
= -1);
252 virtual void DrawMenuSeparator(wxDC
& dc
,
254 const wxMenuGeometryInfo
& geomInfo
);
256 virtual void GetComboBitmaps(wxBitmap
*bmpNormal
,
257 wxBitmap
*bmpPressed
,
258 wxBitmap
*bmpDisabled
);
260 virtual void AdjustSize(wxSize
*size
, const wxWindow
*window
);
261 virtual wxRect
GetBorderDimensions(wxBorder border
) const;
262 virtual bool AreScrollbarsInsideBorder() const;
264 virtual wxSize
GetScrollbarArrowSize() const
265 { return m_sizeScrollbarArrow
; }
266 virtual wxRect
GetScrollbarRect(const wxScrollBar
*scrollbar
,
267 wxScrollBar::Element elem
,
268 int thumbPos
= -1) const;
269 virtual wxCoord
GetScrollbarSize(const wxScrollBar
*scrollbar
);
270 virtual wxHitTest
HitTestScrollbar(const wxScrollBar
*scrollbar
,
271 const wxPoint
& pt
) const;
272 virtual wxCoord
ScrollbarToPixel(const wxScrollBar
*scrollbar
,
274 virtual int PixelToScrollbar(const wxScrollBar
*scrollbar
, wxCoord coord
);
275 virtual wxCoord
GetListboxItemHeight(wxCoord fontHeight
)
276 { return fontHeight
+ 2; }
277 virtual wxSize
GetCheckBitmapSize() const
278 { return wxSize(13, 13); }
279 virtual wxSize
GetRadioBitmapSize() const
280 { return wxSize(12, 12); }
281 virtual wxCoord
GetCheckItemMargin() const
284 virtual wxRect
GetTextTotalArea(const wxTextCtrl
*text
,
286 virtual wxRect
GetTextClientArea(const wxTextCtrl
*text
,
288 wxCoord
*extraSpaceBeyond
);
290 virtual wxSize
GetTabIndent() const { return wxSize(2, 2); }
291 virtual wxSize
GetTabPadding() const { return wxSize(6, 5); }
293 virtual wxCoord
GetSliderDim() const { return 20; }
294 virtual wxCoord
GetSliderTickLen() const { return 4; }
295 virtual wxRect
GetSliderShaftRect(const wxRect
& rect
,
296 wxOrientation orient
) const;
297 virtual wxSize
GetSliderThumbSize(const wxRect
& rect
,
298 wxOrientation orient
) const;
299 virtual wxSize
GetProgressBarStep() const { return wxSize(16, 32); }
301 virtual wxSize
GetMenuBarItemSize(const wxSize
& sizeText
) const;
302 virtual wxMenuGeometryInfo
*GetMenuGeometry(wxWindow
*win
,
303 const wxMenu
& menu
) const;
306 // helper of DrawLabel() and DrawCheckOrRadioButton()
307 void DoDrawLabel(wxDC
& dc
,
308 const wxString
& label
,
311 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
313 wxRect
*rectBounds
= NULL
,
314 const wxPoint
& focusOffset
315 = wxPoint(FOCUS_RECT_OFFSET_X
, FOCUS_RECT_OFFSET_Y
));
317 // common part of DrawLabel() and DrawItem()
318 void DrawFocusRect(wxDC
& dc
, const wxRect
& rect
);
320 // DrawLabel() and DrawButtonLabel() helper
321 void DrawLabelShadow(wxDC
& dc
,
322 const wxString
& label
,
327 // DrawButtonBorder() helper
328 void DoDrawBackground(wxDC
& dc
,
332 // DrawBorder() helpers: all of them shift and clip the DC after drawing
335 // just draw a rectangle with the given pen
336 void DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
338 // draw the lower left part of rectangle
339 void DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
341 // draw the rectange using the first brush for the left and top sides and
342 // the second one for the bottom and right ones
343 void DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
344 const wxPen
& pen1
, const wxPen
& pen2
);
346 // draw the normal 3D border
347 void DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
);
349 // draw the sunken 3D border
350 void DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
);
352 // draw the border used for scrollbar arrows
353 void DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
= FALSE
);
355 // public DrawArrow()s helper
356 void DrawArrow(wxDC
& dc
, const wxRect
& rect
,
357 wxArrowDirection arrowDir
, wxArrowStyle arrowStyle
);
359 // DrawArrowButton is used by DrawScrollbar and DrawComboButton
360 void DrawArrowButton(wxDC
& dc
, const wxRect
& rect
,
361 wxArrowDirection arrowDir
,
362 wxArrowStyle arrowStyle
);
364 // DrawCheckButton/DrawRadioButton helper
365 void DrawCheckOrRadioButton(wxDC
& dc
,
366 const wxString
& label
,
367 const wxBitmap
& bitmap
,
372 wxCoord focusOffsetY
);
374 // draw a normal or transposed line (useful for using the same code fo both
375 // horizontal and vertical widgets)
376 void DrawLine(wxDC
& dc
,
377 wxCoord x1
, wxCoord y1
,
378 wxCoord x2
, wxCoord y2
,
379 bool transpose
= FALSE
)
382 dc
.DrawLine(y1
, x1
, y2
, x2
);
384 dc
.DrawLine(x1
, y1
, x2
, y2
);
387 // get the standard check/radio button bitmap
388 wxBitmap
GetIndicator(IndicatorType indType
, int flags
);
389 wxBitmap
GetCheckBitmap(int flags
)
390 { return GetIndicator(IndicatorType_Check
, flags
); }
391 wxBitmap
GetRadioBitmap(int flags
)
392 { return GetIndicator(IndicatorType_Radio
, flags
); }
395 const wxColourScheme
*m_scheme
;
397 // the sizing parameters (TODO make them changeable)
398 wxSize m_sizeScrollbarArrow
;
400 // GDI objects we use for drawing
401 wxColour m_colDarkGrey
,
409 // first row is for the normal state, second - for the disabled
410 wxBitmap m_bmpArrows
[Arrow_StateMax
][Arrow_Max
];
413 // ----------------------------------------------------------------------------
414 // wxWin32InputHandler and derived classes: process the keyboard and mouse
415 // messages according to Windows standards
416 // ----------------------------------------------------------------------------
418 class wxWin32InputHandler
: public wxInputHandler
421 wxWin32InputHandler(wxWin32Renderer
*renderer
);
423 virtual bool HandleKey(wxControl
*control
,
424 const wxKeyEvent
& event
,
426 virtual bool HandleMouse(wxControl
*control
,
427 const wxMouseEvent
& event
);
430 wxWin32Renderer
*m_renderer
;
433 class wxWin32ScrollBarInputHandler
: public wxStdScrollBarInputHandler
436 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
437 wxInputHandler
*handler
);
439 virtual bool HandleMouse(wxControl
*control
, const wxMouseEvent
& event
);
440 virtual bool HandleMouseMove(wxControl
*control
, const wxMouseEvent
& event
);
442 virtual bool OnScrollTimer(wxScrollBar
*scrollbar
,
443 const wxControlAction
& action
);
446 virtual bool IsAllowedButton(int button
) { return button
== 1; }
448 virtual void Highlight(wxScrollBar
*scrollbar
, bool doIt
)
450 // we don't highlight anything
453 // the first and last event which caused the thumb to move
454 wxMouseEvent m_eventStartDrag
,
457 // have we paused the scrolling because the mouse moved?
460 // we remember the interval of the timer to be able to restart it
464 class wxWin32CheckboxInputHandler
: public wxStdCheckboxInputHandler
467 wxWin32CheckboxInputHandler(wxInputHandler
*handler
)
468 : wxStdCheckboxInputHandler(handler
) { }
470 virtual bool HandleKey(wxControl
*control
,
471 const wxKeyEvent
& event
,
475 class wxWin32TextCtrlInputHandler
: public wxStdTextCtrlInputHandler
478 wxWin32TextCtrlInputHandler(wxInputHandler
*handler
)
479 : wxStdTextCtrlInputHandler(handler
) { }
481 virtual bool HandleKey(wxControl
*control
,
482 const wxKeyEvent
& event
,
486 // ----------------------------------------------------------------------------
487 // wxWin32ColourScheme: uses (default) Win32 colours
488 // ----------------------------------------------------------------------------
490 class wxWin32ColourScheme
: public wxColourScheme
493 virtual wxColour
Get(StdColour col
) const;
494 virtual wxColour
GetBackground(wxWindow
*win
) const;
497 // ----------------------------------------------------------------------------
499 // ----------------------------------------------------------------------------
501 WX_DEFINE_ARRAY(wxInputHandler
*, wxArrayHandlers
);
503 class wxWin32Theme
: public wxTheme
507 virtual ~wxWin32Theme();
509 virtual wxRenderer
*GetRenderer() { return m_renderer
; }
510 virtual wxInputHandler
*GetInputHandler(const wxString
& control
);
511 virtual wxColourScheme
*GetColourScheme();
514 // get the default input handler
515 wxInputHandler
*GetDefaultInputHandler();
517 wxWin32Renderer
*m_renderer
;
519 // the names of the already created handlers and the handlers themselves
520 // (these arrays are synchronized)
521 wxSortedArrayString m_handlerNames
;
522 wxArrayHandlers m_handlers
;
524 wxWin32InputHandler
*m_handlerDefault
;
526 wxWin32ColourScheme
*m_scheme
;
528 WX_DECLARE_THEME(win32
)
531 // ----------------------------------------------------------------------------
533 // ----------------------------------------------------------------------------
537 static const char *checked_menu_xpm
[] = {
538 /* columns rows colors chars-per-pixel */
554 static const char *selected_checked_menu_xpm
[] = {
555 /* columns rows colors chars-per-pixel */
571 static const char *disabled_checked_menu_xpm
[] = {
572 /* columns rows colors chars-per-pixel */
589 static const char *selected_disabled_checked_menu_xpm
[] = {
590 /* columns rows colors chars-per-pixel */
606 // checkbox and radiobox bitmaps below
608 static const char *checked_xpm
[] = {
609 /* columns rows colors chars-per-pixel */
632 static const char *pressed_checked_xpm
[] = {
633 /* columns rows colors chars-per-pixel */
655 static const char *pressed_disabled_checked_xpm
[] = {
656 /* columns rows colors chars-per-pixel */
678 static const char *checked_item_xpm
[] = {
679 /* columns rows colors chars-per-pixel */
700 static const char *unchecked_xpm
[] = {
701 /* columns rows colors chars-per-pixel */
724 static const char *pressed_unchecked_xpm
[] = {
725 /* columns rows colors chars-per-pixel */
747 static const char *unchecked_item_xpm
[] = {
748 /* columns rows colors chars-per-pixel */
768 static const char *checked_radio_xpm
[] = {
769 /* columns rows colors chars-per-pixel */
792 static const char *pressed_checked_radio_xpm
[] = {
793 /* columns rows colors chars-per-pixel */
816 static const char *pressed_disabled_checked_radio_xpm
[] = {
817 /* columns rows colors chars-per-pixel */
840 static const char *unchecked_radio_xpm
[] = {
841 /* columns rows colors chars-per-pixel */
864 static const char *pressed_unchecked_radio_xpm
[] = {
865 /* columns rows colors chars-per-pixel */
889 bmpIndicators
[IndicatorType_Max
][IndicatorState_Max
][IndicatorStatus_Max
] =
894 { checked_xpm
, unchecked_xpm
},
897 { pressed_checked_xpm
, pressed_unchecked_xpm
},
900 { pressed_disabled_checked_xpm
, pressed_unchecked_xpm
},
906 { checked_radio_xpm
, unchecked_radio_xpm
},
909 { pressed_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
912 { pressed_disabled_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
918 { checked_menu_xpm
, NULL
},
921 { selected_checked_menu_xpm
, NULL
},
924 { disabled_checked_menu_xpm
, NULL
},
926 // disabled selected state
927 { selected_disabled_checked_menu_xpm
, NULL
},
931 // ============================================================================
933 // ============================================================================
935 WX_IMPLEMENT_THEME(wxWin32Theme
, win32
, wxTRANSLATE("Win32 theme"));
937 // ----------------------------------------------------------------------------
939 // ----------------------------------------------------------------------------
941 wxWin32Theme::wxWin32Theme()
943 m_scheme
= new wxWin32ColourScheme
;
944 m_renderer
= new wxWin32Renderer(m_scheme
);
945 m_handlerDefault
= NULL
;
948 wxWin32Theme::~wxWin32Theme()
950 size_t count
= m_handlers
.GetCount();
951 for ( size_t n
= 0; n
< count
; n
++ )
953 if ( m_handlers
[n
] != m_handlerDefault
)
954 delete m_handlers
[n
];
957 delete m_handlerDefault
;
963 wxInputHandler
*wxWin32Theme::GetDefaultInputHandler()
965 if ( !m_handlerDefault
)
967 m_handlerDefault
= new wxWin32InputHandler(m_renderer
);
970 return m_handlerDefault
;
973 wxInputHandler
*wxWin32Theme::GetInputHandler(const wxString
& control
)
975 wxInputHandler
*handler
;
976 int n
= m_handlerNames
.Index(control
);
977 if ( n
== wxNOT_FOUND
)
979 // create a new handler
980 if ( control
== wxINP_HANDLER_SCROLLBAR
)
981 handler
= new wxWin32ScrollBarInputHandler(m_renderer
,
982 GetDefaultInputHandler());
984 else if ( control
== wxINP_HANDLER_BUTTON
)
985 handler
= new wxStdButtonInputHandler(GetDefaultInputHandler());
986 #endif // wxUSE_BUTTON
988 else if ( control
== wxINP_HANDLER_CHECKBOX
)
989 handler
= new wxWin32CheckboxInputHandler(GetDefaultInputHandler());
990 #endif // wxUSE_CHECKBOX
992 else if ( control
== wxINP_HANDLER_COMBOBOX
)
993 handler
= new wxStdComboBoxInputHandler(GetDefaultInputHandler());
994 #endif // wxUSE_COMBOBOX
996 else if ( control
== wxINP_HANDLER_LISTBOX
)
997 handler
= new wxStdListboxInputHandler(GetDefaultInputHandler());
998 #endif // wxUSE_LISTBOX
999 #if wxUSE_CHECKLISTBOX
1000 else if ( control
== wxINP_HANDLER_CHECKLISTBOX
)
1001 handler
= new wxStdCheckListboxInputHandler(GetDefaultInputHandler());
1002 #endif // wxUSE_CHECKLISTBOX
1004 else if ( control
== wxINP_HANDLER_TEXTCTRL
)
1005 handler
= new wxWin32TextCtrlInputHandler(GetDefaultInputHandler());
1006 #endif // wxUSE_TEXTCTRL
1008 else if ( control
== wxINP_HANDLER_SLIDER
)
1009 handler
= new wxStdSliderButtonInputHandler(GetDefaultInputHandler());
1010 #endif // wxUSE_SLIDER
1012 else if ( control
== wxINP_HANDLER_SPINBTN
)
1013 handler
= new wxStdSpinButtonInputHandler(GetDefaultInputHandler());
1014 #endif // wxUSE_SPINBTN
1016 else if ( control
== wxINP_HANDLER_NOTEBOOK
)
1017 handler
= new wxStdNotebookInputHandler(GetDefaultInputHandler());
1018 #endif // wxUSE_NOTEBOOK
1020 handler
= GetDefaultInputHandler();
1022 n
= m_handlerNames
.Add(control
);
1023 m_handlers
.Insert(handler
, n
);
1025 else // we already have it
1027 handler
= m_handlers
[n
];
1033 wxColourScheme
*wxWin32Theme::GetColourScheme()
1038 // ============================================================================
1039 // wxWin32ColourScheme
1040 // ============================================================================
1042 wxColour
wxWin32ColourScheme::GetBackground(wxWindow
*win
) const
1045 if ( win
->UseBgCol() )
1047 // use the user specified colour
1048 col
= win
->GetBackgroundColour();
1051 if ( win
->IsContainerWindow() )
1053 wxTextCtrl
*text
= wxDynamicCast(win
, wxTextCtrl
);
1056 if ( !text
->IsEnabled() ) // not IsEditable()
1058 //else: execute code below
1063 // doesn't depend on the state
1069 int flags
= win
->GetStateFlags();
1071 // the colour set by the user should be used for the normal state
1072 // and for the states for which we don't have any specific colours
1073 if ( !col
.Ok() || (flags
!= 0) )
1075 if ( wxDynamicCast(win
, wxScrollBar
) )
1076 col
= Get(flags
& wxCONTROL_PRESSED
? SCROLLBAR_PRESSED
1086 wxColour
wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col
) const
1090 case WINDOW
: return *wxWHITE
;
1092 case CONTROL_PRESSED
:
1093 case CONTROL_CURRENT
:
1094 case CONTROL
: return wxColour(0xc0c0c0);
1096 case CONTROL_TEXT
: return *wxBLACK
;
1098 case SCROLLBAR
: return wxColour(0xe0e0e0);
1099 case SCROLLBAR_PRESSED
: return *wxBLACK
;
1101 case HIGHLIGHT
: return wxColour(0x800000);
1102 case HIGHLIGHT_TEXT
: return wxColour(0xffffff);
1104 case SHADOW_DARK
: return *wxBLACK
;
1106 case CONTROL_TEXT_DISABLED
:
1107 case SHADOW_HIGHLIGHT
: return wxColour(0xe0e0e0);
1109 case SHADOW_IN
: return wxColour(0xc0c0c0);
1111 case CONTROL_TEXT_DISABLED_SHADOW
:
1112 case SHADOW_OUT
: return wxColour(0x7f7f7f);
1116 wxFAIL_MSG(_T("invalid standard colour"));
1121 // ============================================================================
1123 // ============================================================================
1125 // ----------------------------------------------------------------------------
1127 // ----------------------------------------------------------------------------
1129 wxWin32Renderer::wxWin32Renderer(const wxColourScheme
*scheme
)
1133 m_sizeScrollbarArrow
= wxSize(16, 16);
1135 // init colours and pens
1136 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
), 0, wxSOLID
);
1138 m_colDarkGrey
= wxSCHEME_COLOUR(scheme
, SHADOW_OUT
);
1139 m_penDarkGrey
= wxPen(m_colDarkGrey
, 0, wxSOLID
);
1141 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
), 0, wxSOLID
);
1143 m_colHighlight
= wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
);
1144 m_penHighlight
= wxPen(m_colHighlight
, 0, wxSOLID
);
1146 // init the arrow bitmaps
1147 static const size_t ARROW_WIDTH
= 7;
1148 static const size_t ARROW_LENGTH
= 4;
1151 wxMemoryDC dcNormal
,
1154 for ( size_t n
= 0; n
< Arrow_Max
; n
++ )
1156 bool isVertical
= n
> Arrow_Right
;
1169 // disabled arrow is larger because of the shadow
1170 m_bmpArrows
[Arrow_Normal
][n
].Create(w
, h
);
1171 m_bmpArrows
[Arrow_Disabled
][n
].Create(w
+ 1, h
+ 1);
1173 dcNormal
.SelectObject(m_bmpArrows
[Arrow_Normal
][n
]);
1174 dcDisabled
.SelectObject(m_bmpArrows
[Arrow_Disabled
][n
]);
1176 dcNormal
.SetBackground(*wxWHITE_BRUSH
);
1177 dcDisabled
.SetBackground(*wxWHITE_BRUSH
);
1181 dcNormal
.SetPen(m_penBlack
);
1182 dcDisabled
.SetPen(m_penDarkGrey
);
1184 // calculate the position of the point of the arrow
1188 x1
= (ARROW_WIDTH
- 1)/2;
1189 y1
= n
== Arrow_Up
? 0 : ARROW_LENGTH
- 1;
1193 x1
= n
== Arrow_Left
? 0 : ARROW_LENGTH
- 1;
1194 y1
= (ARROW_WIDTH
- 1)/2;
1205 for ( size_t i
= 0; i
< ARROW_LENGTH
; i
++ )
1207 dcNormal
.DrawLine(x1
, y1
, x2
, y2
);
1208 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1215 if ( n
== Arrow_Up
)
1226 else // left or right arrow
1231 if ( n
== Arrow_Left
)
1244 // draw the shadow for the disabled one
1245 dcDisabled
.SetPen(m_penHighlight
);
1250 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1254 x1
= ARROW_LENGTH
- 1;
1255 y1
= (ARROW_WIDTH
- 1)/2 + 1;
1258 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1259 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1264 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1268 x1
= ARROW_WIDTH
- 1;
1270 x2
= (ARROW_WIDTH
- 1)/2;
1272 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1273 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1278 // create the inversed bitmap but only for the right arrow as we only
1279 // use it for the menus
1280 if ( n
== Arrow_Right
)
1282 m_bmpArrows
[Arrow_Inversed
][n
].Create(w
, h
);
1283 dcInverse
.SelectObject(m_bmpArrows
[Arrow_Inversed
][n
]);
1285 dcInverse
.Blit(0, 0, w
, h
,
1288 dcInverse
.SelectObject(wxNullBitmap
);
1290 mask
= new wxMask(m_bmpArrows
[Arrow_Inversed
][n
], *wxBLACK
);
1291 m_bmpArrows
[Arrow_Inversed
][n
].SetMask(mask
);
1293 m_bmpArrows
[Arrow_InversedDisabled
][n
].Create(w
, h
);
1294 dcInverse
.SelectObject(m_bmpArrows
[Arrow_InversedDisabled
][n
]);
1296 dcInverse
.Blit(0, 0, w
, h
,
1299 dcInverse
.SelectObject(wxNullBitmap
);
1301 mask
= new wxMask(m_bmpArrows
[Arrow_InversedDisabled
][n
], *wxBLACK
);
1302 m_bmpArrows
[Arrow_InversedDisabled
][n
].SetMask(mask
);
1305 dcNormal
.SelectObject(wxNullBitmap
);
1306 dcDisabled
.SelectObject(wxNullBitmap
);
1308 mask
= new wxMask(m_bmpArrows
[Arrow_Normal
][n
], *wxWHITE
);
1309 m_bmpArrows
[Arrow_Normal
][n
].SetMask(mask
);
1310 mask
= new wxMask(m_bmpArrows
[Arrow_Disabled
][n
], *wxWHITE
);
1311 m_bmpArrows
[Arrow_Disabled
][n
].SetMask(mask
);
1313 m_bmpArrows
[Arrow_Pressed
][n
] = m_bmpArrows
[Arrow_Normal
][n
];
1317 // ----------------------------------------------------------------------------
1319 // ----------------------------------------------------------------------------
1322 The raised border in Win32 looks like this:
1324 IIIIIIIIIIIIIIIIIIIIIIB
1326 I GB I = white (HILIGHT)
1327 I GB H = light grey (LIGHT)
1328 I GB G = dark grey (SHADOI)
1329 I GB B = black (DKSHADOI)
1330 I GB I = hIghlight (COLOR_3DHILIGHT)
1332 IGGGGGGGGGGGGGGGGGGGGGB
1333 BBBBBBBBBBBBBBBBBBBBBBB
1335 The sunken border looks like this:
1337 GGGGGGGGGGGGGGGGGGGGGGI
1338 GBBBBBBBBBBBBBBBBBBBBHI
1345 GHHHHHHHHHHHHHHHHHHHHHI
1346 IIIIIIIIIIIIIIIIIIIIIII
1348 The static border (used for the controls which don't get focus) is like
1351 GGGGGGGGGGGGGGGGGGGGGGW
1359 WWWWWWWWWWWWWWWWWWWWWWW
1361 The most complicated is the double border:
1363 HHHHHHHHHHHHHHHHHHHHHHB
1364 HWWWWWWWWWWWWWWWWWWWWGB
1365 HWHHHHHHHHHHHHHHHHHHHGB
1370 HWHHHHHHHHHHHHHHHHHHHGB
1371 HGGGGGGGGGGGGGGGGGGGGGB
1372 BBBBBBBBBBBBBBBBBBBBBBB
1374 And the simple border is, well, simple:
1376 BBBBBBBBBBBBBBBBBBBBBBB
1385 BBBBBBBBBBBBBBBBBBBBBBB
1388 void wxWin32Renderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1392 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1393 dc
.DrawRectangle(*rect
);
1399 void wxWin32Renderer::DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1401 // draw the bottom and right sides
1403 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1404 rect
->GetRight() + 1, rect
->GetBottom());
1405 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1406 rect
->GetRight(), rect
->GetBottom());
1413 void wxWin32Renderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
1414 const wxPen
& pen1
, const wxPen
& pen2
)
1416 // draw the rectangle
1418 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
1419 rect
->GetLeft(), rect
->GetBottom());
1420 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
1421 rect
->GetRight(), rect
->GetTop());
1423 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1424 rect
->GetRight(), rect
->GetBottom());
1425 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1426 rect
->GetRight() + 1, rect
->GetBottom());
1432 void wxWin32Renderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
1434 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
1435 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
1438 void wxWin32Renderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
1440 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
1441 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
1444 void wxWin32Renderer::DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
)
1448 DrawRect(dc
, rect
, m_penDarkGrey
);
1450 // the arrow is usually drawn inside border of width 2 and is offset by
1451 // another pixel in both directions when it's pressed - as the border
1452 // in this case is more narrow as well, we have to adjust rect like
1460 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
1461 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
1465 void wxWin32Renderer::DrawBorder(wxDC
& dc
,
1467 const wxRect
& rectTotal
,
1468 int WXUNUSED(flags
),
1473 wxRect rect
= rectTotal
;
1477 case wxBORDER_SUNKEN
:
1478 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1480 DrawSunkenBorder(dc
, &rect
);
1484 case wxBORDER_STATIC
:
1485 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1488 case wxBORDER_RAISED
:
1489 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1491 DrawRaisedBorder(dc
, &rect
);
1495 case wxBORDER_DOUBLE
:
1496 DrawArrowBorder(dc
, &rect
);
1497 DrawRect(dc
, &rect
, m_penLightGrey
);
1500 case wxBORDER_SIMPLE
:
1501 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1503 DrawRect(dc
, &rect
, m_penBlack
);
1508 wxFAIL_MSG(_T("unknown border type"));
1511 case wxBORDER_DEFAULT
:
1520 wxRect
wxWin32Renderer::GetBorderDimensions(wxBorder border
) const
1525 case wxBORDER_RAISED
:
1526 case wxBORDER_SUNKEN
:
1527 width
= BORDER_THICKNESS
;
1530 case wxBORDER_SIMPLE
:
1531 case wxBORDER_STATIC
:
1535 case wxBORDER_DOUBLE
:
1540 wxFAIL_MSG(_T("unknown border type"));
1543 case wxBORDER_DEFAULT
:
1553 rect
.height
= width
;
1558 bool wxWin32Renderer::AreScrollbarsInsideBorder() const
1563 // ----------------------------------------------------------------------------
1565 // ----------------------------------------------------------------------------
1567 void wxWin32Renderer::DrawTextBorder(wxDC
& dc
,
1573 // text controls are not special under windows
1574 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
1577 void wxWin32Renderer::DrawButtonBorder(wxDC
& dc
,
1578 const wxRect
& rectTotal
,
1582 wxRect rect
= rectTotal
;
1584 if ( flags
& wxCONTROL_PRESSED
)
1586 // button pressed: draw a double border around it
1587 DrawRect(dc
, &rect
, m_penBlack
);
1588 DrawRect(dc
, &rect
, m_penDarkGrey
);
1592 // button not pressed
1594 if ( flags
& (wxCONTROL_FOCUSED
| wxCONTROL_ISDEFAULT
) )
1596 // button either default or focused (or both): add an extra border around it
1597 DrawRect(dc
, &rect
, m_penBlack
);
1600 // now draw a normal button
1601 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penBlack
);
1602 DrawHalfRect(dc
, &rect
, m_penDarkGrey
);
1611 // ----------------------------------------------------------------------------
1613 // ----------------------------------------------------------------------------
1615 void wxWin32Renderer::DrawHorizontalLine(wxDC
& dc
,
1616 wxCoord y
, wxCoord x1
, wxCoord x2
)
1618 dc
.SetPen(m_penDarkGrey
);
1619 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1620 dc
.SetPen(m_penHighlight
);
1622 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1625 void wxWin32Renderer::DrawVerticalLine(wxDC
& dc
,
1626 wxCoord x
, wxCoord y1
, wxCoord y2
)
1628 dc
.SetPen(m_penDarkGrey
);
1629 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1630 dc
.SetPen(m_penHighlight
);
1632 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1635 void wxWin32Renderer::DrawFrame(wxDC
& dc
,
1636 const wxString
& label
,
1642 wxCoord height
= 0; // of the label
1643 wxRect rectFrame
= rect
;
1644 if ( !label
.empty() )
1646 // the text should touch the top border of the rect, so the frame
1647 // itself should be lower
1648 dc
.GetTextExtent(label
, NULL
, &height
);
1649 rectFrame
.y
+= height
/ 2;
1650 rectFrame
.height
-= height
/ 2;
1652 // we have to draw each part of the frame individually as we can't
1653 // erase the background beyond the label as it might contain some
1654 // pixmap already, so drawing everything and then overwriting part of
1655 // the frame with label doesn't work
1657 // TODO: the +5 and space insertion should be customizable
1660 rectText
.x
= rectFrame
.x
+ 5;
1661 rectText
.y
= rect
.y
;
1662 rectText
.width
= rectFrame
.width
- 7; // +2 border width
1663 rectText
.height
= height
;
1666 label2
<< _T(' ') << label
<< _T(' ');
1667 if ( indexAccel
!= -1 )
1669 // adjust it as we prepended a space
1674 DrawLabel(dc
, label2
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
1676 StandardDrawFrame(dc
, rectFrame
, rectLabel
);
1680 // just draw the complete frame
1681 DrawShadedRect(dc
, &rectFrame
, m_penDarkGrey
, m_penHighlight
);
1682 DrawShadedRect(dc
, &rectFrame
, m_penHighlight
, m_penDarkGrey
);
1686 // ----------------------------------------------------------------------------
1688 // ----------------------------------------------------------------------------
1690 void wxWin32Renderer::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
1692 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
1693 // pixels each while we really need dots here... PS_ALTERNATE might
1694 // work, but it is for NT 5 only
1696 DrawRect(dc
, &rect
, wxPen(*wxBLACK
, 0, wxDOT
));
1698 // draw the pixels manually: note that to behave in the same manner as
1699 // DrawRect(), we must exclude the bottom and right borders from the
1701 wxCoord x1
= rect
.GetLeft(),
1703 x2
= rect
.GetRight(),
1704 y2
= rect
.GetBottom();
1706 dc
.SetPen(wxPen(*wxBLACK
, 0, wxSOLID
));
1708 // this seems to be closer than what Windows does than wxINVERT although
1709 // I'm still not sure if it's correct
1710 dc
.SetLogicalFunction(wxAND_REVERSE
);
1713 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
1714 dc
.DrawPoint(z
, rect
.GetTop());
1716 wxCoord shift
= z
== x2
? 0 : 1;
1717 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
1718 dc
.DrawPoint(x2
, z
);
1720 shift
= z
== y2
? 0 : 1;
1721 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
1722 dc
.DrawPoint(z
, y2
);
1724 shift
= z
== x1
? 0 : 1;
1725 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
1726 dc
.DrawPoint(x1
, z
);
1728 dc
.SetLogicalFunction(wxCOPY
);
1732 void wxWin32Renderer::DrawLabelShadow(wxDC
& dc
,
1733 const wxString
& label
,
1738 // draw shadow of the text
1739 dc
.SetTextForeground(m_colHighlight
);
1740 wxRect rectShadow
= rect
;
1743 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
1745 // make the text grey
1746 dc
.SetTextForeground(m_colDarkGrey
);
1749 void wxWin32Renderer::DrawLabel(wxDC
& dc
,
1750 const wxString
& label
,
1757 DoDrawLabel(dc
, label
, rect
, flags
, alignment
, indexAccel
, rectBounds
);
1760 void wxWin32Renderer::DoDrawLabel(wxDC
& dc
,
1761 const wxString
& label
,
1767 const wxPoint
& focusOffset
)
1769 // the underscores are not drawn for focused controls in wxMSW
1770 if ( flags
& wxCONTROL_FOCUSED
)
1775 if ( flags
& wxCONTROL_DISABLED
)
1777 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
1778 // currently only can happen for a menu item and it seems that Windows
1779 // doesn't draw the shadow in this case, so we don't do it neither
1780 if ( flags
& wxCONTROL_SELECTED
)
1782 // just make the label text greyed out
1783 dc
.SetTextForeground(m_colDarkGrey
);
1785 else // draw normal disabled label
1787 DrawLabelShadow(dc
, label
, rect
, alignment
, indexAccel
);
1792 dc
.DrawLabel(label
, wxNullBitmap
, rect
, alignment
, indexAccel
, &rectLabel
);
1794 if ( flags
& wxCONTROL_DISABLED
)
1796 // restore the fg colour
1797 dc
.SetTextForeground(*wxBLACK
);
1800 if ( flags
& wxCONTROL_FOCUSED
)
1802 if ( focusOffset
.x
|| focusOffset
.y
)
1804 // before calling Inflate(), ensure that we will have a valid rect
1806 if ( rectLabel
.x
< focusOffset
.x
)
1807 rectLabel
.x
= focusOffset
.x
;
1809 if ( rectLabel
.y
< focusOffset
.y
)
1810 rectLabel
.y
= focusOffset
.y
;
1812 rectLabel
.Inflate(focusOffset
.x
, focusOffset
.y
);
1815 DrawFocusRect(dc
, rectLabel
);
1819 *rectBounds
= rectLabel
;
1822 void wxWin32Renderer::DrawButtonLabel(wxDC
& dc
,
1823 const wxString
& label
,
1824 const wxBitmap
& image
,
1831 // the underscores are not drawn for focused controls in wxMSW
1832 if ( flags
& wxCONTROL_PRESSED
)
1837 wxRect rectLabel
= rect
;
1838 if ( !label
.empty() )
1840 // shift the label if a button is pressed
1841 if ( flags
& wxCONTROL_PRESSED
)
1847 if ( flags
& wxCONTROL_DISABLED
)
1849 DrawLabelShadow(dc
, label
, rectLabel
, alignment
, indexAccel
);
1852 // leave enough space for the focus rectangle
1853 if ( flags
& wxCONTROL_FOCUSED
)
1855 rectLabel
.Inflate(-2);
1859 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
1861 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
1863 if ( flags
& wxCONTROL_PRESSED
)
1865 // the focus rectangle is never pressed, so undo the shift done
1873 DrawFocusRect(dc
, rectLabel
);
1877 // ----------------------------------------------------------------------------
1878 // (check)listbox items
1879 // ----------------------------------------------------------------------------
1881 void wxWin32Renderer::DrawItem(wxDC
& dc
,
1882 const wxString
& label
,
1886 wxDCTextColourChanger
colChanger(dc
);
1888 if ( flags
& wxCONTROL_SELECTED
)
1890 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
1892 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
1893 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
1894 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
1895 dc
.DrawRectangle(rect
);
1898 wxRect rectText
= rect
;
1900 rectText
.width
-= 2;
1901 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
1903 if ( flags
& wxCONTROL_FOCUSED
)
1905 DrawFocusRect(dc
, rect
);
1909 void wxWin32Renderer::DrawCheckItem(wxDC
& dc
,
1910 const wxString
& label
,
1911 const wxBitmap
& bitmap
,
1920 else // use default bitmap
1922 bmp
= wxBitmap(flags
& wxCONTROL_CHECKED
? checked_item_xpm
1923 : unchecked_item_xpm
);
1926 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2 - 1,
1927 TRUE
/* use mask */);
1929 wxRect rectLabel
= rect
;
1930 int bmpWidth
= bmp
.GetWidth();
1931 rectLabel
.x
+= bmpWidth
;
1932 rectLabel
.width
-= bmpWidth
;
1934 DrawItem(dc
, label
, rectLabel
, flags
);
1937 // ----------------------------------------------------------------------------
1938 // check/radio buttons
1939 // ----------------------------------------------------------------------------
1941 wxBitmap
wxWin32Renderer::GetIndicator(IndicatorType indType
, int flags
)
1943 IndicatorState indState
;
1944 if ( flags
& wxCONTROL_SELECTED
)
1945 indState
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
1946 : IndicatorState_Selected
;
1947 else if ( flags
& wxCONTROL_DISABLED
)
1948 indState
= IndicatorState_Disabled
;
1949 else if ( flags
& wxCONTROL_PRESSED
)
1950 indState
= IndicatorState_Pressed
;
1952 indState
= IndicatorState_Normal
;
1954 IndicatorStatus indStatus
= flags
& wxCONTROL_CHECKED
1955 ? IndicatorStatus_Checked
1956 : IndicatorStatus_Unchecked
;
1958 const char **xpm
= bmpIndicators
[indType
][indState
][indStatus
];
1959 return xpm
? wxBitmap(xpm
) : wxNullBitmap
;
1962 void wxWin32Renderer::DrawCheckOrRadioButton(wxDC
& dc
,
1963 const wxString
& label
,
1964 const wxBitmap
& bitmap
,
1969 wxCoord focusOffsetY
)
1971 // calculate the position of the bitmap and of the label
1972 wxCoord heightBmp
= bitmap
.GetHeight();
1974 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
1977 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
1978 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
1980 // align label vertically with the bitmap - looks nicer like this
1981 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
1983 // calc horz position
1984 if ( align
== wxALIGN_RIGHT
)
1986 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
1987 rectLabel
.x
= rect
.x
+ 3;
1988 rectLabel
.SetRight(xBmp
);
1990 else // normal (checkbox to the left of the text) case
1993 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
1994 rectLabel
.SetRight(rect
.GetRight());
1997 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, TRUE
/* use mask */);
2000 dc
, label
, rectLabel
,
2002 wxALIGN_LEFT
| wxALIGN_TOP
,
2004 NULL
, // we don't need bounding rect
2005 // use custom vert focus rect offset
2006 wxPoint(FOCUS_RECT_OFFSET_X
, focusOffsetY
)
2010 void wxWin32Renderer::DrawRadioButton(wxDC
& dc
,
2011 const wxString
& label
,
2012 const wxBitmap
& bitmap
,
2018 DrawCheckOrRadioButton(dc
, label
,
2019 bitmap
.Ok() ? bitmap
: GetRadioBitmap(flags
),
2020 rect
, flags
, align
, indexAccel
,
2021 FOCUS_RECT_OFFSET_Y
); // default focus rect offset
2024 void wxWin32Renderer::DrawCheckButton(wxDC
& dc
,
2025 const wxString
& label
,
2026 const wxBitmap
& bitmap
,
2032 DrawCheckOrRadioButton(dc
, label
,
2033 bitmap
.Ok() ? bitmap
: GetCheckBitmap(flags
),
2034 rect
, flags
, align
, indexAccel
,
2035 0); // no focus rect offset for checkboxes
2038 // ----------------------------------------------------------------------------
2040 // ----------------------------------------------------------------------------
2042 void wxWin32Renderer::DrawTextLine(wxDC
& dc
,
2043 const wxString
& text
,
2049 // nothing special to do here
2050 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
2053 void wxWin32Renderer::DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
)
2055 // we don't draw them
2058 // ----------------------------------------------------------------------------
2060 // ----------------------------------------------------------------------------
2062 void wxWin32Renderer::DrawTab(wxDC
& dc
,
2063 const wxRect
& rectOrig
,
2065 const wxString
& label
,
2066 const wxBitmap
& bitmap
,
2070 wxRect rect
= rectOrig
;
2072 // the current tab is drawn indented (to the top for default case) and
2073 // bigger than the other ones
2074 const wxSize indent
= GetTabIndent();
2075 if ( flags
& wxCONTROL_SELECTED
)
2080 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2084 rect
.Inflate(indent
.x
, 0);
2086 rect
.height
+= indent
.y
;
2090 rect
.Inflate(indent
.x
, 0);
2091 rect
.height
+= indent
.y
;
2096 wxFAIL_MSG(_T("TODO"));
2101 // draw the text, image and the focus around them (if necessary)
2102 wxRect rectLabel
= rect
;
2103 rectLabel
.Deflate(1, 1);
2104 DrawButtonLabel(dc
, label
, bitmap
, rectLabel
,
2105 flags
, wxALIGN_CENTRE
, indexAccel
);
2107 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2108 static const wxCoord CUTOFF
= 2; // radius of the rounded corner
2111 x2
= rect
.GetRight(),
2112 y2
= rect
.GetBottom();
2114 // FIXME: all this code will break if the tab indent or the border width,
2115 // it is tied to the fact that both of them are equal to 2
2120 dc
.SetPen(m_penHighlight
);
2121 dc
.DrawLine(x
, y2
, x
, y
+ CUTOFF
);
2122 dc
.DrawLine(x
, y
+ CUTOFF
, x
+ CUTOFF
, y
);
2123 dc
.DrawLine(x
+ CUTOFF
, y
, x2
- CUTOFF
+ 1, y
);
2125 dc
.SetPen(m_penBlack
);
2126 dc
.DrawLine(x2
, y2
, x2
, y
+ CUTOFF
);
2127 dc
.DrawLine(x2
, y
+ CUTOFF
, x2
- CUTOFF
, y
);
2129 dc
.SetPen(m_penDarkGrey
);
2130 dc
.DrawLine(x2
- 1, y2
, x2
- 1, y
+ CUTOFF
- 1);
2132 if ( flags
& wxCONTROL_SELECTED
)
2134 dc
.SetPen(m_penLightGrey
);
2136 // overwrite the part of the border below this tab
2137 dc
.DrawLine(x
+ 1, y2
+ 1, x2
- 1, y2
+ 1);
2139 // and the shadow of the tab to the left of us
2140 dc
.DrawLine(x
+ 1, y
+ CUTOFF
+ 1, x
+ 1, y2
+ 1);
2145 dc
.SetPen(m_penHighlight
);
2146 // we need to continue one pixel further to overwrite the corner of
2147 // the border for the selected tab
2148 dc
.DrawLine(x
, y
- (flags
& wxCONTROL_SELECTED
? 1 : 0),
2150 dc
.DrawLine(x
, y2
- CUTOFF
, x
+ CUTOFF
, y2
);
2152 dc
.SetPen(m_penBlack
);
2153 dc
.DrawLine(x
+ CUTOFF
, y2
, x2
- CUTOFF
+ 1, y2
);
2154 dc
.DrawLine(x2
, y
, x2
, y2
- CUTOFF
);
2155 dc
.DrawLine(x2
, y2
- CUTOFF
, x2
- CUTOFF
, y2
);
2157 dc
.SetPen(m_penDarkGrey
);
2158 dc
.DrawLine(x
+ CUTOFF
, y2
- 1, x2
- CUTOFF
+ 1, y2
- 1);
2159 dc
.DrawLine(x2
- 1, y
, x2
- 1, y2
- CUTOFF
+ 1);
2161 if ( flags
& wxCONTROL_SELECTED
)
2163 dc
.SetPen(m_penLightGrey
);
2165 // overwrite the part of the (double!) border above this tab
2166 dc
.DrawLine(x
+ 1, y
- 1, x2
- 1, y
- 1);
2167 dc
.DrawLine(x
+ 1, y
- 2, x2
- 1, y
- 2);
2169 // and the shadow of the tab to the left of us
2170 dc
.DrawLine(x
+ 1, y2
- CUTOFF
, x
+ 1, y
- 1);
2176 wxFAIL_MSG(_T("TODO"));
2180 // ----------------------------------------------------------------------------
2182 // ----------------------------------------------------------------------------
2184 wxSize
wxWin32Renderer::GetSliderThumbSize(const wxRect
& rect
,
2185 wxOrientation orient
) const
2189 wxRect rectShaft
= GetSliderShaftRect(rect
, orient
);
2190 if ( orient
== wxHORIZONTAL
)
2192 size
.y
= rect
.height
- 6;
2193 size
.x
= wxMin(size
.y
/ 2, rectShaft
.width
);
2197 size
.x
= rect
.width
- 6;
2198 size
.y
= wxMin(size
.x
/ 2, rectShaft
.height
);
2204 wxRect
wxWin32Renderer::GetSliderShaftRect(const wxRect
& rectOrig
,
2205 wxOrientation orient
) const
2207 static const wxCoord SLIDER_MARGIN
= 6;
2209 wxRect rect
= rectOrig
;
2211 if ( orient
== wxHORIZONTAL
)
2213 // make the rect of minimal width and centre it
2214 rect
.height
= 2*BORDER_THICKNESS
;
2215 rect
.y
= rectOrig
.y
+ (rectOrig
.height
- rect
.height
) / 2;
2219 // leave margins on the sides
2220 rect
.Deflate(SLIDER_MARGIN
, 0);
2224 // same as above but in other direction
2225 rect
.width
= 2*BORDER_THICKNESS
;
2226 rect
.x
= rectOrig
.x
+ (rectOrig
.width
- rect
.width
) / 2;
2230 rect
.Deflate(0, SLIDER_MARGIN
);
2236 void wxWin32Renderer::DrawSliderShaft(wxDC
& dc
,
2237 const wxRect
& rectOrig
,
2238 wxOrientation orient
,
2242 if ( flags
& wxCONTROL_FOCUSED
)
2244 DrawFocusRect(dc
, rectOrig
);
2247 wxRect rect
= GetSliderShaftRect(rectOrig
, orient
);
2252 DrawSunkenBorder(dc
, &rect
);
2255 void wxWin32Renderer::DrawSliderThumb(wxDC
& dc
,
2257 wxOrientation orient
,
2261 we are drawing a shape of this form
2266 H DB where H is hightlight colour
2279 The interior of this shape is filled with the hatched brush if the thumb
2283 DrawBackground(dc
, wxNullColour
, rect
, flags
);
2285 bool transpose
= orient
== wxVERTICAL
;
2287 wxCoord x
, y
, x2
, y2
;
2292 x2
= rect
.GetBottom();
2293 y2
= rect
.GetRight();
2299 x2
= rect
.GetRight();
2300 y2
= rect
.GetBottom();
2303 // the size of the pointed part of the thumb
2304 wxCoord sizeArrow
= (transpose
? rect
.height
: rect
.width
) / 2;
2306 wxCoord x3
= x
+ sizeArrow
,
2307 y3
= y2
- sizeArrow
;
2309 dc
.SetPen(m_penHighlight
);
2310 DrawLine(dc
, x
, y
, x2
, y
, transpose
);
2311 DrawLine(dc
, x
, y
+ 1, x
, y2
- sizeArrow
, transpose
);
2312 DrawLine(dc
, x
, y3
, x3
, y2
, transpose
);
2314 dc
.SetPen(m_penBlack
);
2315 DrawLine(dc
, x3
, y2
, x2
, y3
, transpose
);
2316 DrawLine(dc
, x2
, y3
, x2
, y
- 1, transpose
);
2318 dc
.SetPen(m_penDarkGrey
);
2319 DrawLine(dc
, x3
, y2
- 1, x2
- 1, y3
, transpose
);
2320 DrawLine(dc
, x2
- 1, y3
, x2
- 1, y
, transpose
);
2322 if ( flags
& wxCONTROL_PRESSED
)
2324 // TODO: MSW fills the entire area inside, not just the rect
2325 wxRect rectInt
= rect
;
2327 rectInt
.SetRight(y3
);
2329 rectInt
.SetBottom(y3
);
2332 static const char *stipple_xpm
[] = {
2333 /* columns rows colors chars-per-pixel */
2341 dc
.SetBrush(wxBrush(stipple_xpm
));
2343 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, SHADOW_HIGHLIGHT
));
2344 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, CONTROL
));
2345 dc
.SetPen(*wxTRANSPARENT_PEN
);
2346 dc
.DrawRectangle(rectInt
);
2350 void wxWin32Renderer::DrawSliderTicks(wxDC
& dc
,
2352 const wxSize
& sizeThumb
,
2353 wxOrientation orient
,
2365 // the variable names correspond to horizontal case, but they can be used
2366 // for both orientations
2367 wxCoord x1
, x2
, y1
, y2
, len
, widthThumb
;
2368 if ( orient
== wxHORIZONTAL
)
2370 x1
= rect
.GetLeft();
2371 x2
= rect
.GetRight();
2373 // draw from bottom to top to leave one pixel space between the ticks
2374 // and the slider as Windows do
2375 y1
= rect
.GetBottom();
2380 widthThumb
= sizeThumb
.x
;
2385 x2
= rect
.GetBottom();
2387 y1
= rect
.GetRight();
2388 y2
= rect
.GetLeft();
2392 widthThumb
= sizeThumb
.y
;
2395 // the first tick should be positioned in such way that a thumb drawn in
2396 // the first position points down directly to it
2397 x1
+= widthThumb
/ 2;
2398 x2
-= widthThumb
/ 2;
2400 // this also means that we have slightly less space for the ticks in
2401 // between the first and the last
2404 dc
.SetPen(m_penBlack
);
2406 int range
= end
- start
;
2407 for ( int n
= 0; n
< range
; n
+= step
)
2409 wxCoord x
= x1
+ (len
*n
) / range
;
2411 DrawLine(dc
, x
, y1
, x
, y2
, orient
== wxVERTICAL
);
2414 // always draw the line at the end position
2415 DrawLine(dc
, x2
, y1
, x2
, y2
, orient
== wxVERTICAL
);
2418 // ----------------------------------------------------------------------------
2420 // ----------------------------------------------------------------------------
2422 // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2423 class WXDLLEXPORT wxWin32MenuGeometryInfo
: public wxMenuGeometryInfo
2426 virtual wxSize
GetSize() const { return m_size
; }
2428 wxCoord
GetLabelOffset() const { return m_ofsLabel
; }
2429 wxCoord
GetAccelOffset() const { return m_ofsAccel
; }
2431 wxCoord
GetItemHeight() const { return m_heightItem
; }
2434 // the total size of the menu
2437 // the offset of the start of the menu item label
2440 // the offset of the start of the accel label
2443 // the height of a normal (not separator) item
2444 wxCoord m_heightItem
;
2446 friend wxMenuGeometryInfo
*wxWin32Renderer::
2447 GetMenuGeometry(wxWindow
*, const wxMenu
&) const;
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 void wxWin32Renderer::DrawMenuBarItem(wxDC
& dc
,
2470 const wxRect
& rectOrig
,
2471 const wxString
& label
,
2475 wxRect rect
= rectOrig
;
2478 wxDCTextColourChanger
colChanger(dc
);
2480 if ( flags
& wxCONTROL_SELECTED
)
2482 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2484 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2485 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2486 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2487 dc
.DrawRectangle(rect
);
2490 // don't draw the focus rect around menu bar items
2491 DrawLabel(dc
, label
, rect
, flags
& ~wxCONTROL_FOCUSED
,
2492 wxALIGN_CENTRE
, indexAccel
);
2495 void wxWin32Renderer::DrawMenuItem(wxDC
& dc
,
2497 const wxMenuGeometryInfo
& gi
,
2498 const wxString
& label
,
2499 const wxString
& accel
,
2500 const wxBitmap
& bitmap
,
2504 const wxWin32MenuGeometryInfo
& geometryInfo
=
2505 (const wxWin32MenuGeometryInfo
&)gi
;
2510 rect
.width
= geometryInfo
.GetSize().x
;
2511 rect
.height
= geometryInfo
.GetItemHeight();
2513 // draw the selected item specially
2514 wxDCTextColourChanger
colChanger(dc
);
2515 if ( flags
& wxCONTROL_SELECTED
)
2517 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2519 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2520 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2521 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2522 dc
.DrawRectangle(rect
);
2525 // draw the bitmap: use the bitmap provided or the standard checkmark for
2526 // the checkable items
2527 wxBitmap bmp
= bitmap
;
2528 if ( !bmp
.Ok() && (flags
& wxCONTROL_CHECKED
) )
2530 bmp
= GetIndicator(IndicatorType_Menu
, flags
);
2535 rect
.SetRight(geometryInfo
.GetLabelOffset());
2536 wxControlRenderer::DrawBitmap(dc
, bmp
, rect
);
2540 rect
.x
= geometryInfo
.GetLabelOffset();
2541 rect
.SetRight(geometryInfo
.GetAccelOffset());
2543 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
, indexAccel
);
2545 // draw the accel string
2546 rect
.x
= geometryInfo
.GetAccelOffset();
2547 rect
.SetRight(geometryInfo
.GetSize().x
);
2549 // NB: no accel index here
2550 DrawLabel(dc
, accel
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
);
2552 // draw the submenu indicator
2553 if ( flags
& wxCONTROL_ISSUBMENU
)
2555 rect
.x
= geometryInfo
.GetSize().x
- MENU_RIGHT_MARGIN
;
2556 rect
.width
= MENU_RIGHT_MARGIN
;
2558 wxArrowStyle arrowStyle
;
2559 if ( flags
& wxCONTROL_DISABLED
)
2560 arrowStyle
= flags
& wxCONTROL_SELECTED
? Arrow_InversedDisabled
2562 else if ( flags
& wxCONTROL_SELECTED
)
2563 arrowStyle
= Arrow_Inversed
;
2565 arrowStyle
= Arrow_Normal
;
2567 DrawArrow(dc
, rect
, Arrow_Right
, arrowStyle
);
2571 void wxWin32Renderer::DrawMenuSeparator(wxDC
& dc
,
2573 const wxMenuGeometryInfo
& geomInfo
)
2575 DrawHorizontalLine(dc
, y
+ MENU_VERT_MARGIN
, 0, geomInfo
.GetSize().x
);
2578 wxSize
wxWin32Renderer::GetMenuBarItemSize(const wxSize
& sizeText
) const
2580 wxSize size
= sizeText
;
2582 // FIXME: menubar height is configurable under Windows
2589 wxMenuGeometryInfo
*wxWin32Renderer::GetMenuGeometry(wxWindow
*win
,
2590 const wxMenu
& menu
) const
2592 // prepare the dc: for now we draw all the items with the system font
2594 dc
.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
));
2596 // the height of a normal item
2597 wxCoord heightText
= dc
.GetCharHeight();
2602 // the max length of label and accel strings: the menu width is the sum of
2603 // them, even if they're for different items (as the accels should be
2606 // the max length of the bitmap is never 0 as Windows always leaves enough
2607 // space for a check mark indicator
2608 wxCoord widthLabelMax
= 0,
2610 widthBmpMax
= MENU_LEFT_MARGIN
;
2612 for ( wxMenuItemList::Node
*node
= menu
.GetMenuItems().GetFirst();
2614 node
= node
->GetNext() )
2616 // height of this item
2619 wxMenuItem
*item
= node
->GetData();
2620 if ( item
->IsSeparator() )
2622 h
= MENU_SEPARATOR_HEIGHT
;
2624 else // not separator
2629 dc
.GetTextExtent(item
->GetLabel(), &widthLabel
, NULL
);
2630 if ( widthLabel
> widthLabelMax
)
2632 widthLabelMax
= widthLabel
;
2636 dc
.GetTextExtent(item
->GetAccelString(), &widthAccel
, NULL
);
2637 if ( widthAccel
> widthAccelMax
)
2639 widthAccelMax
= widthAccel
;
2642 const wxBitmap
& bmp
= item
->GetBitmap();
2645 wxCoord widthBmp
= bmp
.GetWidth();
2646 if ( widthBmp
> widthBmpMax
)
2647 widthBmpMax
= widthBmp
;
2649 //else if ( item->IsCheckable() ): no need to check for this as
2650 // MENU_LEFT_MARGIN is big enough to show the check mark
2653 h
+= 2*MENU_VERT_MARGIN
;
2655 // remember the item position and height
2656 item
->SetGeometry(height
, h
);
2661 // bundle the metrics into a struct and return it
2662 wxWin32MenuGeometryInfo
*gi
= new wxWin32MenuGeometryInfo
;
2664 gi
->m_ofsLabel
= widthBmpMax
+ 2*MENU_BMP_MARGIN
;
2665 gi
->m_ofsAccel
= gi
->m_ofsLabel
+ widthLabelMax
;
2666 if ( widthAccelMax
> 0 )
2668 // if we actually have any accesl, add a margin
2669 gi
->m_ofsAccel
+= MENU_ACCEL_MARGIN
;
2672 gi
->m_heightItem
= heightText
+ 2*MENU_VERT_MARGIN
;
2674 gi
->m_size
.x
= gi
->m_ofsAccel
+ widthAccelMax
+ MENU_RIGHT_MARGIN
;
2675 gi
->m_size
.y
= height
;
2680 // ----------------------------------------------------------------------------
2682 // ----------------------------------------------------------------------------
2684 void wxWin32Renderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
2685 wxBitmap
*bmpPressed
,
2686 wxBitmap
*bmpDisabled
)
2688 static const wxCoord widthCombo
= 16;
2689 static const wxCoord heightCombo
= 17;
2695 bmpNormal
->Create(widthCombo
, heightCombo
);
2696 dcMem
.SelectObject(*bmpNormal
);
2697 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2698 Arrow_Down
, Arrow_Normal
);
2703 bmpPressed
->Create(widthCombo
, heightCombo
);
2704 dcMem
.SelectObject(*bmpPressed
);
2705 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2706 Arrow_Down
, Arrow_Pressed
);
2711 bmpDisabled
->Create(widthCombo
, heightCombo
);
2712 dcMem
.SelectObject(*bmpDisabled
);
2713 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2714 Arrow_Down
, Arrow_Disabled
);
2718 // ----------------------------------------------------------------------------
2720 // ----------------------------------------------------------------------------
2722 void wxWin32Renderer::DoDrawBackground(wxDC
& dc
,
2723 const wxColour
& col
,
2726 wxBrush
brush(col
, wxSOLID
);
2728 dc
.SetPen(*wxTRANSPARENT_PEN
);
2729 dc
.DrawRectangle(rect
);
2732 void wxWin32Renderer::DrawBackground(wxDC
& dc
,
2733 const wxColour
& col
,
2737 // just fill it with the given or default bg colour
2738 wxColour colBg
= col
.Ok() ? col
: wxSCHEME_COLOUR(m_scheme
, CONTROL
);
2739 DoDrawBackground(dc
, colBg
, rect
);
2742 // ----------------------------------------------------------------------------
2744 // ----------------------------------------------------------------------------
2746 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2751 // get the bitmap for this arrow
2752 wxArrowDirection arrowDir
;
2755 case wxLEFT
: arrowDir
= Arrow_Left
; break;
2756 case wxRIGHT
: arrowDir
= Arrow_Right
; break;
2757 case wxUP
: arrowDir
= Arrow_Up
; break;
2758 case wxDOWN
: arrowDir
= Arrow_Down
; break;
2761 wxFAIL_MSG(_T("unknown arrow direction"));
2765 wxArrowStyle arrowStyle
;
2766 if ( flags
& wxCONTROL_PRESSED
)
2768 // can't be pressed and disabled
2769 arrowStyle
= Arrow_Pressed
;
2773 arrowStyle
= flags
& wxCONTROL_DISABLED
? Arrow_Disabled
: Arrow_Normal
;
2776 DrawArrowButton(dc
, rect
, arrowDir
, arrowStyle
);
2779 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2781 wxArrowDirection arrowDir
,
2782 wxArrowStyle arrowStyle
)
2784 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
2786 // under Windows the arrows always have the same size so just centre it in
2787 // the provided rectangle
2788 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
2789 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
2791 // Windows does it like this...
2792 if ( arrowDir
== Arrow_Left
)
2796 dc
.DrawBitmap(bmp
, x
, y
, TRUE
/* use mask */);
2799 void wxWin32Renderer::DrawArrowButton(wxDC
& dc
,
2800 const wxRect
& rectAll
,
2801 wxArrowDirection arrowDir
,
2802 wxArrowStyle arrowStyle
)
2804 wxRect rect
= rectAll
;
2805 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2806 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
2807 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
2810 void wxWin32Renderer::DrawScrollbarThumb(wxDC
& dc
,
2811 wxOrientation orient
,
2815 // we don't use the flags, the thumb never changes appearance
2816 wxRect rectThumb
= rect
;
2817 DrawArrowBorder(dc
, &rectThumb
);
2818 DrawBackground(dc
, wxNullColour
, rectThumb
);
2821 void wxWin32Renderer::DrawScrollbarShaft(wxDC
& dc
,
2822 wxOrientation orient
,
2823 const wxRect
& rectBar
,
2826 wxColourScheme::StdColour col
= flags
& wxCONTROL_PRESSED
2827 ? wxColourScheme::SCROLLBAR_PRESSED
2828 : wxColourScheme::SCROLLBAR
;
2829 DoDrawBackground(dc
, m_scheme
->Get(col
), rectBar
);
2832 void wxWin32Renderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
2834 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2837 wxRect
wxWin32Renderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
2838 wxScrollBar::Element elem
,
2841 return StandardGetScrollbarRect(scrollbar
, elem
,
2842 thumbPos
, m_sizeScrollbarArrow
);
2845 wxCoord
wxWin32Renderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
2847 return StandardScrollBarSize(scrollbar
, m_sizeScrollbarArrow
);
2850 wxHitTest
wxWin32Renderer::HitTestScrollbar(const wxScrollBar
*scrollbar
,
2851 const wxPoint
& pt
) const
2853 return StandardHitTestScrollbar(scrollbar
, pt
, m_sizeScrollbarArrow
);
2856 wxCoord
wxWin32Renderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
2859 return StandardScrollbarToPixel(scrollbar
, thumbPos
, m_sizeScrollbarArrow
);
2862 int wxWin32Renderer::PixelToScrollbar(const wxScrollBar
*scrollbar
,
2865 return StandardPixelToScrollbar(scrollbar
, coord
, m_sizeScrollbarArrow
);
2868 // ----------------------------------------------------------------------------
2869 // text control geometry
2870 // ----------------------------------------------------------------------------
2872 static inline int GetTextBorderWidth()
2877 wxRect
wxWin32Renderer::GetTextTotalArea(const wxTextCtrl
*text
,
2880 wxRect rectTotal
= rect
;
2882 wxCoord widthBorder
= GetTextBorderWidth();
2883 if ( rectTotal
.x
< widthBorder
)
2884 rectTotal
.x
= widthBorder
;
2885 if ( rectTotal
.y
< widthBorder
)
2886 rectTotal
.y
= widthBorder
;
2888 rectTotal
.Inflate(widthBorder
);
2890 // this is what Windows does
2896 wxRect
wxWin32Renderer::GetTextClientArea(const wxTextCtrl
*text
,
2898 wxCoord
*extraSpaceBeyond
)
2900 wxRect rectText
= rect
;
2902 // undo GetTextTotalArea()
2903 if ( rectText
.height
> 0 )
2906 wxCoord widthBorder
= GetTextBorderWidth();
2907 if ( rectText
.width
< 2*widthBorder
)
2908 rectText
.width
= 2*widthBorder
;
2909 if ( rectText
.height
< 2*widthBorder
)
2910 rectText
.height
= 2*widthBorder
;
2912 rectText
.Inflate(-widthBorder
);
2914 if ( extraSpaceBeyond
)
2915 *extraSpaceBeyond
= 0;
2920 // ----------------------------------------------------------------------------
2922 // ----------------------------------------------------------------------------
2924 void wxWin32Renderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
2927 if ( wxDynamicCast(window
, wxScrollBar
) )
2929 // we only set the width of vert scrollbars and height of the
2931 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
2932 size
->y
= m_sizeScrollbarArrow
.y
;
2934 size
->x
= m_sizeScrollbarArrow
.x
;
2936 // skip border width adjustments, they don't make sense for us
2939 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
2942 if ( wxDynamicCast(window
, wxButton
) )
2945 size
->x
+= 3*window
->GetCharWidth();
2946 #if 0 // do allow creating small buttons if wanted
2947 wxSize sizeDef
= wxButton::GetDefaultSize();
2948 if ( size
->x
< sizeDef
.x
)
2949 size
->x
= sizeDef
.x
;
2952 wxCoord heightBtn
= (11*(window
->GetCharHeight() + 8))/10;
2953 if ( size
->y
< heightBtn
- 8 )
2954 size
->y
= heightBtn
;
2958 // no border width adjustments for buttons
2961 #endif // wxUSE_BUTTON
2963 // take into account the border width
2964 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
2965 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
2966 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
2969 // ============================================================================
2971 // ============================================================================
2973 // ----------------------------------------------------------------------------
2974 // wxWin32InputHandler
2975 // ----------------------------------------------------------------------------
2977 wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer
*renderer
)
2979 m_renderer
= renderer
;
2982 bool wxWin32InputHandler::HandleKey(wxControl
*control
,
2983 const wxKeyEvent
& event
,
2989 bool wxWin32InputHandler::HandleMouse(wxControl
*control
,
2990 const wxMouseEvent
& event
)
2995 // ----------------------------------------------------------------------------
2996 // wxWin32ScrollBarInputHandler
2997 // ----------------------------------------------------------------------------
2999 wxWin32ScrollBarInputHandler::
3000 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
3001 wxInputHandler
*handler
)
3002 : wxStdScrollBarInputHandler(renderer
, handler
)
3004 m_scrollPaused
= FALSE
;
3008 bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar
*scrollbar
,
3009 const wxControlAction
& action
)
3011 // stop if went beyond the position of the original click (this can only
3012 // happen when we scroll by pages)
3014 if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
3016 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3017 != wxHT_SCROLLBAR_BAR_2
;
3019 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
3021 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3022 != wxHT_SCROLLBAR_BAR_1
;
3027 StopScrolling(scrollbar
);
3029 scrollbar
->Refresh();
3034 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar
, action
);
3037 bool wxWin32ScrollBarInputHandler::HandleMouse(wxControl
*control
,
3038 const wxMouseEvent
& event
)
3040 // remember the current state
3041 bool wasDraggingThumb
= m_htLast
== wxHT_SCROLLBAR_THUMB
;
3043 // do process the message
3044 bool rc
= wxStdScrollBarInputHandler::HandleMouse(control
, event
);
3046 // analyse the changes
3047 if ( !wasDraggingThumb
&& (m_htLast
== wxHT_SCROLLBAR_THUMB
) )
3049 // we just started dragging the thumb, remember its initial position to
3050 // be able to restore it if the drag is cancelled later
3051 m_eventStartDrag
= event
;
3057 bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl
*control
,
3058 const wxMouseEvent
& event
)
3060 // we don't highlight scrollbar elements, so there is no need to process
3061 // mouse move events normally - only do it while mouse is captured (i.e.
3062 // when we're dragging the thumb or pressing on something)
3063 if ( !m_winCapture
)
3066 if ( event
.Entering() )
3068 // we're not interested in this at all
3072 wxScrollBar
*scrollbar
= wxStaticCast(control
, wxScrollBar
);
3074 if ( m_scrollPaused
)
3076 // check if the mouse returned to its original location
3078 if ( event
.Leaving() )
3084 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3085 if ( ht
== m_htLast
)
3087 // yes it did, resume scrolling
3088 m_scrollPaused
= FALSE
;
3089 if ( m_timerScroll
)
3091 // we were scrolling by line/page, restart timer
3092 m_timerScroll
->Start(m_interval
);
3094 Press(scrollbar
, TRUE
);
3096 else // we were dragging the thumb
3098 // restore its last location
3099 HandleThumbMove(scrollbar
, m_eventLastDrag
);
3105 else // normal case, scrolling hasn't been paused
3107 // if we're scrolling the scrollbar because the arrow or the shaft was
3108 // pressed, check that the mouse stays on the same scrollbar element
3110 if ( event
.Moving() )
3112 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3114 else // event.Leaving()
3119 // if we're dragging the thumb and the mouse stays in the scrollbar, it
3120 // is still ok - we only want to catch the case when the mouse leaves
3121 // the scrollbar here
3122 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
&& ht
!= wxHT_NOWHERE
)
3124 ht
= wxHT_SCROLLBAR_THUMB
;
3127 if ( ht
!= m_htLast
)
3129 // what were we doing? 2 possibilities: either an arrow/shaft was
3130 // pressed in which case we have a timer and so we just stop it or
3131 // we were dragging the thumb
3132 if ( m_timerScroll
)
3135 m_interval
= m_timerScroll
->GetInterval();
3136 m_timerScroll
->Stop();
3137 m_scrollPaused
= TRUE
;
3139 // unpress the arrow
3140 Press(scrollbar
, FALSE
);
3142 else // we were dragging the thumb
3144 // remember the current thumb position to be able to restore it
3145 // if the mouse returns to it later
3146 m_eventLastDrag
= event
;
3148 // and restore the original position (before dragging) of the
3150 HandleThumbMove(scrollbar
, m_eventStartDrag
);
3157 return wxStdScrollBarInputHandler::HandleMouseMove(control
, event
);
3160 // ----------------------------------------------------------------------------
3161 // wxWin32CheckboxInputHandler
3162 // ----------------------------------------------------------------------------
3164 bool wxWin32CheckboxInputHandler::HandleKey(wxControl
*control
,
3165 const wxKeyEvent
& event
,
3170 wxControlAction action
;
3171 int keycode
= event
.GetKeyCode();
3175 action
= wxACTION_CHECKBOX_TOGGLE
;
3179 case WXK_NUMPAD_SUBTRACT
:
3180 action
= wxACTION_CHECKBOX_CHECK
;
3184 case WXK_NUMPAD_ADD
:
3185 case WXK_NUMPAD_EQUAL
:
3186 action
= wxACTION_CHECKBOX_CLEAR
;
3192 control
->PerformAction(action
);
3201 // ----------------------------------------------------------------------------
3202 // wxWin32TextCtrlInputHandler
3203 // ----------------------------------------------------------------------------
3205 bool wxWin32TextCtrlInputHandler::HandleKey(wxControl
*control
,
3206 const wxKeyEvent
& event
,
3209 // handle only MSW-specific text bindings here, the others are handled in
3213 int keycode
= event
.GetKeyCode();
3215 wxControlAction action
;
3216 if ( keycode
== WXK_DELETE
&& event
.ShiftDown() )
3218 action
= wxACTION_TEXT_CUT
;
3220 else if ( keycode
== WXK_INSERT
)
3222 if ( event
.ControlDown() )
3223 action
= wxACTION_TEXT_COPY
;
3224 else if ( event
.ShiftDown() )
3225 action
= wxACTION_TEXT_PASTE
;
3228 if ( action
!= wxACTION_NONE
)
3230 control
->PerformAction(action
);
3236 return wxStdTextCtrlInputHandler::HandleKey(control
, event
, pressed
);