1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: univ/themes/win32.cpp
3 // Purpose: wxUniversal theme implementing Win32-like LNF
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
31 #include "wx/window.h"
33 #include "wx/dcmemory.h"
35 #include "wx/button.h"
36 #include "wx/listbox.h"
37 #include "wx/checklst.h"
38 #include "wx/combobox.h"
39 #include "wx/scrolbar.h"
40 #include "wx/slider.h"
41 #include "wx/textctrl.h"
44 #include "wx/notebook.h"
45 #include "wx/spinbutt.h"
46 #include "wx/settings.h"
49 #include "wx/univ/scrtimer.h"
51 #include "wx/univ/renderer.h"
52 #include "wx/univ/inphand.h"
53 #include "wx/univ/colschem.h"
54 #include "wx/univ/theme.h"
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 static const int BORDER_THICKNESS
= 2;
62 // the offset between the label and focus rect around it
63 static const int FOCUS_RECT_OFFSET_X
= 1;
64 static const int FOCUS_RECT_OFFSET_Y
= 1;
76 IndicatorState_Normal
,
77 IndicatorState_Pressed
, // this one is for check/radioboxes
78 IndicatorState_Selected
= IndicatorState_Pressed
, // for menus
79 IndicatorState_Disabled
,
80 IndicatorState_SelectedDisabled
, // only for the menus
86 IndicatorStatus_Checked
,
87 IndicatorStatus_Unchecked
,
91 // 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
,
240 virtual void DrawMenuBarItem(wxDC
& dc
,
242 const wxString
& label
,
244 int indexAccel
= -1);
245 virtual void DrawMenuItem(wxDC
& dc
,
247 const wxMenuGeometryInfo
& geometryInfo
,
248 const wxString
& label
,
249 const wxString
& accel
,
250 const wxBitmap
& bitmap
= wxNullBitmap
,
252 int indexAccel
= -1);
253 virtual void DrawMenuSeparator(wxDC
& dc
,
255 const wxMenuGeometryInfo
& geomInfo
);
257 virtual void GetComboBitmaps(wxBitmap
*bmpNormal
,
259 wxBitmap
*bmpPressed
,
260 wxBitmap
*bmpDisabled
);
262 virtual void AdjustSize(wxSize
*size
, const wxWindow
*window
);
263 virtual wxRect
GetBorderDimensions(wxBorder border
) const;
264 virtual bool AreScrollbarsInsideBorder() const;
266 virtual wxSize
GetScrollbarArrowSize() const
267 { return m_sizeScrollbarArrow
; }
268 virtual wxRect
GetScrollbarRect(const wxScrollBar
*scrollbar
,
269 wxScrollBar::Element elem
,
270 int thumbPos
= -1) const;
271 virtual wxCoord
GetScrollbarSize(const wxScrollBar
*scrollbar
);
272 virtual wxHitTest
HitTestScrollbar(const wxScrollBar
*scrollbar
,
273 const wxPoint
& pt
) const;
274 virtual wxCoord
ScrollbarToPixel(const wxScrollBar
*scrollbar
,
276 virtual int PixelToScrollbar(const wxScrollBar
*scrollbar
, wxCoord coord
);
277 virtual wxCoord
GetListboxItemHeight(wxCoord fontHeight
)
278 { return fontHeight
+ 2; }
279 virtual wxSize
GetCheckBitmapSize() const
280 { return wxSize(13, 13); }
281 virtual wxSize
GetRadioBitmapSize() const
282 { return wxSize(12, 12); }
283 virtual wxCoord
GetCheckItemMargin() const
286 virtual wxRect
GetTextTotalArea(const wxTextCtrl
*text
,
288 virtual wxRect
GetTextClientArea(const wxTextCtrl
*text
,
290 wxCoord
*extraSpaceBeyond
);
292 virtual wxSize
GetTabIndent() const { return wxSize(2, 2); }
293 virtual wxSize
GetTabPadding() const { return wxSize(6, 5); }
295 virtual wxCoord
GetSliderDim() const { return 20; }
296 virtual wxCoord
GetSliderTickLen() const { return 4; }
297 virtual wxRect
GetSliderShaftRect(const wxRect
& rect
,
298 wxOrientation orient
) const;
299 virtual wxSize
GetSliderThumbSize(const wxRect
& rect
,
300 wxOrientation orient
) const;
301 virtual wxSize
GetProgressBarStep() const { return wxSize(16, 32); }
304 virtual wxSize
GetMenuBarItemSize(const wxSize
& sizeText
) const;
305 virtual wxMenuGeometryInfo
*GetMenuGeometry(wxWindow
*win
,
306 const wxMenu
& menu
) const;
309 // helper of DrawLabel() and DrawCheckOrRadioButton()
310 void DoDrawLabel(wxDC
& dc
,
311 const wxString
& label
,
314 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
316 wxRect
*rectBounds
= NULL
,
317 const wxPoint
& focusOffset
318 = wxPoint(FOCUS_RECT_OFFSET_X
, FOCUS_RECT_OFFSET_Y
));
320 // common part of DrawLabel() and DrawItem()
321 void DrawFocusRect(wxDC
& dc
, const wxRect
& rect
);
323 // DrawLabel() and DrawButtonLabel() helper
324 void DrawLabelShadow(wxDC
& dc
,
325 const wxString
& label
,
330 // DrawButtonBorder() helper
331 void DoDrawBackground(wxDC
& dc
,
335 // DrawBorder() helpers: all of them shift and clip the DC after drawing
338 // just draw a rectangle with the given pen
339 void DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
341 // draw the lower left part of rectangle
342 void DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
344 // draw the rectange using the first brush for the left and top sides and
345 // the second one for the bottom and right ones
346 void DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
347 const wxPen
& pen1
, const wxPen
& pen2
);
349 // draw the normal 3D border
350 void DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
);
352 // draw the sunken 3D border
353 void DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
);
355 // draw the border used for scrollbar arrows
356 void DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
= FALSE
);
358 // public DrawArrow()s helper
359 void DrawArrow(wxDC
& dc
, const wxRect
& rect
,
360 wxArrowDirection arrowDir
, wxArrowStyle arrowStyle
);
362 // DrawArrowButton is used by DrawScrollbar and DrawComboButton
363 void DrawArrowButton(wxDC
& dc
, const wxRect
& rect
,
364 wxArrowDirection arrowDir
,
365 wxArrowStyle arrowStyle
);
367 // DrawCheckButton/DrawRadioButton helper
368 void DrawCheckOrRadioButton(wxDC
& dc
,
369 const wxString
& label
,
370 const wxBitmap
& bitmap
,
375 wxCoord focusOffsetY
);
377 // draw a normal or transposed line (useful for using the same code fo both
378 // horizontal and vertical widgets)
379 void DrawLine(wxDC
& dc
,
380 wxCoord x1
, wxCoord y1
,
381 wxCoord x2
, wxCoord y2
,
382 bool transpose
= FALSE
)
385 dc
.DrawLine(y1
, x1
, y2
, x2
);
387 dc
.DrawLine(x1
, y1
, x2
, y2
);
390 // get the standard check/radio button bitmap
391 wxBitmap
GetIndicator(IndicatorType indType
, int flags
);
392 wxBitmap
GetCheckBitmap(int flags
)
393 { return GetIndicator(IndicatorType_Check
, flags
); }
394 wxBitmap
GetRadioBitmap(int flags
)
395 { return GetIndicator(IndicatorType_Radio
, flags
); }
398 const wxColourScheme
*m_scheme
;
400 // the sizing parameters (TODO make them changeable)
401 wxSize m_sizeScrollbarArrow
;
403 // GDI objects we use for drawing
404 wxColour m_colDarkGrey
,
412 // first row is for the normal state, second - for the disabled
413 wxBitmap m_bmpArrows
[Arrow_StateMax
][Arrow_Max
];
416 // ----------------------------------------------------------------------------
417 // wxWin32InputHandler and derived classes: process the keyboard and mouse
418 // messages according to Windows standards
419 // ----------------------------------------------------------------------------
421 class wxWin32InputHandler
: public wxInputHandler
424 wxWin32InputHandler(wxWin32Renderer
*renderer
);
426 virtual bool HandleKey(wxControl
*control
,
427 const wxKeyEvent
& event
,
429 virtual bool HandleMouse(wxControl
*control
,
430 const wxMouseEvent
& event
);
433 wxWin32Renderer
*m_renderer
;
436 class wxWin32ScrollBarInputHandler
: public wxStdScrollBarInputHandler
439 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
440 wxInputHandler
*handler
);
442 virtual bool HandleMouse(wxControl
*control
, const wxMouseEvent
& event
);
443 virtual bool HandleMouseMove(wxControl
*control
, const wxMouseEvent
& event
);
445 virtual bool OnScrollTimer(wxScrollBar
*scrollbar
,
446 const wxControlAction
& action
);
449 virtual bool IsAllowedButton(int button
) { return button
== 1; }
451 virtual void Highlight(wxScrollBar
*scrollbar
, bool doIt
)
453 // we don't highlight anything
456 // the first and last event which caused the thumb to move
457 wxMouseEvent m_eventStartDrag
,
460 // have we paused the scrolling because the mouse moved?
463 // we remember the interval of the timer to be able to restart it
467 class wxWin32CheckboxInputHandler
: public wxStdCheckboxInputHandler
470 wxWin32CheckboxInputHandler(wxInputHandler
*handler
)
471 : wxStdCheckboxInputHandler(handler
) { }
473 virtual bool HandleKey(wxControl
*control
,
474 const wxKeyEvent
& event
,
478 class wxWin32TextCtrlInputHandler
: public wxStdTextCtrlInputHandler
481 wxWin32TextCtrlInputHandler(wxInputHandler
*handler
)
482 : wxStdTextCtrlInputHandler(handler
) { }
484 virtual bool HandleKey(wxControl
*control
,
485 const wxKeyEvent
& event
,
489 // ----------------------------------------------------------------------------
490 // wxWin32ColourScheme: uses (default) Win32 colours
491 // ----------------------------------------------------------------------------
493 class wxWin32ColourScheme
: public wxColourScheme
496 virtual wxColour
Get(StdColour col
) const;
497 virtual wxColour
GetBackground(wxWindow
*win
) const;
500 // ----------------------------------------------------------------------------
502 // ----------------------------------------------------------------------------
504 WX_DEFINE_ARRAY(wxInputHandler
*, wxArrayHandlers
);
506 class wxWin32Theme
: public wxTheme
510 virtual ~wxWin32Theme();
512 virtual wxRenderer
*GetRenderer() { return m_renderer
; }
513 virtual wxInputHandler
*GetInputHandler(const wxString
& control
);
514 virtual wxColourScheme
*GetColourScheme();
517 // get the default input handler
518 wxInputHandler
*GetDefaultInputHandler();
520 wxWin32Renderer
*m_renderer
;
522 // the names of the already created handlers and the handlers themselves
523 // (these arrays are synchronized)
524 wxSortedArrayString m_handlerNames
;
525 wxArrayHandlers m_handlers
;
527 wxWin32InputHandler
*m_handlerDefault
;
529 wxWin32ColourScheme
*m_scheme
;
531 WX_DECLARE_THEME(win32
)
534 // ----------------------------------------------------------------------------
536 // ----------------------------------------------------------------------------
540 static const char *checked_menu_xpm
[] = {
541 /* columns rows colors chars-per-pixel */
557 static const char *selected_checked_menu_xpm
[] = {
558 /* columns rows colors chars-per-pixel */
574 static const char *disabled_checked_menu_xpm
[] = {
575 /* columns rows colors chars-per-pixel */
592 static const char *selected_disabled_checked_menu_xpm
[] = {
593 /* columns rows colors chars-per-pixel */
609 // checkbox and radiobox bitmaps below
611 static const char *checked_xpm
[] = {
612 /* columns rows colors chars-per-pixel */
635 static const char *pressed_checked_xpm
[] = {
636 /* columns rows colors chars-per-pixel */
658 static const char *pressed_disabled_checked_xpm
[] = {
659 /* columns rows colors chars-per-pixel */
681 static const char *checked_item_xpm
[] = {
682 /* columns rows colors chars-per-pixel */
703 static const char *unchecked_xpm
[] = {
704 /* columns rows colors chars-per-pixel */
727 static const char *pressed_unchecked_xpm
[] = {
728 /* columns rows colors chars-per-pixel */
750 static const char *unchecked_item_xpm
[] = {
751 /* columns rows colors chars-per-pixel */
771 static const char *checked_radio_xpm
[] = {
772 /* columns rows colors chars-per-pixel */
795 static const char *pressed_checked_radio_xpm
[] = {
796 /* columns rows colors chars-per-pixel */
819 static const char *pressed_disabled_checked_radio_xpm
[] = {
820 /* columns rows colors chars-per-pixel */
843 static const char *unchecked_radio_xpm
[] = {
844 /* columns rows colors chars-per-pixel */
867 static const char *pressed_unchecked_radio_xpm
[] = {
868 /* columns rows colors chars-per-pixel */
892 bmpIndicators
[IndicatorType_Max
][IndicatorState_Max
][IndicatorStatus_Max
] =
897 { checked_xpm
, unchecked_xpm
},
900 { pressed_checked_xpm
, pressed_unchecked_xpm
},
903 { pressed_disabled_checked_xpm
, pressed_unchecked_xpm
},
909 { checked_radio_xpm
, unchecked_radio_xpm
},
912 { pressed_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
915 { pressed_disabled_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
921 { checked_menu_xpm
, NULL
},
924 { selected_checked_menu_xpm
, NULL
},
927 { disabled_checked_menu_xpm
, NULL
},
929 // disabled selected state
930 { selected_disabled_checked_menu_xpm
, NULL
},
934 // ============================================================================
936 // ============================================================================
938 WX_IMPLEMENT_THEME(wxWin32Theme
, win32
, wxTRANSLATE("Win32 theme"));
940 // ----------------------------------------------------------------------------
942 // ----------------------------------------------------------------------------
944 wxWin32Theme::wxWin32Theme()
946 m_scheme
= new wxWin32ColourScheme
;
947 m_renderer
= new wxWin32Renderer(m_scheme
);
948 m_handlerDefault
= NULL
;
951 wxWin32Theme::~wxWin32Theme()
953 size_t count
= m_handlers
.GetCount();
954 for ( size_t n
= 0; n
< count
; n
++ )
956 if ( m_handlers
[n
] != m_handlerDefault
)
957 delete m_handlers
[n
];
960 delete m_handlerDefault
;
966 wxInputHandler
*wxWin32Theme::GetDefaultInputHandler()
968 if ( !m_handlerDefault
)
970 m_handlerDefault
= new wxWin32InputHandler(m_renderer
);
973 return m_handlerDefault
;
976 wxInputHandler
*wxWin32Theme::GetInputHandler(const wxString
& control
)
978 wxInputHandler
*handler
;
979 int n
= m_handlerNames
.Index(control
);
980 if ( n
== wxNOT_FOUND
)
982 // create a new handler
983 if ( control
== wxINP_HANDLER_SCROLLBAR
)
984 handler
= new wxWin32ScrollBarInputHandler(m_renderer
,
985 GetDefaultInputHandler());
987 else if ( control
== wxINP_HANDLER_BUTTON
)
988 handler
= new wxStdButtonInputHandler(GetDefaultInputHandler());
989 #endif // wxUSE_BUTTON
991 else if ( control
== wxINP_HANDLER_CHECKBOX
)
992 handler
= new wxWin32CheckboxInputHandler(GetDefaultInputHandler());
993 #endif // wxUSE_CHECKBOX
995 else if ( control
== wxINP_HANDLER_COMBOBOX
)
996 handler
= new wxStdComboBoxInputHandler(GetDefaultInputHandler());
997 #endif // wxUSE_COMBOBOX
999 else if ( control
== wxINP_HANDLER_LISTBOX
)
1000 handler
= new wxStdListboxInputHandler(GetDefaultInputHandler());
1001 #endif // wxUSE_LISTBOX
1002 #if wxUSE_CHECKLISTBOX
1003 else if ( control
== wxINP_HANDLER_CHECKLISTBOX
)
1004 handler
= new wxStdCheckListboxInputHandler(GetDefaultInputHandler());
1005 #endif // wxUSE_CHECKLISTBOX
1007 else if ( control
== wxINP_HANDLER_TEXTCTRL
)
1008 handler
= new wxWin32TextCtrlInputHandler(GetDefaultInputHandler());
1009 #endif // wxUSE_TEXTCTRL
1011 else if ( control
== wxINP_HANDLER_SLIDER
)
1012 handler
= new wxStdSliderButtonInputHandler(GetDefaultInputHandler());
1013 #endif // wxUSE_SLIDER
1015 else if ( control
== wxINP_HANDLER_SPINBTN
)
1016 handler
= new wxStdSpinButtonInputHandler(GetDefaultInputHandler());
1017 #endif // wxUSE_SPINBTN
1019 else if ( control
== wxINP_HANDLER_NOTEBOOK
)
1020 handler
= new wxStdNotebookInputHandler(GetDefaultInputHandler());
1021 #endif // wxUSE_NOTEBOOK
1023 handler
= GetDefaultInputHandler();
1025 n
= m_handlerNames
.Add(control
);
1026 m_handlers
.Insert(handler
, n
);
1028 else // we already have it
1030 handler
= m_handlers
[n
];
1036 wxColourScheme
*wxWin32Theme::GetColourScheme()
1041 // ============================================================================
1042 // wxWin32ColourScheme
1043 // ============================================================================
1045 wxColour
wxWin32ColourScheme::GetBackground(wxWindow
*win
) const
1048 if ( win
->UseBgCol() )
1050 // use the user specified colour
1051 col
= win
->GetBackgroundColour();
1054 if ( win
->IsContainerWindow() )
1056 wxTextCtrl
*text
= wxDynamicCast(win
, wxTextCtrl
);
1059 if ( !text
->IsEnabled() ) // not IsEditable()
1061 //else: execute code below
1066 // doesn't depend on the state
1072 int flags
= win
->GetStateFlags();
1074 // the colour set by the user should be used for the normal state
1075 // and for the states for which we don't have any specific colours
1076 if ( !col
.Ok() || (flags
!= 0) )
1078 if ( wxDynamicCast(win
, wxScrollBar
) )
1079 col
= Get(flags
& wxCONTROL_PRESSED
? SCROLLBAR_PRESSED
1089 wxColour
wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col
) const
1093 // use the system colours under Windows
1094 #if defined(__WXMSW__)
1095 case WINDOW
: return wxColour(GetSysColor(COLOR_WINDOW
));
1097 case CONTROL_PRESSED
:
1098 case CONTROL_CURRENT
:
1099 case CONTROL
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1101 case CONTROL_TEXT
: return wxColour(GetSysColor(COLOR_BTNTEXT
));
1103 case SCROLLBAR
: return wxColour(GetSysColor(COLOR_SCROLLBAR
));
1104 case SCROLLBAR_PRESSED
: return wxColour(GetSysColor(COLOR_HIGHLIGHT
));
1106 case HIGHLIGHT
: return wxColour(GetSysColor(COLOR_HIGHLIGHT
));
1107 case HIGHLIGHT_TEXT
: return wxColour(GetSysColor(COLOR_HIGHLIGHTTEXT
));
1109 #if defined(COLOR_3DDKSHADOW)
1110 case SHADOW_DARK
: return wxColour(GetSysColor(COLOR_3DDKSHADOW
));
1112 case SHADOW_DARK
: return *wxBLACK
;
1115 case CONTROL_TEXT_DISABLED
:
1116 case SHADOW_HIGHLIGHT
: return wxColour(GetSysColor(COLOR_BTNHIGHLIGHT
));
1118 case SHADOW_IN
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1120 case CONTROL_TEXT_DISABLED_SHADOW
:
1121 case SHADOW_OUT
: return wxColour(GetSysColor(COLOR_BTNSHADOW
));
1123 // use the standard Windows colours elsewhere
1124 case WINDOW
: return *wxWHITE
;
1126 case CONTROL_PRESSED
:
1127 case CONTROL_CURRENT
:
1128 case CONTROL
: return wxColour(0xc0c0c0);
1130 case CONTROL_TEXT
: return *wxBLACK
;
1132 case SCROLLBAR
: return wxColour(0xe0e0e0);
1133 case SCROLLBAR_PRESSED
: return *wxBLACK
;
1135 case HIGHLIGHT
: return wxColour(0x800000);
1136 case HIGHLIGHT_TEXT
: return wxColour(0xffffff);
1138 case SHADOW_DARK
: return *wxBLACK
;
1140 case CONTROL_TEXT_DISABLED
:
1141 case SHADOW_HIGHLIGHT
: return wxColour(0xe0e0e0);
1143 case SHADOW_IN
: return wxColour(0xc0c0c0);
1145 case CONTROL_TEXT_DISABLED_SHADOW
:
1146 case SHADOW_OUT
: return wxColour(0x7f7f7f);
1151 wxFAIL_MSG(_T("invalid standard colour"));
1156 // ============================================================================
1158 // ============================================================================
1160 // ----------------------------------------------------------------------------
1162 // ----------------------------------------------------------------------------
1164 wxWin32Renderer::wxWin32Renderer(const wxColourScheme
*scheme
)
1168 m_sizeScrollbarArrow
= wxSize(16, 16);
1170 // init colours and pens
1171 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
), 0, wxSOLID
);
1173 m_colDarkGrey
= wxSCHEME_COLOUR(scheme
, SHADOW_OUT
);
1174 m_penDarkGrey
= wxPen(m_colDarkGrey
, 0, wxSOLID
);
1176 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
), 0, wxSOLID
);
1178 m_colHighlight
= wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
);
1179 m_penHighlight
= wxPen(m_colHighlight
, 0, wxSOLID
);
1181 // init the arrow bitmaps
1182 static const size_t ARROW_WIDTH
= 7;
1183 static const size_t ARROW_LENGTH
= 4;
1186 wxMemoryDC dcNormal
,
1189 for ( size_t n
= 0; n
< Arrow_Max
; n
++ )
1191 bool isVertical
= n
> Arrow_Right
;
1204 // disabled arrow is larger because of the shadow
1205 m_bmpArrows
[Arrow_Normal
][n
].Create(w
, h
);
1206 m_bmpArrows
[Arrow_Disabled
][n
].Create(w
+ 1, h
+ 1);
1208 dcNormal
.SelectObject(m_bmpArrows
[Arrow_Normal
][n
]);
1209 dcDisabled
.SelectObject(m_bmpArrows
[Arrow_Disabled
][n
]);
1211 dcNormal
.SetBackground(*wxWHITE_BRUSH
);
1212 dcDisabled
.SetBackground(*wxWHITE_BRUSH
);
1216 dcNormal
.SetPen(m_penBlack
);
1217 dcDisabled
.SetPen(m_penDarkGrey
);
1219 // calculate the position of the point of the arrow
1223 x1
= (ARROW_WIDTH
- 1)/2;
1224 y1
= n
== Arrow_Up
? 0 : ARROW_LENGTH
- 1;
1228 x1
= n
== Arrow_Left
? 0 : ARROW_LENGTH
- 1;
1229 y1
= (ARROW_WIDTH
- 1)/2;
1240 for ( size_t i
= 0; i
< ARROW_LENGTH
; i
++ )
1242 dcNormal
.DrawLine(x1
, y1
, x2
, y2
);
1243 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1250 if ( n
== Arrow_Up
)
1261 else // left or right arrow
1266 if ( n
== Arrow_Left
)
1279 // draw the shadow for the disabled one
1280 dcDisabled
.SetPen(m_penHighlight
);
1285 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1289 x1
= ARROW_LENGTH
- 1;
1290 y1
= (ARROW_WIDTH
- 1)/2 + 1;
1293 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1294 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1299 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1303 x1
= ARROW_WIDTH
- 1;
1305 x2
= (ARROW_WIDTH
- 1)/2;
1307 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1308 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1313 // create the inversed bitmap but only for the right arrow as we only
1314 // use it for the menus
1315 if ( n
== Arrow_Right
)
1317 m_bmpArrows
[Arrow_Inversed
][n
].Create(w
, h
);
1318 dcInverse
.SelectObject(m_bmpArrows
[Arrow_Inversed
][n
]);
1320 dcInverse
.Blit(0, 0, w
, h
,
1323 dcInverse
.SelectObject(wxNullBitmap
);
1325 mask
= new wxMask(m_bmpArrows
[Arrow_Inversed
][n
], *wxBLACK
);
1326 m_bmpArrows
[Arrow_Inversed
][n
].SetMask(mask
);
1328 m_bmpArrows
[Arrow_InversedDisabled
][n
].Create(w
, h
);
1329 dcInverse
.SelectObject(m_bmpArrows
[Arrow_InversedDisabled
][n
]);
1331 dcInverse
.Blit(0, 0, w
, h
,
1334 dcInverse
.SelectObject(wxNullBitmap
);
1336 mask
= new wxMask(m_bmpArrows
[Arrow_InversedDisabled
][n
], *wxBLACK
);
1337 m_bmpArrows
[Arrow_InversedDisabled
][n
].SetMask(mask
);
1340 dcNormal
.SelectObject(wxNullBitmap
);
1341 dcDisabled
.SelectObject(wxNullBitmap
);
1343 mask
= new wxMask(m_bmpArrows
[Arrow_Normal
][n
], *wxWHITE
);
1344 m_bmpArrows
[Arrow_Normal
][n
].SetMask(mask
);
1345 mask
= new wxMask(m_bmpArrows
[Arrow_Disabled
][n
], *wxWHITE
);
1346 m_bmpArrows
[Arrow_Disabled
][n
].SetMask(mask
);
1348 m_bmpArrows
[Arrow_Pressed
][n
] = m_bmpArrows
[Arrow_Normal
][n
];
1352 // ----------------------------------------------------------------------------
1354 // ----------------------------------------------------------------------------
1357 The raised border in Win32 looks like this:
1359 IIIIIIIIIIIIIIIIIIIIIIB
1361 I GB I = white (HILIGHT)
1362 I GB H = light grey (LIGHT)
1363 I GB G = dark grey (SHADOI)
1364 I GB B = black (DKSHADOI)
1365 I GB I = hIghlight (COLOR_3DHILIGHT)
1367 IGGGGGGGGGGGGGGGGGGGGGB
1368 BBBBBBBBBBBBBBBBBBBBBBB
1370 The sunken border looks like this:
1372 GGGGGGGGGGGGGGGGGGGGGGI
1373 GBBBBBBBBBBBBBBBBBBBBHI
1380 GHHHHHHHHHHHHHHHHHHHHHI
1381 IIIIIIIIIIIIIIIIIIIIIII
1383 The static border (used for the controls which don't get focus) is like
1386 GGGGGGGGGGGGGGGGGGGGGGW
1394 WWWWWWWWWWWWWWWWWWWWWWW
1396 The most complicated is the double border:
1398 HHHHHHHHHHHHHHHHHHHHHHB
1399 HWWWWWWWWWWWWWWWWWWWWGB
1400 HWHHHHHHHHHHHHHHHHHHHGB
1405 HWHHHHHHHHHHHHHHHHHHHGB
1406 HGGGGGGGGGGGGGGGGGGGGGB
1407 BBBBBBBBBBBBBBBBBBBBBBB
1409 And the simple border is, well, simple:
1411 BBBBBBBBBBBBBBBBBBBBBBB
1420 BBBBBBBBBBBBBBBBBBBBBBB
1423 void wxWin32Renderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1427 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1428 dc
.DrawRectangle(*rect
);
1434 void wxWin32Renderer::DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1436 // draw the bottom and right sides
1438 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1439 rect
->GetRight() + 1, rect
->GetBottom());
1440 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1441 rect
->GetRight(), rect
->GetBottom());
1448 void wxWin32Renderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
1449 const wxPen
& pen1
, const wxPen
& pen2
)
1451 // draw the rectangle
1453 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
1454 rect
->GetLeft(), rect
->GetBottom());
1455 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
1456 rect
->GetRight(), rect
->GetTop());
1458 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1459 rect
->GetRight(), rect
->GetBottom());
1460 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1461 rect
->GetRight() + 1, rect
->GetBottom());
1467 void wxWin32Renderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
1469 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
1470 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
1473 void wxWin32Renderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
1475 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
1476 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
1479 void wxWin32Renderer::DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
)
1483 DrawRect(dc
, rect
, m_penDarkGrey
);
1485 // the arrow is usually drawn inside border of width 2 and is offset by
1486 // another pixel in both directions when it's pressed - as the border
1487 // in this case is more narrow as well, we have to adjust rect like
1495 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
1496 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
1500 void wxWin32Renderer::DrawBorder(wxDC
& dc
,
1502 const wxRect
& rectTotal
,
1503 int WXUNUSED(flags
),
1508 wxRect rect
= rectTotal
;
1512 case wxBORDER_SUNKEN
:
1513 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1515 DrawSunkenBorder(dc
, &rect
);
1519 case wxBORDER_STATIC
:
1520 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1523 case wxBORDER_RAISED
:
1524 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1526 DrawRaisedBorder(dc
, &rect
);
1530 case wxBORDER_DOUBLE
:
1531 DrawArrowBorder(dc
, &rect
);
1532 DrawRect(dc
, &rect
, m_penLightGrey
);
1535 case wxBORDER_SIMPLE
:
1536 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1538 DrawRect(dc
, &rect
, m_penBlack
);
1543 wxFAIL_MSG(_T("unknown border type"));
1546 case wxBORDER_DEFAULT
:
1555 wxRect
wxWin32Renderer::GetBorderDimensions(wxBorder border
) const
1560 case wxBORDER_RAISED
:
1561 case wxBORDER_SUNKEN
:
1562 width
= BORDER_THICKNESS
;
1565 case wxBORDER_SIMPLE
:
1566 case wxBORDER_STATIC
:
1570 case wxBORDER_DOUBLE
:
1575 wxFAIL_MSG(_T("unknown border type"));
1578 case wxBORDER_DEFAULT
:
1588 rect
.height
= width
;
1593 bool wxWin32Renderer::AreScrollbarsInsideBorder() const
1598 // ----------------------------------------------------------------------------
1600 // ----------------------------------------------------------------------------
1602 void wxWin32Renderer::DrawTextBorder(wxDC
& dc
,
1608 // text controls are not special under windows
1609 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
1612 void wxWin32Renderer::DrawButtonBorder(wxDC
& dc
,
1613 const wxRect
& rectTotal
,
1617 wxRect rect
= rectTotal
;
1619 if ( flags
& wxCONTROL_PRESSED
)
1621 // button pressed: draw a double border around it
1622 DrawRect(dc
, &rect
, m_penBlack
);
1623 DrawRect(dc
, &rect
, m_penDarkGrey
);
1627 // button not pressed
1629 if ( flags
& (wxCONTROL_FOCUSED
| wxCONTROL_ISDEFAULT
) )
1631 // button either default or focused (or both): add an extra border around it
1632 DrawRect(dc
, &rect
, m_penBlack
);
1635 // now draw a normal button
1636 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penBlack
);
1637 DrawHalfRect(dc
, &rect
, m_penDarkGrey
);
1646 // ----------------------------------------------------------------------------
1648 // ----------------------------------------------------------------------------
1650 void wxWin32Renderer::DrawHorizontalLine(wxDC
& dc
,
1651 wxCoord y
, wxCoord x1
, wxCoord x2
)
1653 dc
.SetPen(m_penDarkGrey
);
1654 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1655 dc
.SetPen(m_penHighlight
);
1657 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1660 void wxWin32Renderer::DrawVerticalLine(wxDC
& dc
,
1661 wxCoord x
, wxCoord y1
, wxCoord y2
)
1663 dc
.SetPen(m_penDarkGrey
);
1664 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1665 dc
.SetPen(m_penHighlight
);
1667 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1670 void wxWin32Renderer::DrawFrame(wxDC
& dc
,
1671 const wxString
& label
,
1677 wxCoord height
= 0; // of the label
1678 wxRect rectFrame
= rect
;
1679 if ( !label
.empty() )
1681 // the text should touch the top border of the rect, so the frame
1682 // itself should be lower
1683 dc
.GetTextExtent(label
, NULL
, &height
);
1684 rectFrame
.y
+= height
/ 2;
1685 rectFrame
.height
-= height
/ 2;
1687 // we have to draw each part of the frame individually as we can't
1688 // erase the background beyond the label as it might contain some
1689 // pixmap already, so drawing everything and then overwriting part of
1690 // the frame with label doesn't work
1692 // TODO: the +5 and space insertion should be customizable
1695 rectText
.x
= rectFrame
.x
+ 5;
1696 rectText
.y
= rect
.y
;
1697 rectText
.width
= rectFrame
.width
- 7; // +2 border width
1698 rectText
.height
= height
;
1701 label2
<< _T(' ') << label
<< _T(' ');
1702 if ( indexAccel
!= -1 )
1704 // adjust it as we prepended a space
1709 DrawLabel(dc
, label2
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
1711 StandardDrawFrame(dc
, rectFrame
, rectLabel
);
1715 // just draw the complete frame
1716 DrawShadedRect(dc
, &rectFrame
, m_penDarkGrey
, m_penHighlight
);
1717 DrawShadedRect(dc
, &rectFrame
, m_penHighlight
, m_penDarkGrey
);
1721 // ----------------------------------------------------------------------------
1723 // ----------------------------------------------------------------------------
1725 void wxWin32Renderer::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
1727 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
1728 // pixels each while we really need dots here... PS_ALTERNATE might
1729 // work, but it is for NT 5 only
1731 DrawRect(dc
, &rect
, wxPen(*wxBLACK
, 0, wxDOT
));
1733 // draw the pixels manually: note that to behave in the same manner as
1734 // DrawRect(), we must exclude the bottom and right borders from the
1736 wxCoord x1
= rect
.GetLeft(),
1738 x2
= rect
.GetRight(),
1739 y2
= rect
.GetBottom();
1741 dc
.SetPen(wxPen(*wxBLACK
, 0, wxSOLID
));
1743 // this seems to be closer than what Windows does than wxINVERT although
1744 // I'm still not sure if it's correct
1745 dc
.SetLogicalFunction(wxAND_REVERSE
);
1748 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
1749 dc
.DrawPoint(z
, rect
.GetTop());
1751 wxCoord shift
= z
== x2
? 0 : 1;
1752 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
1753 dc
.DrawPoint(x2
, z
);
1755 shift
= z
== y2
? 0 : 1;
1756 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
1757 dc
.DrawPoint(z
, y2
);
1759 shift
= z
== x1
? 0 : 1;
1760 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
1761 dc
.DrawPoint(x1
, z
);
1763 dc
.SetLogicalFunction(wxCOPY
);
1767 void wxWin32Renderer::DrawLabelShadow(wxDC
& dc
,
1768 const wxString
& label
,
1773 // draw shadow of the text
1774 dc
.SetTextForeground(m_colHighlight
);
1775 wxRect rectShadow
= rect
;
1778 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
1780 // make the text grey
1781 dc
.SetTextForeground(m_colDarkGrey
);
1784 void wxWin32Renderer::DrawLabel(wxDC
& dc
,
1785 const wxString
& label
,
1792 DoDrawLabel(dc
, label
, rect
, flags
, alignment
, indexAccel
, rectBounds
);
1795 void wxWin32Renderer::DoDrawLabel(wxDC
& dc
,
1796 const wxString
& label
,
1802 const wxPoint
& focusOffset
)
1804 // the underscores are not drawn for focused controls in wxMSW
1805 if ( flags
& wxCONTROL_FOCUSED
)
1810 if ( flags
& wxCONTROL_DISABLED
)
1812 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
1813 // currently only can happen for a menu item and it seems that Windows
1814 // doesn't draw the shadow in this case, so we don't do it neither
1815 if ( flags
& wxCONTROL_SELECTED
)
1817 // just make the label text greyed out
1818 dc
.SetTextForeground(m_colDarkGrey
);
1820 else // draw normal disabled label
1822 DrawLabelShadow(dc
, label
, rect
, alignment
, indexAccel
);
1827 dc
.DrawLabel(label
, wxNullBitmap
, rect
, alignment
, indexAccel
, &rectLabel
);
1829 if ( flags
& wxCONTROL_DISABLED
)
1831 // restore the fg colour
1832 dc
.SetTextForeground(*wxBLACK
);
1835 if ( flags
& wxCONTROL_FOCUSED
)
1837 if ( focusOffset
.x
|| focusOffset
.y
)
1839 rectLabel
.Inflate(focusOffset
.x
, focusOffset
.y
);
1842 DrawFocusRect(dc
, rectLabel
);
1846 *rectBounds
= rectLabel
;
1849 void wxWin32Renderer::DrawButtonLabel(wxDC
& dc
,
1850 const wxString
& label
,
1851 const wxBitmap
& image
,
1858 // the underscores are not drawn for focused controls in wxMSW
1859 if ( flags
& wxCONTROL_PRESSED
)
1864 wxRect rectLabel
= rect
;
1865 if ( !label
.empty() )
1867 // shift the label if a button is pressed
1868 if ( flags
& wxCONTROL_PRESSED
)
1874 if ( flags
& wxCONTROL_DISABLED
)
1876 DrawLabelShadow(dc
, label
, rectLabel
, alignment
, indexAccel
);
1879 // leave enough space for the focus rectangle
1880 if ( flags
& wxCONTROL_FOCUSED
)
1882 rectLabel
.Inflate(-2);
1886 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
1888 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
1890 if ( flags
& wxCONTROL_PRESSED
)
1892 // the focus rectangle is never pressed, so undo the shift done
1900 DrawFocusRect(dc
, rectLabel
);
1904 // ----------------------------------------------------------------------------
1905 // (check)listbox items
1906 // ----------------------------------------------------------------------------
1908 void wxWin32Renderer::DrawItem(wxDC
& dc
,
1909 const wxString
& label
,
1913 wxDCTextColourChanger
colChanger(dc
);
1915 if ( flags
& wxCONTROL_SELECTED
)
1917 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
1919 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
1920 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
1921 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
1922 dc
.DrawRectangle(rect
);
1925 wxRect rectText
= rect
;
1927 rectText
.width
-= 2;
1928 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
1930 if ( flags
& wxCONTROL_FOCUSED
)
1932 DrawFocusRect(dc
, rect
);
1936 void wxWin32Renderer::DrawCheckItem(wxDC
& dc
,
1937 const wxString
& label
,
1938 const wxBitmap
& bitmap
,
1947 else // use default bitmap
1949 bmp
= wxBitmap(flags
& wxCONTROL_CHECKED
? checked_item_xpm
1950 : unchecked_item_xpm
);
1953 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2 - 1,
1954 TRUE
/* use mask */);
1956 wxRect rectLabel
= rect
;
1957 int bmpWidth
= bmp
.GetWidth();
1958 rectLabel
.x
+= bmpWidth
;
1959 rectLabel
.width
-= bmpWidth
;
1961 DrawItem(dc
, label
, rectLabel
, flags
);
1964 // ----------------------------------------------------------------------------
1965 // check/radio buttons
1966 // ----------------------------------------------------------------------------
1968 wxBitmap
wxWin32Renderer::GetIndicator(IndicatorType indType
, int flags
)
1970 IndicatorState indState
;
1971 if ( flags
& wxCONTROL_SELECTED
)
1972 indState
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
1973 : IndicatorState_Selected
;
1974 else if ( flags
& wxCONTROL_DISABLED
)
1975 indState
= IndicatorState_Disabled
;
1976 else if ( flags
& wxCONTROL_PRESSED
)
1977 indState
= IndicatorState_Pressed
;
1979 indState
= IndicatorState_Normal
;
1981 IndicatorStatus indStatus
= flags
& wxCONTROL_CHECKED
1982 ? IndicatorStatus_Checked
1983 : IndicatorStatus_Unchecked
;
1985 const char **xpm
= bmpIndicators
[indType
][indState
][indStatus
];
1986 return xpm
? wxBitmap(xpm
) : wxNullBitmap
;
1989 void wxWin32Renderer::DrawCheckOrRadioButton(wxDC
& dc
,
1990 const wxString
& label
,
1991 const wxBitmap
& bitmap
,
1996 wxCoord focusOffsetY
)
1998 // calculate the position of the bitmap and of the label
1999 wxCoord heightBmp
= bitmap
.GetHeight();
2001 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
2004 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
2005 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
2007 // align label vertically with the bitmap - looks nicer like this
2008 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
2010 // calc horz position
2011 if ( align
== wxALIGN_RIGHT
)
2013 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
2014 rectLabel
.x
= rect
.x
+ 3;
2015 rectLabel
.SetRight(xBmp
);
2017 else // normal (checkbox to the left of the text) case
2020 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
2021 rectLabel
.SetRight(rect
.GetRight());
2024 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, TRUE
/* use mask */);
2027 dc
, label
, rectLabel
,
2029 wxALIGN_LEFT
| wxALIGN_TOP
,
2031 NULL
, // we don't need bounding rect
2032 // use custom vert focus rect offset
2033 wxPoint(FOCUS_RECT_OFFSET_X
, focusOffsetY
)
2037 void wxWin32Renderer::DrawRadioButton(wxDC
& dc
,
2038 const wxString
& label
,
2039 const wxBitmap
& bitmap
,
2045 DrawCheckOrRadioButton(dc
, label
,
2046 bitmap
.Ok() ? bitmap
: GetRadioBitmap(flags
),
2047 rect
, flags
, align
, indexAccel
,
2048 FOCUS_RECT_OFFSET_Y
); // default focus rect offset
2051 void wxWin32Renderer::DrawCheckButton(wxDC
& dc
,
2052 const wxString
& label
,
2053 const wxBitmap
& bitmap
,
2059 DrawCheckOrRadioButton(dc
, label
,
2060 bitmap
.Ok() ? bitmap
: GetCheckBitmap(flags
),
2061 rect
, flags
, align
, indexAccel
,
2062 0); // no focus rect offset for checkboxes
2065 // ----------------------------------------------------------------------------
2067 // ----------------------------------------------------------------------------
2069 void wxWin32Renderer::DrawTextLine(wxDC
& dc
,
2070 const wxString
& text
,
2076 // nothing special to do here
2077 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
2080 void wxWin32Renderer::DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
)
2082 // we don't draw them
2085 // ----------------------------------------------------------------------------
2087 // ----------------------------------------------------------------------------
2089 void wxWin32Renderer::DrawTab(wxDC
& dc
,
2090 const wxRect
& rectOrig
,
2092 const wxString
& label
,
2093 const wxBitmap
& bitmap
,
2097 wxRect rect
= rectOrig
;
2099 // the current tab is drawn indented (to the top for default case) and
2100 // bigger than the other ones
2101 const wxSize indent
= GetTabIndent();
2102 if ( flags
& wxCONTROL_SELECTED
)
2107 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2111 rect
.Inflate(indent
.x
, 0);
2113 rect
.height
+= indent
.y
;
2117 rect
.Inflate(indent
.x
, 0);
2118 rect
.height
+= indent
.y
;
2123 wxFAIL_MSG(_T("TODO"));
2128 // draw the text, image and the focus around them (if necessary)
2129 wxRect rectLabel
= rect
;
2130 rectLabel
.Deflate(1, 1);
2131 DrawButtonLabel(dc
, label
, bitmap
, rectLabel
,
2132 flags
, wxALIGN_CENTRE
, indexAccel
);
2134 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2135 static const wxCoord CUTOFF
= 2; // radius of the rounded corner
2138 x2
= rect
.GetRight(),
2139 y2
= rect
.GetBottom();
2141 // FIXME: all this code will break if the tab indent or the border width,
2142 // it is tied to the fact that both of them are equal to 2
2147 dc
.SetPen(m_penHighlight
);
2148 dc
.DrawLine(x
, y2
, x
, y
+ CUTOFF
);
2149 dc
.DrawLine(x
, y
+ CUTOFF
, x
+ CUTOFF
, y
);
2150 dc
.DrawLine(x
+ CUTOFF
, y
, x2
- CUTOFF
+ 1, y
);
2152 dc
.SetPen(m_penBlack
);
2153 dc
.DrawLine(x2
, y2
, x2
, y
+ CUTOFF
);
2154 dc
.DrawLine(x2
, y
+ CUTOFF
, x2
- CUTOFF
, y
);
2156 dc
.SetPen(m_penDarkGrey
);
2157 dc
.DrawLine(x2
- 1, y2
, x2
- 1, y
+ CUTOFF
- 1);
2159 if ( flags
& wxCONTROL_SELECTED
)
2161 dc
.SetPen(m_penLightGrey
);
2163 // overwrite the part of the border below this tab
2164 dc
.DrawLine(x
+ 1, y2
+ 1, x2
- 1, y2
+ 1);
2166 // and the shadow of the tab to the left of us
2167 dc
.DrawLine(x
+ 1, y
+ CUTOFF
+ 1, x
+ 1, y2
+ 1);
2172 dc
.SetPen(m_penHighlight
);
2173 // we need to continue one pixel further to overwrite the corner of
2174 // the border for the selected tab
2175 dc
.DrawLine(x
, y
- (flags
& wxCONTROL_SELECTED
? 1 : 0),
2177 dc
.DrawLine(x
, y2
- CUTOFF
, x
+ CUTOFF
, y2
);
2179 dc
.SetPen(m_penBlack
);
2180 dc
.DrawLine(x
+ CUTOFF
, y2
, x2
- CUTOFF
+ 1, y2
);
2181 dc
.DrawLine(x2
, y
, x2
, y2
- CUTOFF
);
2182 dc
.DrawLine(x2
, y2
- CUTOFF
, x2
- CUTOFF
, y2
);
2184 dc
.SetPen(m_penDarkGrey
);
2185 dc
.DrawLine(x
+ CUTOFF
, y2
- 1, x2
- CUTOFF
+ 1, y2
- 1);
2186 dc
.DrawLine(x2
- 1, y
, x2
- 1, y2
- CUTOFF
+ 1);
2188 if ( flags
& wxCONTROL_SELECTED
)
2190 dc
.SetPen(m_penLightGrey
);
2192 // overwrite the part of the (double!) border above this tab
2193 dc
.DrawLine(x
+ 1, y
- 1, x2
- 1, y
- 1);
2194 dc
.DrawLine(x
+ 1, y
- 2, x2
- 1, y
- 2);
2196 // and the shadow of the tab to the left of us
2197 dc
.DrawLine(x
+ 1, y2
- CUTOFF
, x
+ 1, y
- 1);
2203 wxFAIL_MSG(_T("TODO"));
2207 // ----------------------------------------------------------------------------
2209 // ----------------------------------------------------------------------------
2211 wxSize
wxWin32Renderer::GetSliderThumbSize(const wxRect
& rect
,
2212 wxOrientation orient
) const
2216 wxRect rectShaft
= GetSliderShaftRect(rect
, orient
);
2217 if ( orient
== wxHORIZONTAL
)
2219 size
.y
= rect
.height
- 6;
2220 size
.x
= wxMin(size
.y
/ 2, rectShaft
.width
);
2224 size
.x
= rect
.width
- 6;
2225 size
.y
= wxMin(size
.x
/ 2, rectShaft
.height
);
2231 wxRect
wxWin32Renderer::GetSliderShaftRect(const wxRect
& rectOrig
,
2232 wxOrientation orient
) const
2234 static const wxCoord SLIDER_MARGIN
= 6;
2236 wxRect rect
= rectOrig
;
2238 if ( orient
== wxHORIZONTAL
)
2240 // make the rect of minimal width and centre it
2241 rect
.height
= 2*BORDER_THICKNESS
;
2242 rect
.y
= rectOrig
.y
+ (rectOrig
.height
- rect
.height
) / 2;
2246 // leave margins on the sides
2247 rect
.Deflate(SLIDER_MARGIN
, 0);
2251 // same as above but in other direction
2252 rect
.width
= 2*BORDER_THICKNESS
;
2253 rect
.x
= rectOrig
.x
+ (rectOrig
.width
- rect
.width
) / 2;
2257 rect
.Deflate(0, SLIDER_MARGIN
);
2263 void wxWin32Renderer::DrawSliderShaft(wxDC
& dc
,
2264 const wxRect
& rectOrig
,
2265 wxOrientation orient
,
2269 if ( flags
& wxCONTROL_FOCUSED
)
2271 DrawFocusRect(dc
, rectOrig
);
2274 wxRect rect
= GetSliderShaftRect(rectOrig
, orient
);
2279 DrawSunkenBorder(dc
, &rect
);
2282 void wxWin32Renderer::DrawSliderThumb(wxDC
& dc
,
2284 wxOrientation orient
,
2288 we are drawing a shape of this form
2293 H DB where H is hightlight colour
2306 The interior of this shape is filled with the hatched brush if the thumb
2310 DrawBackground(dc
, wxNullColour
, rect
, flags
);
2312 bool transpose
= orient
== wxVERTICAL
;
2314 wxCoord x
, y
, x2
, y2
;
2319 x2
= rect
.GetBottom();
2320 y2
= rect
.GetRight();
2326 x2
= rect
.GetRight();
2327 y2
= rect
.GetBottom();
2330 // the size of the pointed part of the thumb
2331 wxCoord sizeArrow
= (transpose
? rect
.height
: rect
.width
) / 2;
2333 wxCoord x3
= x
+ sizeArrow
,
2334 y3
= y2
- sizeArrow
;
2336 dc
.SetPen(m_penHighlight
);
2337 DrawLine(dc
, x
, y
, x2
, y
, transpose
);
2338 DrawLine(dc
, x
, y
+ 1, x
, y2
- sizeArrow
, transpose
);
2339 DrawLine(dc
, x
, y3
, x3
, y2
, transpose
);
2341 dc
.SetPen(m_penBlack
);
2342 DrawLine(dc
, x3
, y2
, x2
, y3
, transpose
);
2343 DrawLine(dc
, x2
, y3
, x2
, y
- 1, transpose
);
2345 dc
.SetPen(m_penDarkGrey
);
2346 DrawLine(dc
, x3
, y2
- 1, x2
- 1, y3
, transpose
);
2347 DrawLine(dc
, x2
- 1, y3
, x2
- 1, y
, transpose
);
2349 if ( flags
& wxCONTROL_PRESSED
)
2351 // TODO: MSW fills the entire area inside, not just the rect
2352 wxRect rectInt
= rect
;
2354 rectInt
.SetRight(y3
);
2356 rectInt
.SetBottom(y3
);
2359 static const char *stipple_xpm
[] = {
2360 /* columns rows colors chars-per-pixel */
2368 dc
.SetBrush(wxBrush(stipple_xpm
));
2370 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, SHADOW_HIGHLIGHT
));
2371 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, CONTROL
));
2372 dc
.SetPen(*wxTRANSPARENT_PEN
);
2373 dc
.DrawRectangle(rectInt
);
2377 void wxWin32Renderer::DrawSliderTicks(wxDC
& dc
,
2379 const wxSize
& sizeThumb
,
2380 wxOrientation orient
,
2392 // the variable names correspond to horizontal case, but they can be used
2393 // for both orientations
2394 wxCoord x1
, x2
, y1
, y2
, len
, widthThumb
;
2395 if ( orient
== wxHORIZONTAL
)
2397 x1
= rect
.GetLeft();
2398 x2
= rect
.GetRight();
2400 // draw from bottom to top to leave one pixel space between the ticks
2401 // and the slider as Windows do
2402 y1
= rect
.GetBottom();
2407 widthThumb
= sizeThumb
.x
;
2412 x2
= rect
.GetBottom();
2414 y1
= rect
.GetRight();
2415 y2
= rect
.GetLeft();
2419 widthThumb
= sizeThumb
.y
;
2422 // the first tick should be positioned in such way that a thumb drawn in
2423 // the first position points down directly to it
2424 x1
+= widthThumb
/ 2;
2425 x2
-= widthThumb
/ 2;
2427 // this also means that we have slightly less space for the ticks in
2428 // between the first and the last
2431 dc
.SetPen(m_penBlack
);
2433 int range
= end
- start
;
2434 for ( int n
= 0; n
< range
; n
+= step
)
2436 wxCoord x
= x1
+ (len
*n
) / range
;
2438 DrawLine(dc
, x
, y1
, x
, y2
, orient
== wxVERTICAL
);
2441 // always draw the line at the end position
2442 DrawLine(dc
, x2
, y1
, x2
, y2
, orient
== wxVERTICAL
);
2445 // ----------------------------------------------------------------------------
2447 // ----------------------------------------------------------------------------
2451 // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2452 class WXDLLEXPORT wxWin32MenuGeometryInfo
: public wxMenuGeometryInfo
2455 virtual wxSize
GetSize() const { return m_size
; }
2457 wxCoord
GetLabelOffset() const { return m_ofsLabel
; }
2458 wxCoord
GetAccelOffset() const { return m_ofsAccel
; }
2460 wxCoord
GetItemHeight() const { return m_heightItem
; }
2463 // the total size of the menu
2466 // the offset of the start of the menu item label
2469 // the offset of the start of the accel label
2472 // the height of a normal (not separator) item
2473 wxCoord m_heightItem
;
2475 friend wxMenuGeometryInfo
*wxWin32Renderer::
2476 GetMenuGeometry(wxWindow
*, const wxMenu
&) const;
2479 #endif // wxUSE_MENUS
2481 // FIXME: all constants are hardcoded but shouldn't be
2482 static const wxCoord MENU_LEFT_MARGIN
= 9;
2483 static const wxCoord MENU_RIGHT_MARGIN
= 18;
2484 static const wxCoord MENU_VERT_MARGIN
= 3;
2486 // the margin around bitmap/check marks (on each side)
2487 static const wxCoord MENU_BMP_MARGIN
= 2;
2489 // the margin between the labels and accel strings
2490 static const wxCoord MENU_ACCEL_MARGIN
= 8;
2492 // the separator height in pixels: in fact, strangely enough, the real height
2493 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2495 static const wxCoord MENU_SEPARATOR_HEIGHT
= 3;
2497 // the size of the standard checkmark bitmap
2498 static const wxCoord MENU_CHECK_SIZE
= 9;
2500 // we can't implement these methods without wxMenuGeometryInfo implementation
2501 // which we don't have if !wxUSE_MENUS
2504 void wxWin32Renderer::DrawMenuBarItem(wxDC
& dc
,
2505 const wxRect
& rectOrig
,
2506 const wxString
& label
,
2510 wxRect rect
= rectOrig
;
2513 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 // don't draw the focus rect around menu bar items
2526 DrawLabel(dc
, label
, rect
, flags
& ~wxCONTROL_FOCUSED
,
2527 wxALIGN_CENTRE
, indexAccel
);
2530 void wxWin32Renderer::DrawMenuItem(wxDC
& dc
,
2532 const wxMenuGeometryInfo
& gi
,
2533 const wxString
& label
,
2534 const wxString
& accel
,
2535 const wxBitmap
& bitmap
,
2539 const wxWin32MenuGeometryInfo
& geometryInfo
=
2540 (const wxWin32MenuGeometryInfo
&)gi
;
2545 rect
.width
= geometryInfo
.GetSize().x
;
2546 rect
.height
= geometryInfo
.GetItemHeight();
2548 // draw the selected item specially
2549 wxDCTextColourChanger
colChanger(dc
);
2550 if ( flags
& wxCONTROL_SELECTED
)
2552 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2554 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2555 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2556 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2557 dc
.DrawRectangle(rect
);
2560 // draw the bitmap: use the bitmap provided or the standard checkmark for
2561 // the checkable items
2562 wxBitmap bmp
= bitmap
;
2563 if ( !bmp
.Ok() && (flags
& wxCONTROL_CHECKED
) )
2565 bmp
= GetIndicator(IndicatorType_Menu
, flags
);
2570 rect
.SetRight(geometryInfo
.GetLabelOffset());
2571 wxControlRenderer::DrawBitmap(dc
, bmp
, rect
);
2575 rect
.x
= geometryInfo
.GetLabelOffset();
2576 rect
.SetRight(geometryInfo
.GetAccelOffset());
2578 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
, indexAccel
);
2580 // draw the accel string
2581 rect
.x
= geometryInfo
.GetAccelOffset();
2582 rect
.SetRight(geometryInfo
.GetSize().x
);
2584 // NB: no accel index here
2585 DrawLabel(dc
, accel
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
);
2587 // draw the submenu indicator
2588 if ( flags
& wxCONTROL_ISSUBMENU
)
2590 rect
.x
= geometryInfo
.GetSize().x
- MENU_RIGHT_MARGIN
;
2591 rect
.width
= MENU_RIGHT_MARGIN
;
2593 wxArrowStyle arrowStyle
;
2594 if ( flags
& wxCONTROL_DISABLED
)
2595 arrowStyle
= flags
& wxCONTROL_SELECTED
? Arrow_InversedDisabled
2597 else if ( flags
& wxCONTROL_SELECTED
)
2598 arrowStyle
= Arrow_Inversed
;
2600 arrowStyle
= Arrow_Normal
;
2602 DrawArrow(dc
, rect
, Arrow_Right
, arrowStyle
);
2606 void wxWin32Renderer::DrawMenuSeparator(wxDC
& dc
,
2608 const wxMenuGeometryInfo
& geomInfo
)
2610 DrawHorizontalLine(dc
, y
+ MENU_VERT_MARGIN
, 0, geomInfo
.GetSize().x
);
2613 wxSize
wxWin32Renderer::GetMenuBarItemSize(const wxSize
& sizeText
) const
2615 wxSize size
= sizeText
;
2617 // FIXME: menubar height is configurable under Windows
2624 wxMenuGeometryInfo
*wxWin32Renderer::GetMenuGeometry(wxWindow
*win
,
2625 const wxMenu
& menu
) const
2627 // prepare the dc: for now we draw all the items with the system font
2629 dc
.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
));
2631 // the height of a normal item
2632 wxCoord heightText
= dc
.GetCharHeight();
2637 // the max length of label and accel strings: the menu width is the sum of
2638 // them, even if they're for different items (as the accels should be
2641 // the max length of the bitmap is never 0 as Windows always leaves enough
2642 // space for a check mark indicator
2643 wxCoord widthLabelMax
= 0,
2645 widthBmpMax
= MENU_LEFT_MARGIN
;
2647 for ( wxMenuItemList::Node
*node
= menu
.GetMenuItems().GetFirst();
2649 node
= node
->GetNext() )
2651 // height of this item
2654 wxMenuItem
*item
= node
->GetData();
2655 if ( item
->IsSeparator() )
2657 h
= MENU_SEPARATOR_HEIGHT
;
2659 else // not separator
2664 dc
.GetTextExtent(item
->GetLabel(), &widthLabel
, NULL
);
2665 if ( widthLabel
> widthLabelMax
)
2667 widthLabelMax
= widthLabel
;
2671 dc
.GetTextExtent(item
->GetAccelString(), &widthAccel
, NULL
);
2672 if ( widthAccel
> widthAccelMax
)
2674 widthAccelMax
= widthAccel
;
2677 const wxBitmap
& bmp
= item
->GetBitmap();
2680 wxCoord widthBmp
= bmp
.GetWidth();
2681 if ( widthBmp
> widthBmpMax
)
2682 widthBmpMax
= widthBmp
;
2684 //else if ( item->IsCheckable() ): no need to check for this as
2685 // MENU_LEFT_MARGIN is big enough to show the check mark
2688 h
+= 2*MENU_VERT_MARGIN
;
2690 // remember the item position and height
2691 item
->SetGeometry(height
, h
);
2696 // bundle the metrics into a struct and return it
2697 wxWin32MenuGeometryInfo
*gi
= new wxWin32MenuGeometryInfo
;
2699 gi
->m_ofsLabel
= widthBmpMax
+ 2*MENU_BMP_MARGIN
;
2700 gi
->m_ofsAccel
= gi
->m_ofsLabel
+ widthLabelMax
;
2701 if ( widthAccelMax
> 0 )
2703 // if we actually have any accesl, add a margin
2704 gi
->m_ofsAccel
+= MENU_ACCEL_MARGIN
;
2707 gi
->m_heightItem
= heightText
+ 2*MENU_VERT_MARGIN
;
2709 gi
->m_size
.x
= gi
->m_ofsAccel
+ widthAccelMax
+ MENU_RIGHT_MARGIN
;
2710 gi
->m_size
.y
= height
;
2715 #else // !wxUSE_MENUS
2718 void wxWin32Renderer::DrawMenuBarItem(wxDC& WXUNUSED(dc),
2719 const wxRect& WXUNUSED(rectOrig),
2720 const wxString& WXUNUSED(label),
2721 int WXUNUSED(flags),
2722 int WXUNUSED(indexAccel))
2726 void wxWin32Renderer::DrawMenuItem(wxDC& WXUNUSED(dc),
2727 wxCoord WXUNUSED(y),
2728 const wxMenuGeometryInfo& WXUNUSED(gi),
2729 const wxString& WXUNUSED(label),
2730 const wxString& WXUNUSED(accel),
2731 const wxBitmap& WXUNUSED(bitmap),
2732 int WXUNUSED(flags),
2733 int WXUNUSED(indexAccel))
2737 void wxWin32Renderer::DrawMenuSeparator(wxDC& WXUNUSED(dc),
2738 wxCoord WXUNUSED(y),
2739 const wxMenuGeometryInfo& WXUNUSED(gi))
2743 wxSize wxWin32Renderer::GetMenuBarItemSize(const wxSize& size) const
2748 wxMenuGeometryInfo *
2749 wxWin32Renderer::GetMenuGeometry(wxWindow *WXUNUSED(win),
2750 const wxMenu& WXUNUSED(menu)) const
2756 #endif // wxUSE_MENUS/!wxUSE_MENUS
2758 // ----------------------------------------------------------------------------
2760 // ----------------------------------------------------------------------------
2762 void wxWin32Renderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
2764 wxBitmap
*bmpPressed
,
2765 wxBitmap
*bmpDisabled
)
2767 static const wxCoord widthCombo
= 16;
2768 static const wxCoord heightCombo
= 17;
2774 bmpNormal
->Create(widthCombo
, heightCombo
);
2775 dcMem
.SelectObject(*bmpNormal
);
2776 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2777 Arrow_Down
, Arrow_Normal
);
2782 bmpPressed
->Create(widthCombo
, heightCombo
);
2783 dcMem
.SelectObject(*bmpPressed
);
2784 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2785 Arrow_Down
, Arrow_Pressed
);
2790 bmpDisabled
->Create(widthCombo
, heightCombo
);
2791 dcMem
.SelectObject(*bmpDisabled
);
2792 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2793 Arrow_Down
, Arrow_Disabled
);
2797 // ----------------------------------------------------------------------------
2799 // ----------------------------------------------------------------------------
2801 void wxWin32Renderer::DoDrawBackground(wxDC
& dc
,
2802 const wxColour
& col
,
2805 wxBrush
brush(col
, wxSOLID
);
2807 dc
.SetPen(*wxTRANSPARENT_PEN
);
2808 dc
.DrawRectangle(rect
);
2811 void wxWin32Renderer::DrawBackground(wxDC
& dc
,
2812 const wxColour
& col
,
2816 // just fill it with the given or default bg colour
2817 wxColour colBg
= col
.Ok() ? col
: wxSCHEME_COLOUR(m_scheme
, CONTROL
);
2818 DoDrawBackground(dc
, colBg
, rect
);
2821 // ----------------------------------------------------------------------------
2823 // ----------------------------------------------------------------------------
2825 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2830 // get the bitmap for this arrow
2831 wxArrowDirection arrowDir
;
2834 case wxLEFT
: arrowDir
= Arrow_Left
; break;
2835 case wxRIGHT
: arrowDir
= Arrow_Right
; break;
2836 case wxUP
: arrowDir
= Arrow_Up
; break;
2837 case wxDOWN
: arrowDir
= Arrow_Down
; break;
2840 wxFAIL_MSG(_T("unknown arrow direction"));
2844 wxArrowStyle arrowStyle
;
2845 if ( flags
& wxCONTROL_PRESSED
)
2847 // can't be pressed and disabled
2848 arrowStyle
= Arrow_Pressed
;
2852 arrowStyle
= flags
& wxCONTROL_DISABLED
? Arrow_Disabled
: Arrow_Normal
;
2855 DrawArrowButton(dc
, rect
, arrowDir
, arrowStyle
);
2858 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2860 wxArrowDirection arrowDir
,
2861 wxArrowStyle arrowStyle
)
2863 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
2865 // under Windows the arrows always have the same size so just centre it in
2866 // the provided rectangle
2867 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
2868 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
2870 // Windows does it like this...
2871 if ( arrowDir
== Arrow_Left
)
2875 dc
.DrawBitmap(bmp
, x
, y
, TRUE
/* use mask */);
2878 void wxWin32Renderer::DrawArrowButton(wxDC
& dc
,
2879 const wxRect
& rectAll
,
2880 wxArrowDirection arrowDir
,
2881 wxArrowStyle arrowStyle
)
2883 wxRect rect
= rectAll
;
2884 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2885 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
2886 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
2889 void wxWin32Renderer::DrawScrollbarThumb(wxDC
& dc
,
2890 wxOrientation orient
,
2894 // we don't use the flags, the thumb never changes appearance
2895 wxRect rectThumb
= rect
;
2896 DrawArrowBorder(dc
, &rectThumb
);
2897 DrawBackground(dc
, wxNullColour
, rectThumb
);
2900 void wxWin32Renderer::DrawScrollbarShaft(wxDC
& dc
,
2901 wxOrientation orient
,
2902 const wxRect
& rectBar
,
2905 wxColourScheme::StdColour col
= flags
& wxCONTROL_PRESSED
2906 ? wxColourScheme::SCROLLBAR_PRESSED
2907 : wxColourScheme::SCROLLBAR
;
2908 DoDrawBackground(dc
, m_scheme
->Get(col
), rectBar
);
2911 void wxWin32Renderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
2913 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2916 wxRect
wxWin32Renderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
2917 wxScrollBar::Element elem
,
2920 return StandardGetScrollbarRect(scrollbar
, elem
,
2921 thumbPos
, m_sizeScrollbarArrow
);
2924 wxCoord
wxWin32Renderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
2926 return StandardScrollBarSize(scrollbar
, m_sizeScrollbarArrow
);
2929 wxHitTest
wxWin32Renderer::HitTestScrollbar(const wxScrollBar
*scrollbar
,
2930 const wxPoint
& pt
) const
2932 return StandardHitTestScrollbar(scrollbar
, pt
, m_sizeScrollbarArrow
);
2935 wxCoord
wxWin32Renderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
2938 return StandardScrollbarToPixel(scrollbar
, thumbPos
, m_sizeScrollbarArrow
);
2941 int wxWin32Renderer::PixelToScrollbar(const wxScrollBar
*scrollbar
,
2944 return StandardPixelToScrollbar(scrollbar
, coord
, m_sizeScrollbarArrow
);
2947 // ----------------------------------------------------------------------------
2948 // text control geometry
2949 // ----------------------------------------------------------------------------
2951 static inline int GetTextBorderWidth()
2956 wxRect
wxWin32Renderer::GetTextTotalArea(const wxTextCtrl
*text
,
2959 wxRect rectTotal
= rect
;
2961 wxCoord widthBorder
= GetTextBorderWidth();
2962 rectTotal
.Inflate(widthBorder
);
2964 // this is what Windows does
2970 wxRect
wxWin32Renderer::GetTextClientArea(const wxTextCtrl
*text
,
2972 wxCoord
*extraSpaceBeyond
)
2974 wxRect rectText
= rect
;
2976 // undo GetTextTotalArea()
2977 if ( rectText
.height
> 0 )
2980 wxCoord widthBorder
= GetTextBorderWidth();
2981 rectText
.Inflate(-widthBorder
);
2983 if ( extraSpaceBeyond
)
2984 *extraSpaceBeyond
= 0;
2989 // ----------------------------------------------------------------------------
2991 // ----------------------------------------------------------------------------
2993 void wxWin32Renderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
2996 if ( wxDynamicCast(window
, wxScrollBar
) )
2998 // we only set the width of vert scrollbars and height of the
3000 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
3001 size
->y
= m_sizeScrollbarArrow
.y
;
3003 size
->x
= m_sizeScrollbarArrow
.x
;
3005 // skip border width adjustments, they don't make sense for us
3008 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
3011 if ( wxDynamicCast(window
, wxButton
) )
3013 if ( !(window
->GetWindowStyle() & wxBU_EXACTFIT
) )
3015 // TODO: don't harcode all this
3016 size
->x
+= 3*window
->GetCharWidth();
3018 wxCoord heightBtn
= (11*(window
->GetCharHeight() + 8))/10;
3019 if ( size
->y
< heightBtn
- 8 )
3020 size
->y
= heightBtn
;
3025 // no border width adjustments for buttons
3028 #endif // wxUSE_BUTTON
3030 // take into account the border width
3031 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
3032 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
3033 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
3036 // ============================================================================
3038 // ============================================================================
3040 // ----------------------------------------------------------------------------
3041 // wxWin32InputHandler
3042 // ----------------------------------------------------------------------------
3044 wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer
*renderer
)
3046 m_renderer
= renderer
;
3049 bool wxWin32InputHandler::HandleKey(wxControl
*control
,
3050 const wxKeyEvent
& event
,
3056 bool wxWin32InputHandler::HandleMouse(wxControl
*control
,
3057 const wxMouseEvent
& event
)
3062 // ----------------------------------------------------------------------------
3063 // wxWin32ScrollBarInputHandler
3064 // ----------------------------------------------------------------------------
3066 wxWin32ScrollBarInputHandler::
3067 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
3068 wxInputHandler
*handler
)
3069 : wxStdScrollBarInputHandler(renderer
, handler
)
3071 m_scrollPaused
= FALSE
;
3075 bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar
*scrollbar
,
3076 const wxControlAction
& action
)
3078 // stop if went beyond the position of the original click (this can only
3079 // happen when we scroll by pages)
3081 if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
3083 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3084 != wxHT_SCROLLBAR_BAR_2
;
3086 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
3088 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3089 != wxHT_SCROLLBAR_BAR_1
;
3094 StopScrolling(scrollbar
);
3096 scrollbar
->Refresh();
3101 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar
, action
);
3104 bool wxWin32ScrollBarInputHandler::HandleMouse(wxControl
*control
,
3105 const wxMouseEvent
& event
)
3107 // remember the current state
3108 bool wasDraggingThumb
= m_htLast
== wxHT_SCROLLBAR_THUMB
;
3110 // do process the message
3111 bool rc
= wxStdScrollBarInputHandler::HandleMouse(control
, event
);
3113 // analyse the changes
3114 if ( !wasDraggingThumb
&& (m_htLast
== wxHT_SCROLLBAR_THUMB
) )
3116 // we just started dragging the thumb, remember its initial position to
3117 // be able to restore it if the drag is cancelled later
3118 m_eventStartDrag
= event
;
3124 bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl
*control
,
3125 const wxMouseEvent
& event
)
3127 // we don't highlight scrollbar elements, so there is no need to process
3128 // mouse move events normally - only do it while mouse is captured (i.e.
3129 // when we're dragging the thumb or pressing on something)
3130 if ( !m_winCapture
)
3133 if ( event
.Entering() )
3135 // we're not interested in this at all
3139 wxScrollBar
*scrollbar
= wxStaticCast(control
, wxScrollBar
);
3141 if ( m_scrollPaused
)
3143 // check if the mouse returned to its original location
3145 if ( event
.Leaving() )
3151 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3152 if ( ht
== m_htLast
)
3154 // yes it did, resume scrolling
3155 m_scrollPaused
= FALSE
;
3156 if ( m_timerScroll
)
3158 // we were scrolling by line/page, restart timer
3159 m_timerScroll
->Start(m_interval
);
3161 Press(scrollbar
, TRUE
);
3163 else // we were dragging the thumb
3165 // restore its last location
3166 HandleThumbMove(scrollbar
, m_eventLastDrag
);
3172 else // normal case, scrolling hasn't been paused
3174 // if we're scrolling the scrollbar because the arrow or the shaft was
3175 // pressed, check that the mouse stays on the same scrollbar element
3177 if ( event
.Moving() )
3179 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3181 else // event.Leaving()
3186 // if we're dragging the thumb and the mouse stays in the scrollbar, it
3187 // is still ok - we only want to catch the case when the mouse leaves
3188 // the scrollbar here
3189 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
&& ht
!= wxHT_NOWHERE
)
3191 ht
= wxHT_SCROLLBAR_THUMB
;
3194 if ( ht
!= m_htLast
)
3196 // what were we doing? 2 possibilities: either an arrow/shaft was
3197 // pressed in which case we have a timer and so we just stop it or
3198 // we were dragging the thumb
3199 if ( m_timerScroll
)
3202 m_interval
= m_timerScroll
->GetInterval();
3203 m_timerScroll
->Stop();
3204 m_scrollPaused
= TRUE
;
3206 // unpress the arrow
3207 Press(scrollbar
, FALSE
);
3209 else // we were dragging the thumb
3211 // remember the current thumb position to be able to restore it
3212 // if the mouse returns to it later
3213 m_eventLastDrag
= event
;
3215 // and restore the original position (before dragging) of the
3217 HandleThumbMove(scrollbar
, m_eventStartDrag
);
3224 return wxStdScrollBarInputHandler::HandleMouseMove(control
, event
);
3227 // ----------------------------------------------------------------------------
3228 // wxWin32CheckboxInputHandler
3229 // ----------------------------------------------------------------------------
3231 bool wxWin32CheckboxInputHandler::HandleKey(wxControl
*control
,
3232 const wxKeyEvent
& event
,
3237 wxControlAction action
;
3238 int keycode
= event
.GetKeyCode();
3242 action
= wxACTION_CHECKBOX_TOGGLE
;
3246 case WXK_NUMPAD_SUBTRACT
:
3247 action
= wxACTION_CHECKBOX_CHECK
;
3251 case WXK_NUMPAD_ADD
:
3252 case WXK_NUMPAD_EQUAL
:
3253 action
= wxACTION_CHECKBOX_CLEAR
;
3259 control
->PerformAction(action
);
3268 // ----------------------------------------------------------------------------
3269 // wxWin32TextCtrlInputHandler
3270 // ----------------------------------------------------------------------------
3272 bool wxWin32TextCtrlInputHandler::HandleKey(wxControl
*control
,
3273 const wxKeyEvent
& event
,
3276 // handle only MSW-specific text bindings here, the others are handled in
3280 int keycode
= event
.GetKeyCode();
3282 wxControlAction action
;
3283 if ( keycode
== WXK_DELETE
&& event
.ShiftDown() )
3285 action
= wxACTION_TEXT_CUT
;
3287 else if ( keycode
== WXK_INSERT
)
3289 if ( event
.ControlDown() )
3290 action
= wxACTION_TEXT_COPY
;
3291 else if ( event
.ShiftDown() )
3292 action
= wxACTION_TEXT_PASTE
;
3295 if ( action
!= wxACTION_NONE
)
3297 control
->PerformAction(action
);
3303 return wxStdTextCtrlInputHandler::HandleKey(control
, event
, pressed
);