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 rectLabel
.Inflate(focusOffset
.x
, focusOffset
.y
);
1807 DrawFocusRect(dc
, rectLabel
);
1811 *rectBounds
= rectLabel
;
1814 void wxWin32Renderer::DrawButtonLabel(wxDC
& dc
,
1815 const wxString
& label
,
1816 const wxBitmap
& image
,
1823 // the underscores are not drawn for focused controls in wxMSW
1824 if ( flags
& wxCONTROL_PRESSED
)
1829 wxRect rectLabel
= rect
;
1830 if ( !label
.empty() )
1832 // shift the label if a button is pressed
1833 if ( flags
& wxCONTROL_PRESSED
)
1839 if ( flags
& wxCONTROL_DISABLED
)
1841 DrawLabelShadow(dc
, label
, rectLabel
, alignment
, indexAccel
);
1844 // leave enough space for the focus rectangle
1845 if ( flags
& wxCONTROL_FOCUSED
)
1847 rectLabel
.Inflate(-2);
1851 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
1853 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
1855 if ( flags
& wxCONTROL_PRESSED
)
1857 // the focus rectangle is never pressed, so undo the shift done
1865 DrawFocusRect(dc
, rectLabel
);
1869 // ----------------------------------------------------------------------------
1870 // (check)listbox items
1871 // ----------------------------------------------------------------------------
1873 void wxWin32Renderer::DrawItem(wxDC
& dc
,
1874 const wxString
& label
,
1878 wxDCTextColourChanger
colChanger(dc
);
1880 if ( flags
& wxCONTROL_SELECTED
)
1882 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
1884 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
1885 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
1886 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
1887 dc
.DrawRectangle(rect
);
1890 wxRect rectText
= rect
;
1892 rectText
.width
-= 2;
1893 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
1895 if ( flags
& wxCONTROL_FOCUSED
)
1897 DrawFocusRect(dc
, rect
);
1901 void wxWin32Renderer::DrawCheckItem(wxDC
& dc
,
1902 const wxString
& label
,
1903 const wxBitmap
& bitmap
,
1912 else // use default bitmap
1914 bmp
= wxBitmap(flags
& wxCONTROL_CHECKED
? checked_item_xpm
1915 : unchecked_item_xpm
);
1918 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2 - 1,
1919 TRUE
/* use mask */);
1921 wxRect rectLabel
= rect
;
1922 int bmpWidth
= bmp
.GetWidth();
1923 rectLabel
.x
+= bmpWidth
;
1924 rectLabel
.width
-= bmpWidth
;
1926 DrawItem(dc
, label
, rectLabel
, flags
);
1929 // ----------------------------------------------------------------------------
1930 // check/radio buttons
1931 // ----------------------------------------------------------------------------
1933 wxBitmap
wxWin32Renderer::GetIndicator(IndicatorType indType
, int flags
)
1935 IndicatorState indState
;
1936 if ( flags
& wxCONTROL_SELECTED
)
1937 indState
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
1938 : IndicatorState_Selected
;
1939 else if ( flags
& wxCONTROL_DISABLED
)
1940 indState
= IndicatorState_Disabled
;
1941 else if ( flags
& wxCONTROL_PRESSED
)
1942 indState
= IndicatorState_Pressed
;
1944 indState
= IndicatorState_Normal
;
1946 IndicatorStatus indStatus
= flags
& wxCONTROL_CHECKED
1947 ? IndicatorStatus_Checked
1948 : IndicatorStatus_Unchecked
;
1950 const char **xpm
= bmpIndicators
[indType
][indState
][indStatus
];
1951 return xpm
? wxBitmap(xpm
) : wxNullBitmap
;
1954 void wxWin32Renderer::DrawCheckOrRadioButton(wxDC
& dc
,
1955 const wxString
& label
,
1956 const wxBitmap
& bitmap
,
1961 wxCoord focusOffsetY
)
1963 // calculate the position of the bitmap and of the label
1964 wxCoord heightBmp
= bitmap
.GetHeight();
1966 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
1969 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
1970 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
1972 // align label vertically with the bitmap - looks nicer like this
1973 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
1975 // calc horz position
1976 if ( align
== wxALIGN_RIGHT
)
1978 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
1979 rectLabel
.x
= rect
.x
+ 3;
1980 rectLabel
.SetRight(xBmp
);
1982 else // normal (checkbox to the left of the text) case
1985 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
1986 rectLabel
.SetRight(rect
.GetRight());
1989 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, TRUE
/* use mask */);
1992 dc
, label
, rectLabel
,
1994 wxALIGN_LEFT
| wxALIGN_TOP
,
1996 NULL
, // we don't need bounding rect
1997 // use custom vert focus rect offset
1998 wxPoint(FOCUS_RECT_OFFSET_X
, focusOffsetY
)
2002 void wxWin32Renderer::DrawRadioButton(wxDC
& dc
,
2003 const wxString
& label
,
2004 const wxBitmap
& bitmap
,
2010 DrawCheckOrRadioButton(dc
, label
,
2011 bitmap
.Ok() ? bitmap
: GetRadioBitmap(flags
),
2012 rect
, flags
, align
, indexAccel
,
2013 FOCUS_RECT_OFFSET_Y
); // default focus rect offset
2016 void wxWin32Renderer::DrawCheckButton(wxDC
& dc
,
2017 const wxString
& label
,
2018 const wxBitmap
& bitmap
,
2024 DrawCheckOrRadioButton(dc
, label
,
2025 bitmap
.Ok() ? bitmap
: GetCheckBitmap(flags
),
2026 rect
, flags
, align
, indexAccel
,
2027 0); // no focus rect offset for checkboxes
2030 // ----------------------------------------------------------------------------
2032 // ----------------------------------------------------------------------------
2034 void wxWin32Renderer::DrawTextLine(wxDC
& dc
,
2035 const wxString
& text
,
2041 // nothing special to do here
2042 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
2045 void wxWin32Renderer::DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
)
2047 // we don't draw them
2050 // ----------------------------------------------------------------------------
2052 // ----------------------------------------------------------------------------
2054 void wxWin32Renderer::DrawTab(wxDC
& dc
,
2055 const wxRect
& rectOrig
,
2057 const wxString
& label
,
2058 const wxBitmap
& bitmap
,
2062 wxRect rect
= rectOrig
;
2064 // the current tab is drawn indented (to the top for default case) and
2065 // bigger than the other ones
2066 const wxSize indent
= GetTabIndent();
2067 if ( flags
& wxCONTROL_SELECTED
)
2072 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2076 rect
.Inflate(indent
.x
, 0);
2078 rect
.height
+= indent
.y
;
2082 rect
.Inflate(indent
.x
, 0);
2083 rect
.height
+= indent
.y
;
2088 wxFAIL_MSG(_T("TODO"));
2093 // draw the text, image and the focus around them (if necessary)
2094 wxRect rectLabel
= rect
;
2095 rectLabel
.Deflate(1, 1);
2096 DrawButtonLabel(dc
, label
, bitmap
, rectLabel
,
2097 flags
, wxALIGN_CENTRE
, indexAccel
);
2099 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2100 static const wxCoord CUTOFF
= 2; // radius of the rounded corner
2103 x2
= rect
.GetRight(),
2104 y2
= rect
.GetBottom();
2106 // FIXME: all this code will break if the tab indent or the border width,
2107 // it is tied to the fact that both of them are equal to 2
2112 dc
.SetPen(m_penHighlight
);
2113 dc
.DrawLine(x
, y2
, x
, y
+ CUTOFF
);
2114 dc
.DrawLine(x
, y
+ CUTOFF
, x
+ CUTOFF
, y
);
2115 dc
.DrawLine(x
+ CUTOFF
, y
, x2
- CUTOFF
+ 1, y
);
2117 dc
.SetPen(m_penBlack
);
2118 dc
.DrawLine(x2
, y2
, x2
, y
+ CUTOFF
);
2119 dc
.DrawLine(x2
, y
+ CUTOFF
, x2
- CUTOFF
, y
);
2121 dc
.SetPen(m_penDarkGrey
);
2122 dc
.DrawLine(x2
- 1, y2
, x2
- 1, y
+ CUTOFF
- 1);
2124 if ( flags
& wxCONTROL_SELECTED
)
2126 dc
.SetPen(m_penLightGrey
);
2128 // overwrite the part of the border below this tab
2129 dc
.DrawLine(x
+ 1, y2
+ 1, x2
- 1, y2
+ 1);
2131 // and the shadow of the tab to the left of us
2132 dc
.DrawLine(x
+ 1, y
+ CUTOFF
+ 1, x
+ 1, y2
+ 1);
2137 dc
.SetPen(m_penHighlight
);
2138 // we need to continue one pixel further to overwrite the corner of
2139 // the border for the selected tab
2140 dc
.DrawLine(x
, y
- (flags
& wxCONTROL_SELECTED
? 1 : 0),
2142 dc
.DrawLine(x
, y2
- CUTOFF
, x
+ CUTOFF
, y2
);
2144 dc
.SetPen(m_penBlack
);
2145 dc
.DrawLine(x
+ CUTOFF
, y2
, x2
- CUTOFF
+ 1, y2
);
2146 dc
.DrawLine(x2
, y
, x2
, y2
- CUTOFF
);
2147 dc
.DrawLine(x2
, y2
- CUTOFF
, x2
- CUTOFF
, y2
);
2149 dc
.SetPen(m_penDarkGrey
);
2150 dc
.DrawLine(x
+ CUTOFF
, y2
- 1, x2
- CUTOFF
+ 1, y2
- 1);
2151 dc
.DrawLine(x2
- 1, y
, x2
- 1, y2
- CUTOFF
+ 1);
2153 if ( flags
& wxCONTROL_SELECTED
)
2155 dc
.SetPen(m_penLightGrey
);
2157 // overwrite the part of the (double!) border above this tab
2158 dc
.DrawLine(x
+ 1, y
- 1, x2
- 1, y
- 1);
2159 dc
.DrawLine(x
+ 1, y
- 2, x2
- 1, y
- 2);
2161 // and the shadow of the tab to the left of us
2162 dc
.DrawLine(x
+ 1, y2
- CUTOFF
, x
+ 1, y
- 1);
2168 wxFAIL_MSG(_T("TODO"));
2172 // ----------------------------------------------------------------------------
2174 // ----------------------------------------------------------------------------
2176 wxSize
wxWin32Renderer::GetSliderThumbSize(const wxRect
& rect
,
2177 wxOrientation orient
) const
2181 wxRect rectShaft
= GetSliderShaftRect(rect
, orient
);
2182 if ( orient
== wxHORIZONTAL
)
2184 size
.y
= rect
.height
- 6;
2185 size
.x
= wxMin(size
.y
/ 2, rectShaft
.width
);
2189 size
.x
= rect
.width
- 6;
2190 size
.y
= wxMin(size
.x
/ 2, rectShaft
.height
);
2196 wxRect
wxWin32Renderer::GetSliderShaftRect(const wxRect
& rectOrig
,
2197 wxOrientation orient
) const
2199 static const wxCoord SLIDER_MARGIN
= 6;
2201 wxRect rect
= rectOrig
;
2203 if ( orient
== wxHORIZONTAL
)
2205 // make the rect of minimal width and centre it
2206 rect
.height
= 2*BORDER_THICKNESS
;
2207 rect
.y
= rectOrig
.y
+ (rectOrig
.height
- rect
.height
) / 2;
2211 // leave margins on the sides
2212 rect
.Deflate(SLIDER_MARGIN
, 0);
2216 // same as above but in other direction
2217 rect
.width
= 2*BORDER_THICKNESS
;
2218 rect
.x
= rectOrig
.x
+ (rectOrig
.width
- rect
.width
) / 2;
2222 rect
.Deflate(0, SLIDER_MARGIN
);
2228 void wxWin32Renderer::DrawSliderShaft(wxDC
& dc
,
2229 const wxRect
& rectOrig
,
2230 wxOrientation orient
,
2234 if ( flags
& wxCONTROL_FOCUSED
)
2236 DrawFocusRect(dc
, rectOrig
);
2239 wxRect rect
= GetSliderShaftRect(rectOrig
, orient
);
2244 DrawSunkenBorder(dc
, &rect
);
2247 void wxWin32Renderer::DrawSliderThumb(wxDC
& dc
,
2249 wxOrientation orient
,
2253 we are drawing a shape of this form
2258 H DB where H is hightlight colour
2271 The interior of this shape is filled with the hatched brush if the thumb
2275 DrawBackground(dc
, wxNullColour
, rect
, flags
);
2277 bool transpose
= orient
== wxVERTICAL
;
2279 wxCoord x
, y
, x2
, y2
;
2284 x2
= rect
.GetBottom();
2285 y2
= rect
.GetRight();
2291 x2
= rect
.GetRight();
2292 y2
= rect
.GetBottom();
2295 // the size of the pointed part of the thumb
2296 wxCoord sizeArrow
= (transpose
? rect
.height
: rect
.width
) / 2;
2298 wxCoord x3
= x
+ sizeArrow
,
2299 y3
= y2
- sizeArrow
;
2301 dc
.SetPen(m_penHighlight
);
2302 DrawLine(dc
, x
, y
, x2
, y
, transpose
);
2303 DrawLine(dc
, x
, y
+ 1, x
, y2
- sizeArrow
, transpose
);
2304 DrawLine(dc
, x
, y3
, x3
, y2
, transpose
);
2306 dc
.SetPen(m_penBlack
);
2307 DrawLine(dc
, x3
, y2
, x2
, y3
, transpose
);
2308 DrawLine(dc
, x2
, y3
, x2
, y
- 1, transpose
);
2310 dc
.SetPen(m_penDarkGrey
);
2311 DrawLine(dc
, x3
, y2
- 1, x2
- 1, y3
, transpose
);
2312 DrawLine(dc
, x2
- 1, y3
, x2
- 1, y
, transpose
);
2314 if ( flags
& wxCONTROL_PRESSED
)
2316 // TODO: MSW fills the entire area inside, not just the rect
2317 wxRect rectInt
= rect
;
2319 rectInt
.SetRight(y3
);
2321 rectInt
.SetBottom(y3
);
2324 static const char *stipple_xpm
[] = {
2325 /* columns rows colors chars-per-pixel */
2333 dc
.SetBrush(wxBrush(stipple_xpm
));
2335 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, SHADOW_HIGHLIGHT
));
2336 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, CONTROL
));
2337 dc
.SetPen(*wxTRANSPARENT_PEN
);
2338 dc
.DrawRectangle(rectInt
);
2342 void wxWin32Renderer::DrawSliderTicks(wxDC
& dc
,
2344 const wxSize
& sizeThumb
,
2345 wxOrientation orient
,
2357 // the variable names correspond to horizontal case, but they can be used
2358 // for both orientations
2359 wxCoord x1
, x2
, y1
, y2
, len
, widthThumb
;
2360 if ( orient
== wxHORIZONTAL
)
2362 x1
= rect
.GetLeft();
2363 x2
= rect
.GetRight();
2365 // draw from bottom to top to leave one pixel space between the ticks
2366 // and the slider as Windows do
2367 y1
= rect
.GetBottom();
2372 widthThumb
= sizeThumb
.x
;
2377 x2
= rect
.GetBottom();
2379 y1
= rect
.GetRight();
2380 y2
= rect
.GetLeft();
2384 widthThumb
= sizeThumb
.y
;
2387 // the first tick should be positioned in such way that a thumb drawn in
2388 // the first position points down directly to it
2389 x1
+= widthThumb
/ 2;
2390 x2
-= widthThumb
/ 2;
2392 // this also means that we have slightly less space for the ticks in
2393 // between the first and the last
2396 dc
.SetPen(m_penBlack
);
2398 int range
= end
- start
;
2399 for ( int n
= 0; n
< range
; n
+= step
)
2401 wxCoord x
= x1
+ (len
*n
) / range
;
2403 DrawLine(dc
, x
, y1
, x
, y2
, orient
== wxVERTICAL
);
2406 // always draw the line at the end position
2407 DrawLine(dc
, x2
, y1
, x2
, y2
, orient
== wxVERTICAL
);
2410 // ----------------------------------------------------------------------------
2412 // ----------------------------------------------------------------------------
2416 // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2417 class WXDLLEXPORT wxWin32MenuGeometryInfo
: public wxMenuGeometryInfo
2420 virtual wxSize
GetSize() const { return m_size
; }
2422 wxCoord
GetLabelOffset() const { return m_ofsLabel
; }
2423 wxCoord
GetAccelOffset() const { return m_ofsAccel
; }
2425 wxCoord
GetItemHeight() const { return m_heightItem
; }
2428 // the total size of the menu
2431 // the offset of the start of the menu item label
2434 // the offset of the start of the accel label
2437 // the height of a normal (not separator) item
2438 wxCoord m_heightItem
;
2440 friend wxMenuGeometryInfo
*wxWin32Renderer::
2441 GetMenuGeometry(wxWindow
*, const wxMenu
&) const;
2444 #endif // wxUSE_WAVE
2446 // FIXME: all constants are hardcoded but shouldn't be
2447 static const wxCoord MENU_LEFT_MARGIN
= 9;
2448 static const wxCoord MENU_RIGHT_MARGIN
= 18;
2449 static const wxCoord MENU_VERT_MARGIN
= 3;
2451 // the margin around bitmap/check marks (on each side)
2452 static const wxCoord MENU_BMP_MARGIN
= 2;
2454 // the margin between the labels and accel strings
2455 static const wxCoord MENU_ACCEL_MARGIN
= 8;
2457 // the separator height in pixels: in fact, strangely enough, the real height
2458 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2460 static const wxCoord MENU_SEPARATOR_HEIGHT
= 3;
2462 // the size of the standard checkmark bitmap
2463 static const wxCoord MENU_CHECK_SIZE
= 9;
2465 // we can't implement these methods without wxMenuGeometryInfo implementation
2466 // which we don't have if !wxUSE_MENUS
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 #else // !wxUSE_MENUS
2682 void wxWin32Renderer::DrawMenuBarItem(wxDC
& WXUNUSED(dc
),
2683 const wxRect
& WXUNUSED(rectOrig
),
2684 const wxString
& WXUNUSED(label
),
2685 int WXUNUSED(flags
),
2686 int WXUNUSED(indexAccel
))
2690 void wxWin32Renderer::DrawMenuItem(wxDC
& WXUNUSED(dc
),
2691 wxCoord
WXUNUSED(y
),
2692 const wxMenuGeometryInfo
& WXUNUSED(gi
),
2693 const wxString
& WXUNUSED(label
),
2694 const wxString
& WXUNUSED(accel
),
2695 const wxBitmap
& WXUNUSED(bitmap
),
2696 int WXUNUSED(flags
),
2697 int WXUNUSED(indexAccel
))
2701 void wxWin32Renderer::DrawMenuSeparator(wxDC
& WXUNUSED(dc
),
2702 wxCoord
WXUNUSED(y
),
2703 const wxMenuGeometryInfo
& WXUNUSED(gi
))
2707 wxSize
wxWin32Renderer::GetMenuBarItemSize(const wxSize
& size
) const
2712 wxMenuGeometryInfo
*
2713 wxWin32Renderer::GetMenuGeometry(wxWindow
*WXUNUSED(win
),
2714 const wxMenu
& WXUNUSED(menu
)) const
2719 #endif // wxUSE_MENUS/!wxUSE_MENUS
2721 // ----------------------------------------------------------------------------
2723 // ----------------------------------------------------------------------------
2725 void wxWin32Renderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
2726 wxBitmap
*bmpPressed
,
2727 wxBitmap
*bmpDisabled
)
2729 static const wxCoord widthCombo
= 16;
2730 static const wxCoord heightCombo
= 17;
2736 bmpNormal
->Create(widthCombo
, heightCombo
);
2737 dcMem
.SelectObject(*bmpNormal
);
2738 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2739 Arrow_Down
, Arrow_Normal
);
2744 bmpPressed
->Create(widthCombo
, heightCombo
);
2745 dcMem
.SelectObject(*bmpPressed
);
2746 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2747 Arrow_Down
, Arrow_Pressed
);
2752 bmpDisabled
->Create(widthCombo
, heightCombo
);
2753 dcMem
.SelectObject(*bmpDisabled
);
2754 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2755 Arrow_Down
, Arrow_Disabled
);
2759 // ----------------------------------------------------------------------------
2761 // ----------------------------------------------------------------------------
2763 void wxWin32Renderer::DoDrawBackground(wxDC
& dc
,
2764 const wxColour
& col
,
2767 wxBrush
brush(col
, wxSOLID
);
2769 dc
.SetPen(*wxTRANSPARENT_PEN
);
2770 dc
.DrawRectangle(rect
);
2773 void wxWin32Renderer::DrawBackground(wxDC
& dc
,
2774 const wxColour
& col
,
2778 // just fill it with the given or default bg colour
2779 wxColour colBg
= col
.Ok() ? col
: wxSCHEME_COLOUR(m_scheme
, CONTROL
);
2780 DoDrawBackground(dc
, colBg
, rect
);
2783 // ----------------------------------------------------------------------------
2785 // ----------------------------------------------------------------------------
2787 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2792 // get the bitmap for this arrow
2793 wxArrowDirection arrowDir
;
2796 case wxLEFT
: arrowDir
= Arrow_Left
; break;
2797 case wxRIGHT
: arrowDir
= Arrow_Right
; break;
2798 case wxUP
: arrowDir
= Arrow_Up
; break;
2799 case wxDOWN
: arrowDir
= Arrow_Down
; break;
2802 wxFAIL_MSG(_T("unknown arrow direction"));
2806 wxArrowStyle arrowStyle
;
2807 if ( flags
& wxCONTROL_PRESSED
)
2809 // can't be pressed and disabled
2810 arrowStyle
= Arrow_Pressed
;
2814 arrowStyle
= flags
& wxCONTROL_DISABLED
? Arrow_Disabled
: Arrow_Normal
;
2817 DrawArrowButton(dc
, rect
, arrowDir
, arrowStyle
);
2820 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2822 wxArrowDirection arrowDir
,
2823 wxArrowStyle arrowStyle
)
2825 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
2827 // under Windows the arrows always have the same size so just centre it in
2828 // the provided rectangle
2829 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
2830 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
2832 // Windows does it like this...
2833 if ( arrowDir
== Arrow_Left
)
2837 dc
.DrawBitmap(bmp
, x
, y
, TRUE
/* use mask */);
2840 void wxWin32Renderer::DrawArrowButton(wxDC
& dc
,
2841 const wxRect
& rectAll
,
2842 wxArrowDirection arrowDir
,
2843 wxArrowStyle arrowStyle
)
2845 wxRect rect
= rectAll
;
2846 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2847 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
2848 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
2851 void wxWin32Renderer::DrawScrollbarThumb(wxDC
& dc
,
2852 wxOrientation orient
,
2856 // we don't use the flags, the thumb never changes appearance
2857 wxRect rectThumb
= rect
;
2858 DrawArrowBorder(dc
, &rectThumb
);
2859 DrawBackground(dc
, wxNullColour
, rectThumb
);
2862 void wxWin32Renderer::DrawScrollbarShaft(wxDC
& dc
,
2863 wxOrientation orient
,
2864 const wxRect
& rectBar
,
2867 wxColourScheme::StdColour col
= flags
& wxCONTROL_PRESSED
2868 ? wxColourScheme::SCROLLBAR_PRESSED
2869 : wxColourScheme::SCROLLBAR
;
2870 DoDrawBackground(dc
, m_scheme
->Get(col
), rectBar
);
2873 void wxWin32Renderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
2875 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2878 wxRect
wxWin32Renderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
2879 wxScrollBar::Element elem
,
2882 return StandardGetScrollbarRect(scrollbar
, elem
,
2883 thumbPos
, m_sizeScrollbarArrow
);
2886 wxCoord
wxWin32Renderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
2888 return StandardScrollBarSize(scrollbar
, m_sizeScrollbarArrow
);
2891 wxHitTest
wxWin32Renderer::HitTestScrollbar(const wxScrollBar
*scrollbar
,
2892 const wxPoint
& pt
) const
2894 return StandardHitTestScrollbar(scrollbar
, pt
, m_sizeScrollbarArrow
);
2897 wxCoord
wxWin32Renderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
2900 return StandardScrollbarToPixel(scrollbar
, thumbPos
, m_sizeScrollbarArrow
);
2903 int wxWin32Renderer::PixelToScrollbar(const wxScrollBar
*scrollbar
,
2906 return StandardPixelToScrollbar(scrollbar
, coord
, m_sizeScrollbarArrow
);
2909 // ----------------------------------------------------------------------------
2910 // text control geometry
2911 // ----------------------------------------------------------------------------
2913 static inline int GetTextBorderWidth()
2918 wxRect
wxWin32Renderer::GetTextTotalArea(const wxTextCtrl
*text
,
2921 wxRect rectTotal
= rect
;
2923 wxCoord widthBorder
= GetTextBorderWidth();
2924 rectTotal
.Inflate(widthBorder
);
2926 // this is what Windows does
2932 wxRect
wxWin32Renderer::GetTextClientArea(const wxTextCtrl
*text
,
2934 wxCoord
*extraSpaceBeyond
)
2936 wxRect rectText
= rect
;
2938 // undo GetTextTotalArea()
2939 if ( rectText
.height
> 0 )
2942 wxCoord widthBorder
= GetTextBorderWidth();
2943 rectText
.Inflate(-widthBorder
);
2945 if ( extraSpaceBeyond
)
2946 *extraSpaceBeyond
= 0;
2951 // ----------------------------------------------------------------------------
2953 // ----------------------------------------------------------------------------
2955 void wxWin32Renderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
2958 if ( wxDynamicCast(window
, wxScrollBar
) )
2960 // we only set the width of vert scrollbars and height of the
2962 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
2963 size
->y
= m_sizeScrollbarArrow
.y
;
2965 size
->x
= m_sizeScrollbarArrow
.x
;
2967 // skip border width adjustments, they don't make sense for us
2970 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
2973 if ( wxDynamicCast(window
, wxButton
) )
2976 size
->x
+= 3*window
->GetCharWidth();
2977 #if 0 // do allow creating small buttons if wanted
2978 wxSize sizeDef
= wxButton::GetDefaultSize();
2979 if ( size
->x
< sizeDef
.x
)
2980 size
->x
= sizeDef
.x
;
2983 wxCoord heightBtn
= (11*(window
->GetCharHeight() + 8))/10;
2984 if ( size
->y
< heightBtn
- 8 )
2985 size
->y
= heightBtn
;
2989 // no border width adjustments for buttons
2992 #endif // wxUSE_BUTTON
2994 // take into account the border width
2995 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
2996 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
2997 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
3000 // ============================================================================
3002 // ============================================================================
3004 // ----------------------------------------------------------------------------
3005 // wxWin32InputHandler
3006 // ----------------------------------------------------------------------------
3008 wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer
*renderer
)
3010 m_renderer
= renderer
;
3013 bool wxWin32InputHandler::HandleKey(wxControl
*control
,
3014 const wxKeyEvent
& event
,
3020 bool wxWin32InputHandler::HandleMouse(wxControl
*control
,
3021 const wxMouseEvent
& event
)
3026 // ----------------------------------------------------------------------------
3027 // wxWin32ScrollBarInputHandler
3028 // ----------------------------------------------------------------------------
3030 wxWin32ScrollBarInputHandler::
3031 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
3032 wxInputHandler
*handler
)
3033 : wxStdScrollBarInputHandler(renderer
, handler
)
3035 m_scrollPaused
= FALSE
;
3039 bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar
*scrollbar
,
3040 const wxControlAction
& action
)
3042 // stop if went beyond the position of the original click (this can only
3043 // happen when we scroll by pages)
3045 if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
3047 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3048 != wxHT_SCROLLBAR_BAR_2
;
3050 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
3052 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3053 != wxHT_SCROLLBAR_BAR_1
;
3058 StopScrolling(scrollbar
);
3060 scrollbar
->Refresh();
3065 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar
, action
);
3068 bool wxWin32ScrollBarInputHandler::HandleMouse(wxControl
*control
,
3069 const wxMouseEvent
& event
)
3071 // remember the current state
3072 bool wasDraggingThumb
= m_htLast
== wxHT_SCROLLBAR_THUMB
;
3074 // do process the message
3075 bool rc
= wxStdScrollBarInputHandler::HandleMouse(control
, event
);
3077 // analyse the changes
3078 if ( !wasDraggingThumb
&& (m_htLast
== wxHT_SCROLLBAR_THUMB
) )
3080 // we just started dragging the thumb, remember its initial position to
3081 // be able to restore it if the drag is cancelled later
3082 m_eventStartDrag
= event
;
3088 bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl
*control
,
3089 const wxMouseEvent
& event
)
3091 // we don't highlight scrollbar elements, so there is no need to process
3092 // mouse move events normally - only do it while mouse is captured (i.e.
3093 // when we're dragging the thumb or pressing on something)
3094 if ( !m_winCapture
)
3097 if ( event
.Entering() )
3099 // we're not interested in this at all
3103 wxScrollBar
*scrollbar
= wxStaticCast(control
, wxScrollBar
);
3105 if ( m_scrollPaused
)
3107 // check if the mouse returned to its original location
3109 if ( event
.Leaving() )
3115 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3116 if ( ht
== m_htLast
)
3118 // yes it did, resume scrolling
3119 m_scrollPaused
= FALSE
;
3120 if ( m_timerScroll
)
3122 // we were scrolling by line/page, restart timer
3123 m_timerScroll
->Start(m_interval
);
3125 Press(scrollbar
, TRUE
);
3127 else // we were dragging the thumb
3129 // restore its last location
3130 HandleThumbMove(scrollbar
, m_eventLastDrag
);
3136 else // normal case, scrolling hasn't been paused
3138 // if we're scrolling the scrollbar because the arrow or the shaft was
3139 // pressed, check that the mouse stays on the same scrollbar element
3141 if ( event
.Moving() )
3143 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3145 else // event.Leaving()
3150 // if we're dragging the thumb and the mouse stays in the scrollbar, it
3151 // is still ok - we only want to catch the case when the mouse leaves
3152 // the scrollbar here
3153 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
&& ht
!= wxHT_NOWHERE
)
3155 ht
= wxHT_SCROLLBAR_THUMB
;
3158 if ( ht
!= m_htLast
)
3160 // what were we doing? 2 possibilities: either an arrow/shaft was
3161 // pressed in which case we have a timer and so we just stop it or
3162 // we were dragging the thumb
3163 if ( m_timerScroll
)
3166 m_interval
= m_timerScroll
->GetInterval();
3167 m_timerScroll
->Stop();
3168 m_scrollPaused
= TRUE
;
3170 // unpress the arrow
3171 Press(scrollbar
, FALSE
);
3173 else // we were dragging the thumb
3175 // remember the current thumb position to be able to restore it
3176 // if the mouse returns to it later
3177 m_eventLastDrag
= event
;
3179 // and restore the original position (before dragging) of the
3181 HandleThumbMove(scrollbar
, m_eventStartDrag
);
3188 return wxStdScrollBarInputHandler::HandleMouseMove(control
, event
);
3191 // ----------------------------------------------------------------------------
3192 // wxWin32CheckboxInputHandler
3193 // ----------------------------------------------------------------------------
3195 bool wxWin32CheckboxInputHandler::HandleKey(wxControl
*control
,
3196 const wxKeyEvent
& event
,
3201 wxControlAction action
;
3202 int keycode
= event
.GetKeyCode();
3206 action
= wxACTION_CHECKBOX_TOGGLE
;
3210 case WXK_NUMPAD_SUBTRACT
:
3211 action
= wxACTION_CHECKBOX_CHECK
;
3215 case WXK_NUMPAD_ADD
:
3216 case WXK_NUMPAD_EQUAL
:
3217 action
= wxACTION_CHECKBOX_CLEAR
;
3223 control
->PerformAction(action
);
3232 // ----------------------------------------------------------------------------
3233 // wxWin32TextCtrlInputHandler
3234 // ----------------------------------------------------------------------------
3236 bool wxWin32TextCtrlInputHandler::HandleKey(wxControl
*control
,
3237 const wxKeyEvent
& event
,
3240 // handle only MSW-specific text bindings here, the others are handled in
3244 int keycode
= event
.GetKeyCode();
3246 wxControlAction action
;
3247 if ( keycode
== WXK_DELETE
&& event
.ShiftDown() )
3249 action
= wxACTION_TEXT_CUT
;
3251 else if ( keycode
== WXK_INSERT
)
3253 if ( event
.ControlDown() )
3254 action
= wxACTION_TEXT_COPY
;
3255 else if ( event
.ShiftDown() )
3256 action
= wxACTION_TEXT_PASTE
;
3259 if ( action
!= wxACTION_NONE
)
3261 control
->PerformAction(action
);
3267 return wxStdTextCtrlInputHandler::HandleKey(control
, event
, pressed
);