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
,
258 wxBitmap
*bmpPressed
,
259 wxBitmap
*bmpDisabled
);
261 virtual void AdjustSize(wxSize
*size
, const wxWindow
*window
);
262 virtual wxRect
GetBorderDimensions(wxBorder border
) const;
263 virtual bool AreScrollbarsInsideBorder() const;
265 virtual wxSize
GetScrollbarArrowSize() const
266 { return m_sizeScrollbarArrow
; }
267 virtual wxRect
GetScrollbarRect(const wxScrollBar
*scrollbar
,
268 wxScrollBar::Element elem
,
269 int thumbPos
= -1) const;
270 virtual wxCoord
GetScrollbarSize(const wxScrollBar
*scrollbar
);
271 virtual wxHitTest
HitTestScrollbar(const wxScrollBar
*scrollbar
,
272 const wxPoint
& pt
) const;
273 virtual wxCoord
ScrollbarToPixel(const wxScrollBar
*scrollbar
,
275 virtual int PixelToScrollbar(const wxScrollBar
*scrollbar
, wxCoord coord
);
276 virtual wxCoord
GetListboxItemHeight(wxCoord fontHeight
)
277 { return fontHeight
+ 2; }
278 virtual wxSize
GetCheckBitmapSize() const
279 { return wxSize(13, 13); }
280 virtual wxSize
GetRadioBitmapSize() const
281 { return wxSize(12, 12); }
282 virtual wxCoord
GetCheckItemMargin() const
285 virtual wxRect
GetTextTotalArea(const wxTextCtrl
*text
,
287 virtual wxRect
GetTextClientArea(const wxTextCtrl
*text
,
289 wxCoord
*extraSpaceBeyond
);
291 virtual wxSize
GetTabIndent() const { return wxSize(2, 2); }
292 virtual wxSize
GetTabPadding() const { return wxSize(6, 5); }
294 virtual wxCoord
GetSliderDim() const { return 20; }
295 virtual wxCoord
GetSliderTickLen() const { return 4; }
296 virtual wxRect
GetSliderShaftRect(const wxRect
& rect
,
297 wxOrientation orient
) const;
298 virtual wxSize
GetSliderThumbSize(const wxRect
& rect
,
299 wxOrientation orient
) const;
300 virtual wxSize
GetProgressBarStep() const { return wxSize(16, 32); }
303 virtual wxSize
GetMenuBarItemSize(const wxSize
& sizeText
) const;
304 virtual wxMenuGeometryInfo
*GetMenuGeometry(wxWindow
*win
,
305 const wxMenu
& menu
) const;
308 // helper of DrawLabel() and DrawCheckOrRadioButton()
309 void DoDrawLabel(wxDC
& dc
,
310 const wxString
& label
,
313 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
315 wxRect
*rectBounds
= NULL
,
316 const wxPoint
& focusOffset
317 = wxPoint(FOCUS_RECT_OFFSET_X
, FOCUS_RECT_OFFSET_Y
));
319 // common part of DrawLabel() and DrawItem()
320 void DrawFocusRect(wxDC
& dc
, const wxRect
& rect
);
322 // DrawLabel() and DrawButtonLabel() helper
323 void DrawLabelShadow(wxDC
& dc
,
324 const wxString
& label
,
329 // DrawButtonBorder() helper
330 void DoDrawBackground(wxDC
& dc
,
334 // DrawBorder() helpers: all of them shift and clip the DC after drawing
337 // just draw a rectangle with the given pen
338 void DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
340 // draw the lower left part of rectangle
341 void DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
343 // draw the rectange using the first brush for the left and top sides and
344 // the second one for the bottom and right ones
345 void DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
346 const wxPen
& pen1
, const wxPen
& pen2
);
348 // draw the normal 3D border
349 void DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
);
351 // draw the sunken 3D border
352 void DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
);
354 // draw the border used for scrollbar arrows
355 void DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
= FALSE
);
357 // public DrawArrow()s helper
358 void DrawArrow(wxDC
& dc
, const wxRect
& rect
,
359 wxArrowDirection arrowDir
, wxArrowStyle arrowStyle
);
361 // DrawArrowButton is used by DrawScrollbar and DrawComboButton
362 void DrawArrowButton(wxDC
& dc
, const wxRect
& rect
,
363 wxArrowDirection arrowDir
,
364 wxArrowStyle arrowStyle
);
366 // DrawCheckButton/DrawRadioButton helper
367 void DrawCheckOrRadioButton(wxDC
& dc
,
368 const wxString
& label
,
369 const wxBitmap
& bitmap
,
374 wxCoord focusOffsetY
);
376 // draw a normal or transposed line (useful for using the same code fo both
377 // horizontal and vertical widgets)
378 void DrawLine(wxDC
& dc
,
379 wxCoord x1
, wxCoord y1
,
380 wxCoord x2
, wxCoord y2
,
381 bool transpose
= FALSE
)
384 dc
.DrawLine(y1
, x1
, y2
, x2
);
386 dc
.DrawLine(x1
, y1
, x2
, y2
);
389 // get the standard check/radio button bitmap
390 wxBitmap
GetIndicator(IndicatorType indType
, int flags
);
391 wxBitmap
GetCheckBitmap(int flags
)
392 { return GetIndicator(IndicatorType_Check
, flags
); }
393 wxBitmap
GetRadioBitmap(int flags
)
394 { return GetIndicator(IndicatorType_Radio
, flags
); }
397 const wxColourScheme
*m_scheme
;
399 // the sizing parameters (TODO make them changeable)
400 wxSize m_sizeScrollbarArrow
;
402 // GDI objects we use for drawing
403 wxColour m_colDarkGrey
,
411 // first row is for the normal state, second - for the disabled
412 wxBitmap m_bmpArrows
[Arrow_StateMax
][Arrow_Max
];
415 // ----------------------------------------------------------------------------
416 // wxWin32InputHandler and derived classes: process the keyboard and mouse
417 // messages according to Windows standards
418 // ----------------------------------------------------------------------------
420 class wxWin32InputHandler
: public wxInputHandler
423 wxWin32InputHandler(wxWin32Renderer
*renderer
);
425 virtual bool HandleKey(wxControl
*control
,
426 const wxKeyEvent
& event
,
428 virtual bool HandleMouse(wxControl
*control
,
429 const wxMouseEvent
& event
);
432 wxWin32Renderer
*m_renderer
;
435 class wxWin32ScrollBarInputHandler
: public wxStdScrollBarInputHandler
438 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
439 wxInputHandler
*handler
);
441 virtual bool HandleMouse(wxControl
*control
, const wxMouseEvent
& event
);
442 virtual bool HandleMouseMove(wxControl
*control
, const wxMouseEvent
& event
);
444 virtual bool OnScrollTimer(wxScrollBar
*scrollbar
,
445 const wxControlAction
& action
);
448 virtual bool IsAllowedButton(int button
) { return button
== 1; }
450 virtual void Highlight(wxScrollBar
*scrollbar
, bool doIt
)
452 // we don't highlight anything
455 // the first and last event which caused the thumb to move
456 wxMouseEvent m_eventStartDrag
,
459 // have we paused the scrolling because the mouse moved?
462 // we remember the interval of the timer to be able to restart it
466 class wxWin32CheckboxInputHandler
: public wxStdCheckboxInputHandler
469 wxWin32CheckboxInputHandler(wxInputHandler
*handler
)
470 : wxStdCheckboxInputHandler(handler
) { }
472 virtual bool HandleKey(wxControl
*control
,
473 const wxKeyEvent
& event
,
477 class wxWin32TextCtrlInputHandler
: public wxStdTextCtrlInputHandler
480 wxWin32TextCtrlInputHandler(wxInputHandler
*handler
)
481 : wxStdTextCtrlInputHandler(handler
) { }
483 virtual bool HandleKey(wxControl
*control
,
484 const wxKeyEvent
& event
,
488 // ----------------------------------------------------------------------------
489 // wxWin32ColourScheme: uses (default) Win32 colours
490 // ----------------------------------------------------------------------------
492 class wxWin32ColourScheme
: public wxColourScheme
495 virtual wxColour
Get(StdColour col
) const;
496 virtual wxColour
GetBackground(wxWindow
*win
) const;
499 // ----------------------------------------------------------------------------
501 // ----------------------------------------------------------------------------
503 WX_DEFINE_ARRAY(wxInputHandler
*, wxArrayHandlers
);
505 class wxWin32Theme
: public wxTheme
509 virtual ~wxWin32Theme();
511 virtual wxRenderer
*GetRenderer() { return m_renderer
; }
512 virtual wxInputHandler
*GetInputHandler(const wxString
& control
);
513 virtual wxColourScheme
*GetColourScheme();
516 // get the default input handler
517 wxInputHandler
*GetDefaultInputHandler();
519 wxWin32Renderer
*m_renderer
;
521 // the names of the already created handlers and the handlers themselves
522 // (these arrays are synchronized)
523 wxSortedArrayString m_handlerNames
;
524 wxArrayHandlers m_handlers
;
526 wxWin32InputHandler
*m_handlerDefault
;
528 wxWin32ColourScheme
*m_scheme
;
530 WX_DECLARE_THEME(win32
)
533 // ----------------------------------------------------------------------------
535 // ----------------------------------------------------------------------------
539 static const char *checked_menu_xpm
[] = {
540 /* columns rows colors chars-per-pixel */
556 static const char *selected_checked_menu_xpm
[] = {
557 /* columns rows colors chars-per-pixel */
573 static const char *disabled_checked_menu_xpm
[] = {
574 /* columns rows colors chars-per-pixel */
591 static const char *selected_disabled_checked_menu_xpm
[] = {
592 /* columns rows colors chars-per-pixel */
608 // checkbox and radiobox bitmaps below
610 static const char *checked_xpm
[] = {
611 /* columns rows colors chars-per-pixel */
634 static const char *pressed_checked_xpm
[] = {
635 /* columns rows colors chars-per-pixel */
657 static const char *pressed_disabled_checked_xpm
[] = {
658 /* columns rows colors chars-per-pixel */
680 static const char *checked_item_xpm
[] = {
681 /* columns rows colors chars-per-pixel */
702 static const char *unchecked_xpm
[] = {
703 /* columns rows colors chars-per-pixel */
726 static const char *pressed_unchecked_xpm
[] = {
727 /* columns rows colors chars-per-pixel */
749 static const char *unchecked_item_xpm
[] = {
750 /* columns rows colors chars-per-pixel */
770 static const char *checked_radio_xpm
[] = {
771 /* columns rows colors chars-per-pixel */
794 static const char *pressed_checked_radio_xpm
[] = {
795 /* columns rows colors chars-per-pixel */
818 static const char *pressed_disabled_checked_radio_xpm
[] = {
819 /* columns rows colors chars-per-pixel */
842 static const char *unchecked_radio_xpm
[] = {
843 /* columns rows colors chars-per-pixel */
866 static const char *pressed_unchecked_radio_xpm
[] = {
867 /* columns rows colors chars-per-pixel */
891 bmpIndicators
[IndicatorType_Max
][IndicatorState_Max
][IndicatorStatus_Max
] =
896 { checked_xpm
, unchecked_xpm
},
899 { pressed_checked_xpm
, pressed_unchecked_xpm
},
902 { pressed_disabled_checked_xpm
, pressed_unchecked_xpm
},
908 { checked_radio_xpm
, unchecked_radio_xpm
},
911 { pressed_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
914 { pressed_disabled_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
920 { checked_menu_xpm
, NULL
},
923 { selected_checked_menu_xpm
, NULL
},
926 { disabled_checked_menu_xpm
, NULL
},
928 // disabled selected state
929 { selected_disabled_checked_menu_xpm
, NULL
},
933 // ============================================================================
935 // ============================================================================
937 WX_IMPLEMENT_THEME(wxWin32Theme
, win32
, wxTRANSLATE("Win32 theme"));
939 // ----------------------------------------------------------------------------
941 // ----------------------------------------------------------------------------
943 wxWin32Theme::wxWin32Theme()
945 m_scheme
= new wxWin32ColourScheme
;
946 m_renderer
= new wxWin32Renderer(m_scheme
);
947 m_handlerDefault
= NULL
;
950 wxWin32Theme::~wxWin32Theme()
952 size_t count
= m_handlers
.GetCount();
953 for ( size_t n
= 0; n
< count
; n
++ )
955 if ( m_handlers
[n
] != m_handlerDefault
)
956 delete m_handlers
[n
];
959 delete m_handlerDefault
;
965 wxInputHandler
*wxWin32Theme::GetDefaultInputHandler()
967 if ( !m_handlerDefault
)
969 m_handlerDefault
= new wxWin32InputHandler(m_renderer
);
972 return m_handlerDefault
;
975 wxInputHandler
*wxWin32Theme::GetInputHandler(const wxString
& control
)
977 wxInputHandler
*handler
;
978 int n
= m_handlerNames
.Index(control
);
979 if ( n
== wxNOT_FOUND
)
981 // create a new handler
982 if ( control
== wxINP_HANDLER_SCROLLBAR
)
983 handler
= new wxWin32ScrollBarInputHandler(m_renderer
,
984 GetDefaultInputHandler());
986 else if ( control
== wxINP_HANDLER_BUTTON
)
987 handler
= new wxStdButtonInputHandler(GetDefaultInputHandler());
988 #endif // wxUSE_BUTTON
990 else if ( control
== wxINP_HANDLER_CHECKBOX
)
991 handler
= new wxWin32CheckboxInputHandler(GetDefaultInputHandler());
992 #endif // wxUSE_CHECKBOX
994 else if ( control
== wxINP_HANDLER_COMBOBOX
)
995 handler
= new wxStdComboBoxInputHandler(GetDefaultInputHandler());
996 #endif // wxUSE_COMBOBOX
998 else if ( control
== wxINP_HANDLER_LISTBOX
)
999 handler
= new wxStdListboxInputHandler(GetDefaultInputHandler());
1000 #endif // wxUSE_LISTBOX
1001 #if wxUSE_CHECKLISTBOX
1002 else if ( control
== wxINP_HANDLER_CHECKLISTBOX
)
1003 handler
= new wxStdCheckListboxInputHandler(GetDefaultInputHandler());
1004 #endif // wxUSE_CHECKLISTBOX
1006 else if ( control
== wxINP_HANDLER_TEXTCTRL
)
1007 handler
= new wxWin32TextCtrlInputHandler(GetDefaultInputHandler());
1008 #endif // wxUSE_TEXTCTRL
1010 else if ( control
== wxINP_HANDLER_SLIDER
)
1011 handler
= new wxStdSliderButtonInputHandler(GetDefaultInputHandler());
1012 #endif // wxUSE_SLIDER
1014 else if ( control
== wxINP_HANDLER_SPINBTN
)
1015 handler
= new wxStdSpinButtonInputHandler(GetDefaultInputHandler());
1016 #endif // wxUSE_SPINBTN
1018 else if ( control
== wxINP_HANDLER_NOTEBOOK
)
1019 handler
= new wxStdNotebookInputHandler(GetDefaultInputHandler());
1020 #endif // wxUSE_NOTEBOOK
1022 handler
= GetDefaultInputHandler();
1024 n
= m_handlerNames
.Add(control
);
1025 m_handlers
.Insert(handler
, n
);
1027 else // we already have it
1029 handler
= m_handlers
[n
];
1035 wxColourScheme
*wxWin32Theme::GetColourScheme()
1040 // ============================================================================
1041 // wxWin32ColourScheme
1042 // ============================================================================
1044 wxColour
wxWin32ColourScheme::GetBackground(wxWindow
*win
) const
1047 if ( win
->UseBgCol() )
1049 // use the user specified colour
1050 col
= win
->GetBackgroundColour();
1053 if ( win
->IsContainerWindow() )
1055 wxTextCtrl
*text
= wxDynamicCast(win
, wxTextCtrl
);
1058 if ( !text
->IsEnabled() ) // not IsEditable()
1060 //else: execute code below
1065 // doesn't depend on the state
1071 int flags
= win
->GetStateFlags();
1073 // the colour set by the user should be used for the normal state
1074 // and for the states for which we don't have any specific colours
1075 if ( !col
.Ok() || (flags
!= 0) )
1077 if ( wxDynamicCast(win
, wxScrollBar
) )
1078 col
= Get(flags
& wxCONTROL_PRESSED
? SCROLLBAR_PRESSED
1088 wxColour
wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col
) const
1092 case WINDOW
: return *wxWHITE
;
1094 // use the system colours under Windows
1095 #if defined(__WXMSW__)
1096 case WINDOW
: return wxColour(GetSysColor(COLOR_WINDOW
));
1098 case CONTROL_PRESSED
:
1099 case CONTROL_CURRENT
:
1100 case CONTROL
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1102 case CONTROL_TEXT
: return wxColour(GetSysColor(COLOR_BTNTEXT
));
1104 case SCROLLBAR
: return wxColour(GetSysColor(COLOR_SCROLLBAR
));
1105 case SCROLLBAR_PRESSED
: return wxColour(GetSysColor(COLOR_HIGHLIGHT
));
1107 case HIGHLIGHT
: return wxColour(GetSysColor(COLOR_HIGHLIGHT
));
1108 case HIGHLIGHT_TEXT
: return wxColour(GetSysColor(COLOR_HIGHLIGHTTEXT
));
1110 #if defined(COLOR_3DDKSHADOW)
1111 case SHADOW_DARK
: return wxColour(GetSysColor(COLOR_3DDKSHADOW
));
1113 case SHADOW_DARK
: return *wxBLACK
;
1116 case CONTROL_TEXT_DISABLED
:
1117 case SHADOW_HIGHLIGHT
: return wxColour(GetSysColor(COLOR_BTNHIGHLIGHT
));
1119 case SHADOW_IN
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1121 case CONTROL_TEXT_DISABLED_SHADOW
:
1122 case SHADOW_OUT
: return wxColour(GetSysColor(COLOR_BTNSHADOW
));
1124 // use the standard Windows colours elsewhere
1125 case CONTROL_PRESSED
:
1126 case CONTROL_CURRENT
:
1127 case CONTROL
: return wxColour(0xc0c0c0);
1129 case CONTROL_TEXT
: return *wxBLACK
;
1131 case SCROLLBAR
: return wxColour(0xe0e0e0);
1132 case SCROLLBAR_PRESSED
: return *wxBLACK
;
1134 case HIGHLIGHT
: return wxColour(0x800000);
1135 case HIGHLIGHT_TEXT
: return wxColour(0xffffff);
1137 case SHADOW_DARK
: return *wxBLACK
;
1139 case CONTROL_TEXT_DISABLED
:
1140 case SHADOW_HIGHLIGHT
: return wxColour(0xe0e0e0);
1142 case SHADOW_IN
: return wxColour(0xc0c0c0);
1144 case CONTROL_TEXT_DISABLED_SHADOW
:
1145 case SHADOW_OUT
: return wxColour(0x7f7f7f);
1150 wxFAIL_MSG(_T("invalid standard colour"));
1155 // ============================================================================
1157 // ============================================================================
1159 // ----------------------------------------------------------------------------
1161 // ----------------------------------------------------------------------------
1163 wxWin32Renderer::wxWin32Renderer(const wxColourScheme
*scheme
)
1167 m_sizeScrollbarArrow
= wxSize(16, 16);
1169 // init colours and pens
1170 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
), 0, wxSOLID
);
1172 m_colDarkGrey
= wxSCHEME_COLOUR(scheme
, SHADOW_OUT
);
1173 m_penDarkGrey
= wxPen(m_colDarkGrey
, 0, wxSOLID
);
1175 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
), 0, wxSOLID
);
1177 m_colHighlight
= wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
);
1178 m_penHighlight
= wxPen(m_colHighlight
, 0, wxSOLID
);
1180 // init the arrow bitmaps
1181 static const size_t ARROW_WIDTH
= 7;
1182 static const size_t ARROW_LENGTH
= 4;
1185 wxMemoryDC dcNormal
,
1188 for ( size_t n
= 0; n
< Arrow_Max
; n
++ )
1190 bool isVertical
= n
> Arrow_Right
;
1203 // disabled arrow is larger because of the shadow
1204 m_bmpArrows
[Arrow_Normal
][n
].Create(w
, h
);
1205 m_bmpArrows
[Arrow_Disabled
][n
].Create(w
+ 1, h
+ 1);
1207 dcNormal
.SelectObject(m_bmpArrows
[Arrow_Normal
][n
]);
1208 dcDisabled
.SelectObject(m_bmpArrows
[Arrow_Disabled
][n
]);
1210 dcNormal
.SetBackground(*wxWHITE_BRUSH
);
1211 dcDisabled
.SetBackground(*wxWHITE_BRUSH
);
1215 dcNormal
.SetPen(m_penBlack
);
1216 dcDisabled
.SetPen(m_penDarkGrey
);
1218 // calculate the position of the point of the arrow
1222 x1
= (ARROW_WIDTH
- 1)/2;
1223 y1
= n
== Arrow_Up
? 0 : ARROW_LENGTH
- 1;
1227 x1
= n
== Arrow_Left
? 0 : ARROW_LENGTH
- 1;
1228 y1
= (ARROW_WIDTH
- 1)/2;
1239 for ( size_t i
= 0; i
< ARROW_LENGTH
; i
++ )
1241 dcNormal
.DrawLine(x1
, y1
, x2
, y2
);
1242 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1249 if ( n
== Arrow_Up
)
1260 else // left or right arrow
1265 if ( n
== Arrow_Left
)
1278 // draw the shadow for the disabled one
1279 dcDisabled
.SetPen(m_penHighlight
);
1284 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1288 x1
= ARROW_LENGTH
- 1;
1289 y1
= (ARROW_WIDTH
- 1)/2 + 1;
1292 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1293 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1298 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1302 x1
= ARROW_WIDTH
- 1;
1304 x2
= (ARROW_WIDTH
- 1)/2;
1306 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1307 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1312 // create the inversed bitmap but only for the right arrow as we only
1313 // use it for the menus
1314 if ( n
== Arrow_Right
)
1316 m_bmpArrows
[Arrow_Inversed
][n
].Create(w
, h
);
1317 dcInverse
.SelectObject(m_bmpArrows
[Arrow_Inversed
][n
]);
1319 dcInverse
.Blit(0, 0, w
, h
,
1322 dcInverse
.SelectObject(wxNullBitmap
);
1324 mask
= new wxMask(m_bmpArrows
[Arrow_Inversed
][n
], *wxBLACK
);
1325 m_bmpArrows
[Arrow_Inversed
][n
].SetMask(mask
);
1327 m_bmpArrows
[Arrow_InversedDisabled
][n
].Create(w
, h
);
1328 dcInverse
.SelectObject(m_bmpArrows
[Arrow_InversedDisabled
][n
]);
1330 dcInverse
.Blit(0, 0, w
, h
,
1333 dcInverse
.SelectObject(wxNullBitmap
);
1335 mask
= new wxMask(m_bmpArrows
[Arrow_InversedDisabled
][n
], *wxBLACK
);
1336 m_bmpArrows
[Arrow_InversedDisabled
][n
].SetMask(mask
);
1339 dcNormal
.SelectObject(wxNullBitmap
);
1340 dcDisabled
.SelectObject(wxNullBitmap
);
1342 mask
= new wxMask(m_bmpArrows
[Arrow_Normal
][n
], *wxWHITE
);
1343 m_bmpArrows
[Arrow_Normal
][n
].SetMask(mask
);
1344 mask
= new wxMask(m_bmpArrows
[Arrow_Disabled
][n
], *wxWHITE
);
1345 m_bmpArrows
[Arrow_Disabled
][n
].SetMask(mask
);
1347 m_bmpArrows
[Arrow_Pressed
][n
] = m_bmpArrows
[Arrow_Normal
][n
];
1351 // ----------------------------------------------------------------------------
1353 // ----------------------------------------------------------------------------
1356 The raised border in Win32 looks like this:
1358 IIIIIIIIIIIIIIIIIIIIIIB
1360 I GB I = white (HILIGHT)
1361 I GB H = light grey (LIGHT)
1362 I GB G = dark grey (SHADOI)
1363 I GB B = black (DKSHADOI)
1364 I GB I = hIghlight (COLOR_3DHILIGHT)
1366 IGGGGGGGGGGGGGGGGGGGGGB
1367 BBBBBBBBBBBBBBBBBBBBBBB
1369 The sunken border looks like this:
1371 GGGGGGGGGGGGGGGGGGGGGGI
1372 GBBBBBBBBBBBBBBBBBBBBHI
1379 GHHHHHHHHHHHHHHHHHHHHHI
1380 IIIIIIIIIIIIIIIIIIIIIII
1382 The static border (used for the controls which don't get focus) is like
1385 GGGGGGGGGGGGGGGGGGGGGGW
1393 WWWWWWWWWWWWWWWWWWWWWWW
1395 The most complicated is the double border:
1397 HHHHHHHHHHHHHHHHHHHHHHB
1398 HWWWWWWWWWWWWWWWWWWWWGB
1399 HWHHHHHHHHHHHHHHHHHHHGB
1404 HWHHHHHHHHHHHHHHHHHHHGB
1405 HGGGGGGGGGGGGGGGGGGGGGB
1406 BBBBBBBBBBBBBBBBBBBBBBB
1408 And the simple border is, well, simple:
1410 BBBBBBBBBBBBBBBBBBBBBBB
1419 BBBBBBBBBBBBBBBBBBBBBBB
1422 void wxWin32Renderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1426 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1427 dc
.DrawRectangle(*rect
);
1433 void wxWin32Renderer::DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1435 // draw the bottom and right sides
1437 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1438 rect
->GetRight() + 1, rect
->GetBottom());
1439 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1440 rect
->GetRight(), rect
->GetBottom());
1447 void wxWin32Renderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
1448 const wxPen
& pen1
, const wxPen
& pen2
)
1450 // draw the rectangle
1452 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
1453 rect
->GetLeft(), rect
->GetBottom());
1454 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
1455 rect
->GetRight(), rect
->GetTop());
1457 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1458 rect
->GetRight(), rect
->GetBottom());
1459 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1460 rect
->GetRight() + 1, rect
->GetBottom());
1466 void wxWin32Renderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
1468 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
1469 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
1472 void wxWin32Renderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
1474 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
1475 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
1478 void wxWin32Renderer::DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
)
1482 DrawRect(dc
, rect
, m_penDarkGrey
);
1484 // the arrow is usually drawn inside border of width 2 and is offset by
1485 // another pixel in both directions when it's pressed - as the border
1486 // in this case is more narrow as well, we have to adjust rect like
1494 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
1495 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
1499 void wxWin32Renderer::DrawBorder(wxDC
& dc
,
1501 const wxRect
& rectTotal
,
1502 int WXUNUSED(flags
),
1507 wxRect rect
= rectTotal
;
1511 case wxBORDER_SUNKEN
:
1512 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1514 DrawSunkenBorder(dc
, &rect
);
1518 case wxBORDER_STATIC
:
1519 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1522 case wxBORDER_RAISED
:
1523 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1525 DrawRaisedBorder(dc
, &rect
);
1529 case wxBORDER_DOUBLE
:
1530 DrawArrowBorder(dc
, &rect
);
1531 DrawRect(dc
, &rect
, m_penLightGrey
);
1534 case wxBORDER_SIMPLE
:
1535 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1537 DrawRect(dc
, &rect
, m_penBlack
);
1542 wxFAIL_MSG(_T("unknown border type"));
1545 case wxBORDER_DEFAULT
:
1554 wxRect
wxWin32Renderer::GetBorderDimensions(wxBorder border
) const
1559 case wxBORDER_RAISED
:
1560 case wxBORDER_SUNKEN
:
1561 width
= BORDER_THICKNESS
;
1564 case wxBORDER_SIMPLE
:
1565 case wxBORDER_STATIC
:
1569 case wxBORDER_DOUBLE
:
1574 wxFAIL_MSG(_T("unknown border type"));
1577 case wxBORDER_DEFAULT
:
1587 rect
.height
= width
;
1592 bool wxWin32Renderer::AreScrollbarsInsideBorder() const
1597 // ----------------------------------------------------------------------------
1599 // ----------------------------------------------------------------------------
1601 void wxWin32Renderer::DrawTextBorder(wxDC
& dc
,
1607 // text controls are not special under windows
1608 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
1611 void wxWin32Renderer::DrawButtonBorder(wxDC
& dc
,
1612 const wxRect
& rectTotal
,
1616 wxRect rect
= rectTotal
;
1618 if ( flags
& wxCONTROL_PRESSED
)
1620 // button pressed: draw a double border around it
1621 DrawRect(dc
, &rect
, m_penBlack
);
1622 DrawRect(dc
, &rect
, m_penDarkGrey
);
1626 // button not pressed
1628 if ( flags
& (wxCONTROL_FOCUSED
| wxCONTROL_ISDEFAULT
) )
1630 // button either default or focused (or both): add an extra border around it
1631 DrawRect(dc
, &rect
, m_penBlack
);
1634 // now draw a normal button
1635 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penBlack
);
1636 DrawHalfRect(dc
, &rect
, m_penDarkGrey
);
1645 // ----------------------------------------------------------------------------
1647 // ----------------------------------------------------------------------------
1649 void wxWin32Renderer::DrawHorizontalLine(wxDC
& dc
,
1650 wxCoord y
, wxCoord x1
, wxCoord x2
)
1652 dc
.SetPen(m_penDarkGrey
);
1653 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1654 dc
.SetPen(m_penHighlight
);
1656 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1659 void wxWin32Renderer::DrawVerticalLine(wxDC
& dc
,
1660 wxCoord x
, wxCoord y1
, wxCoord y2
)
1662 dc
.SetPen(m_penDarkGrey
);
1663 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1664 dc
.SetPen(m_penHighlight
);
1666 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1669 void wxWin32Renderer::DrawFrame(wxDC
& dc
,
1670 const wxString
& label
,
1676 wxCoord height
= 0; // of the label
1677 wxRect rectFrame
= rect
;
1678 if ( !label
.empty() )
1680 // the text should touch the top border of the rect, so the frame
1681 // itself should be lower
1682 dc
.GetTextExtent(label
, NULL
, &height
);
1683 rectFrame
.y
+= height
/ 2;
1684 rectFrame
.height
-= height
/ 2;
1686 // we have to draw each part of the frame individually as we can't
1687 // erase the background beyond the label as it might contain some
1688 // pixmap already, so drawing everything and then overwriting part of
1689 // the frame with label doesn't work
1691 // TODO: the +5 and space insertion should be customizable
1694 rectText
.x
= rectFrame
.x
+ 5;
1695 rectText
.y
= rect
.y
;
1696 rectText
.width
= rectFrame
.width
- 7; // +2 border width
1697 rectText
.height
= height
;
1700 label2
<< _T(' ') << label
<< _T(' ');
1701 if ( indexAccel
!= -1 )
1703 // adjust it as we prepended a space
1708 DrawLabel(dc
, label2
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
1710 StandardDrawFrame(dc
, rectFrame
, rectLabel
);
1714 // just draw the complete frame
1715 DrawShadedRect(dc
, &rectFrame
, m_penDarkGrey
, m_penHighlight
);
1716 DrawShadedRect(dc
, &rectFrame
, m_penHighlight
, m_penDarkGrey
);
1720 // ----------------------------------------------------------------------------
1722 // ----------------------------------------------------------------------------
1724 void wxWin32Renderer::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
1726 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
1727 // pixels each while we really need dots here... PS_ALTERNATE might
1728 // work, but it is for NT 5 only
1730 DrawRect(dc
, &rect
, wxPen(*wxBLACK
, 0, wxDOT
));
1732 // draw the pixels manually: note that to behave in the same manner as
1733 // DrawRect(), we must exclude the bottom and right borders from the
1735 wxCoord x1
= rect
.GetLeft(),
1737 x2
= rect
.GetRight(),
1738 y2
= rect
.GetBottom();
1740 dc
.SetPen(wxPen(*wxBLACK
, 0, wxSOLID
));
1742 // this seems to be closer than what Windows does than wxINVERT although
1743 // I'm still not sure if it's correct
1744 dc
.SetLogicalFunction(wxAND_REVERSE
);
1747 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
1748 dc
.DrawPoint(z
, rect
.GetTop());
1750 wxCoord shift
= z
== x2
? 0 : 1;
1751 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
1752 dc
.DrawPoint(x2
, z
);
1754 shift
= z
== y2
? 0 : 1;
1755 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
1756 dc
.DrawPoint(z
, y2
);
1758 shift
= z
== x1
? 0 : 1;
1759 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
1760 dc
.DrawPoint(x1
, z
);
1762 dc
.SetLogicalFunction(wxCOPY
);
1766 void wxWin32Renderer::DrawLabelShadow(wxDC
& dc
,
1767 const wxString
& label
,
1772 // draw shadow of the text
1773 dc
.SetTextForeground(m_colHighlight
);
1774 wxRect rectShadow
= rect
;
1777 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
1779 // make the text grey
1780 dc
.SetTextForeground(m_colDarkGrey
);
1783 void wxWin32Renderer::DrawLabel(wxDC
& dc
,
1784 const wxString
& label
,
1791 DoDrawLabel(dc
, label
, rect
, flags
, alignment
, indexAccel
, rectBounds
);
1794 void wxWin32Renderer::DoDrawLabel(wxDC
& dc
,
1795 const wxString
& label
,
1801 const wxPoint
& focusOffset
)
1803 // the underscores are not drawn for focused controls in wxMSW
1804 if ( flags
& wxCONTROL_FOCUSED
)
1809 if ( flags
& wxCONTROL_DISABLED
)
1811 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
1812 // currently only can happen for a menu item and it seems that Windows
1813 // doesn't draw the shadow in this case, so we don't do it neither
1814 if ( flags
& wxCONTROL_SELECTED
)
1816 // just make the label text greyed out
1817 dc
.SetTextForeground(m_colDarkGrey
);
1819 else // draw normal disabled label
1821 DrawLabelShadow(dc
, label
, rect
, alignment
, indexAccel
);
1826 dc
.DrawLabel(label
, wxNullBitmap
, rect
, alignment
, indexAccel
, &rectLabel
);
1828 if ( flags
& wxCONTROL_DISABLED
)
1830 // restore the fg colour
1831 dc
.SetTextForeground(*wxBLACK
);
1834 if ( flags
& wxCONTROL_FOCUSED
)
1836 if ( focusOffset
.x
|| focusOffset
.y
)
1838 rectLabel
.Inflate(focusOffset
.x
, focusOffset
.y
);
1841 DrawFocusRect(dc
, rectLabel
);
1845 *rectBounds
= rectLabel
;
1848 void wxWin32Renderer::DrawButtonLabel(wxDC
& dc
,
1849 const wxString
& label
,
1850 const wxBitmap
& image
,
1857 // the underscores are not drawn for focused controls in wxMSW
1858 if ( flags
& wxCONTROL_PRESSED
)
1863 wxRect rectLabel
= rect
;
1864 if ( !label
.empty() )
1866 // shift the label if a button is pressed
1867 if ( flags
& wxCONTROL_PRESSED
)
1873 if ( flags
& wxCONTROL_DISABLED
)
1875 DrawLabelShadow(dc
, label
, rectLabel
, alignment
, indexAccel
);
1878 // leave enough space for the focus rectangle
1879 if ( flags
& wxCONTROL_FOCUSED
)
1881 rectLabel
.Inflate(-2);
1885 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
1887 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
1889 if ( flags
& wxCONTROL_PRESSED
)
1891 // the focus rectangle is never pressed, so undo the shift done
1899 DrawFocusRect(dc
, rectLabel
);
1903 // ----------------------------------------------------------------------------
1904 // (check)listbox items
1905 // ----------------------------------------------------------------------------
1907 void wxWin32Renderer::DrawItem(wxDC
& dc
,
1908 const wxString
& label
,
1912 wxDCTextColourChanger
colChanger(dc
);
1914 if ( flags
& wxCONTROL_SELECTED
)
1916 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
1918 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
1919 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
1920 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
1921 dc
.DrawRectangle(rect
);
1924 wxRect rectText
= rect
;
1926 rectText
.width
-= 2;
1927 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
1929 if ( flags
& wxCONTROL_FOCUSED
)
1931 DrawFocusRect(dc
, rect
);
1935 void wxWin32Renderer::DrawCheckItem(wxDC
& dc
,
1936 const wxString
& label
,
1937 const wxBitmap
& bitmap
,
1946 else // use default bitmap
1948 bmp
= wxBitmap(flags
& wxCONTROL_CHECKED
? checked_item_xpm
1949 : unchecked_item_xpm
);
1952 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2 - 1,
1953 TRUE
/* use mask */);
1955 wxRect rectLabel
= rect
;
1956 int bmpWidth
= bmp
.GetWidth();
1957 rectLabel
.x
+= bmpWidth
;
1958 rectLabel
.width
-= bmpWidth
;
1960 DrawItem(dc
, label
, rectLabel
, flags
);
1963 // ----------------------------------------------------------------------------
1964 // check/radio buttons
1965 // ----------------------------------------------------------------------------
1967 wxBitmap
wxWin32Renderer::GetIndicator(IndicatorType indType
, int flags
)
1969 IndicatorState indState
;
1970 if ( flags
& wxCONTROL_SELECTED
)
1971 indState
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
1972 : IndicatorState_Selected
;
1973 else if ( flags
& wxCONTROL_DISABLED
)
1974 indState
= IndicatorState_Disabled
;
1975 else if ( flags
& wxCONTROL_PRESSED
)
1976 indState
= IndicatorState_Pressed
;
1978 indState
= IndicatorState_Normal
;
1980 IndicatorStatus indStatus
= flags
& wxCONTROL_CHECKED
1981 ? IndicatorStatus_Checked
1982 : IndicatorStatus_Unchecked
;
1984 const char **xpm
= bmpIndicators
[indType
][indState
][indStatus
];
1985 return xpm
? wxBitmap(xpm
) : wxNullBitmap
;
1988 void wxWin32Renderer::DrawCheckOrRadioButton(wxDC
& dc
,
1989 const wxString
& label
,
1990 const wxBitmap
& bitmap
,
1995 wxCoord focusOffsetY
)
1997 // calculate the position of the bitmap and of the label
1998 wxCoord heightBmp
= bitmap
.GetHeight();
2000 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
2003 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
2004 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
2006 // align label vertically with the bitmap - looks nicer like this
2007 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
2009 // calc horz position
2010 if ( align
== wxALIGN_RIGHT
)
2012 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
2013 rectLabel
.x
= rect
.x
+ 3;
2014 rectLabel
.SetRight(xBmp
);
2016 else // normal (checkbox to the left of the text) case
2019 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
2020 rectLabel
.SetRight(rect
.GetRight());
2023 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, TRUE
/* use mask */);
2026 dc
, label
, rectLabel
,
2028 wxALIGN_LEFT
| wxALIGN_TOP
,
2030 NULL
, // we don't need bounding rect
2031 // use custom vert focus rect offset
2032 wxPoint(FOCUS_RECT_OFFSET_X
, focusOffsetY
)
2036 void wxWin32Renderer::DrawRadioButton(wxDC
& dc
,
2037 const wxString
& label
,
2038 const wxBitmap
& bitmap
,
2044 DrawCheckOrRadioButton(dc
, label
,
2045 bitmap
.Ok() ? bitmap
: GetRadioBitmap(flags
),
2046 rect
, flags
, align
, indexAccel
,
2047 FOCUS_RECT_OFFSET_Y
); // default focus rect offset
2050 void wxWin32Renderer::DrawCheckButton(wxDC
& dc
,
2051 const wxString
& label
,
2052 const wxBitmap
& bitmap
,
2058 DrawCheckOrRadioButton(dc
, label
,
2059 bitmap
.Ok() ? bitmap
: GetCheckBitmap(flags
),
2060 rect
, flags
, align
, indexAccel
,
2061 0); // no focus rect offset for checkboxes
2064 // ----------------------------------------------------------------------------
2066 // ----------------------------------------------------------------------------
2068 void wxWin32Renderer::DrawTextLine(wxDC
& dc
,
2069 const wxString
& text
,
2075 // nothing special to do here
2076 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
2079 void wxWin32Renderer::DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
)
2081 // we don't draw them
2084 // ----------------------------------------------------------------------------
2086 // ----------------------------------------------------------------------------
2088 void wxWin32Renderer::DrawTab(wxDC
& dc
,
2089 const wxRect
& rectOrig
,
2091 const wxString
& label
,
2092 const wxBitmap
& bitmap
,
2096 wxRect rect
= rectOrig
;
2098 // the current tab is drawn indented (to the top for default case) and
2099 // bigger than the other ones
2100 const wxSize indent
= GetTabIndent();
2101 if ( flags
& wxCONTROL_SELECTED
)
2106 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2110 rect
.Inflate(indent
.x
, 0);
2112 rect
.height
+= indent
.y
;
2116 rect
.Inflate(indent
.x
, 0);
2117 rect
.height
+= indent
.y
;
2122 wxFAIL_MSG(_T("TODO"));
2127 // draw the text, image and the focus around them (if necessary)
2128 wxRect rectLabel
= rect
;
2129 rectLabel
.Deflate(1, 1);
2130 DrawButtonLabel(dc
, label
, bitmap
, rectLabel
,
2131 flags
, wxALIGN_CENTRE
, indexAccel
);
2133 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2134 static const wxCoord CUTOFF
= 2; // radius of the rounded corner
2137 x2
= rect
.GetRight(),
2138 y2
= rect
.GetBottom();
2140 // FIXME: all this code will break if the tab indent or the border width,
2141 // it is tied to the fact that both of them are equal to 2
2146 dc
.SetPen(m_penHighlight
);
2147 dc
.DrawLine(x
, y2
, x
, y
+ CUTOFF
);
2148 dc
.DrawLine(x
, y
+ CUTOFF
, x
+ CUTOFF
, y
);
2149 dc
.DrawLine(x
+ CUTOFF
, y
, x2
- CUTOFF
+ 1, y
);
2151 dc
.SetPen(m_penBlack
);
2152 dc
.DrawLine(x2
, y2
, x2
, y
+ CUTOFF
);
2153 dc
.DrawLine(x2
, y
+ CUTOFF
, x2
- CUTOFF
, y
);
2155 dc
.SetPen(m_penDarkGrey
);
2156 dc
.DrawLine(x2
- 1, y2
, x2
- 1, y
+ CUTOFF
- 1);
2158 if ( flags
& wxCONTROL_SELECTED
)
2160 dc
.SetPen(m_penLightGrey
);
2162 // overwrite the part of the border below this tab
2163 dc
.DrawLine(x
+ 1, y2
+ 1, x2
- 1, y2
+ 1);
2165 // and the shadow of the tab to the left of us
2166 dc
.DrawLine(x
+ 1, y
+ CUTOFF
+ 1, x
+ 1, y2
+ 1);
2171 dc
.SetPen(m_penHighlight
);
2172 // we need to continue one pixel further to overwrite the corner of
2173 // the border for the selected tab
2174 dc
.DrawLine(x
, y
- (flags
& wxCONTROL_SELECTED
? 1 : 0),
2176 dc
.DrawLine(x
, y2
- CUTOFF
, x
+ CUTOFF
, y2
);
2178 dc
.SetPen(m_penBlack
);
2179 dc
.DrawLine(x
+ CUTOFF
, y2
, x2
- CUTOFF
+ 1, y2
);
2180 dc
.DrawLine(x2
, y
, x2
, y2
- CUTOFF
);
2181 dc
.DrawLine(x2
, y2
- CUTOFF
, x2
- CUTOFF
, y2
);
2183 dc
.SetPen(m_penDarkGrey
);
2184 dc
.DrawLine(x
+ CUTOFF
, y2
- 1, x2
- CUTOFF
+ 1, y2
- 1);
2185 dc
.DrawLine(x2
- 1, y
, x2
- 1, y2
- CUTOFF
+ 1);
2187 if ( flags
& wxCONTROL_SELECTED
)
2189 dc
.SetPen(m_penLightGrey
);
2191 // overwrite the part of the (double!) border above this tab
2192 dc
.DrawLine(x
+ 1, y
- 1, x2
- 1, y
- 1);
2193 dc
.DrawLine(x
+ 1, y
- 2, x2
- 1, y
- 2);
2195 // and the shadow of the tab to the left of us
2196 dc
.DrawLine(x
+ 1, y2
- CUTOFF
, x
+ 1, y
- 1);
2202 wxFAIL_MSG(_T("TODO"));
2206 // ----------------------------------------------------------------------------
2208 // ----------------------------------------------------------------------------
2210 wxSize
wxWin32Renderer::GetSliderThumbSize(const wxRect
& rect
,
2211 wxOrientation orient
) const
2215 wxRect rectShaft
= GetSliderShaftRect(rect
, orient
);
2216 if ( orient
== wxHORIZONTAL
)
2218 size
.y
= rect
.height
- 6;
2219 size
.x
= wxMin(size
.y
/ 2, rectShaft
.width
);
2223 size
.x
= rect
.width
- 6;
2224 size
.y
= wxMin(size
.x
/ 2, rectShaft
.height
);
2230 wxRect
wxWin32Renderer::GetSliderShaftRect(const wxRect
& rectOrig
,
2231 wxOrientation orient
) const
2233 static const wxCoord SLIDER_MARGIN
= 6;
2235 wxRect rect
= rectOrig
;
2237 if ( orient
== wxHORIZONTAL
)
2239 // make the rect of minimal width and centre it
2240 rect
.height
= 2*BORDER_THICKNESS
;
2241 rect
.y
= rectOrig
.y
+ (rectOrig
.height
- rect
.height
) / 2;
2245 // leave margins on the sides
2246 rect
.Deflate(SLIDER_MARGIN
, 0);
2250 // same as above but in other direction
2251 rect
.width
= 2*BORDER_THICKNESS
;
2252 rect
.x
= rectOrig
.x
+ (rectOrig
.width
- rect
.width
) / 2;
2256 rect
.Deflate(0, SLIDER_MARGIN
);
2262 void wxWin32Renderer::DrawSliderShaft(wxDC
& dc
,
2263 const wxRect
& rectOrig
,
2264 wxOrientation orient
,
2268 if ( flags
& wxCONTROL_FOCUSED
)
2270 DrawFocusRect(dc
, rectOrig
);
2273 wxRect rect
= GetSliderShaftRect(rectOrig
, orient
);
2278 DrawSunkenBorder(dc
, &rect
);
2281 void wxWin32Renderer::DrawSliderThumb(wxDC
& dc
,
2283 wxOrientation orient
,
2287 we are drawing a shape of this form
2292 H DB where H is hightlight colour
2305 The interior of this shape is filled with the hatched brush if the thumb
2309 DrawBackground(dc
, wxNullColour
, rect
, flags
);
2311 bool transpose
= orient
== wxVERTICAL
;
2313 wxCoord x
, y
, x2
, y2
;
2318 x2
= rect
.GetBottom();
2319 y2
= rect
.GetRight();
2325 x2
= rect
.GetRight();
2326 y2
= rect
.GetBottom();
2329 // the size of the pointed part of the thumb
2330 wxCoord sizeArrow
= (transpose
? rect
.height
: rect
.width
) / 2;
2332 wxCoord x3
= x
+ sizeArrow
,
2333 y3
= y2
- sizeArrow
;
2335 dc
.SetPen(m_penHighlight
);
2336 DrawLine(dc
, x
, y
, x2
, y
, transpose
);
2337 DrawLine(dc
, x
, y
+ 1, x
, y2
- sizeArrow
, transpose
);
2338 DrawLine(dc
, x
, y3
, x3
, y2
, transpose
);
2340 dc
.SetPen(m_penBlack
);
2341 DrawLine(dc
, x3
, y2
, x2
, y3
, transpose
);
2342 DrawLine(dc
, x2
, y3
, x2
, y
- 1, transpose
);
2344 dc
.SetPen(m_penDarkGrey
);
2345 DrawLine(dc
, x3
, y2
- 1, x2
- 1, y3
, transpose
);
2346 DrawLine(dc
, x2
- 1, y3
, x2
- 1, y
, transpose
);
2348 if ( flags
& wxCONTROL_PRESSED
)
2350 // TODO: MSW fills the entire area inside, not just the rect
2351 wxRect rectInt
= rect
;
2353 rectInt
.SetRight(y3
);
2355 rectInt
.SetBottom(y3
);
2358 static const char *stipple_xpm
[] = {
2359 /* columns rows colors chars-per-pixel */
2367 dc
.SetBrush(wxBrush(stipple_xpm
));
2369 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, SHADOW_HIGHLIGHT
));
2370 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, CONTROL
));
2371 dc
.SetPen(*wxTRANSPARENT_PEN
);
2372 dc
.DrawRectangle(rectInt
);
2376 void wxWin32Renderer::DrawSliderTicks(wxDC
& dc
,
2378 const wxSize
& sizeThumb
,
2379 wxOrientation orient
,
2391 // the variable names correspond to horizontal case, but they can be used
2392 // for both orientations
2393 wxCoord x1
, x2
, y1
, y2
, len
, widthThumb
;
2394 if ( orient
== wxHORIZONTAL
)
2396 x1
= rect
.GetLeft();
2397 x2
= rect
.GetRight();
2399 // draw from bottom to top to leave one pixel space between the ticks
2400 // and the slider as Windows do
2401 y1
= rect
.GetBottom();
2406 widthThumb
= sizeThumb
.x
;
2411 x2
= rect
.GetBottom();
2413 y1
= rect
.GetRight();
2414 y2
= rect
.GetLeft();
2418 widthThumb
= sizeThumb
.y
;
2421 // the first tick should be positioned in such way that a thumb drawn in
2422 // the first position points down directly to it
2423 x1
+= widthThumb
/ 2;
2424 x2
-= widthThumb
/ 2;
2426 // this also means that we have slightly less space for the ticks in
2427 // between the first and the last
2430 dc
.SetPen(m_penBlack
);
2432 int range
= end
- start
;
2433 for ( int n
= 0; n
< range
; n
+= step
)
2435 wxCoord x
= x1
+ (len
*n
) / range
;
2437 DrawLine(dc
, x
, y1
, x
, y2
, orient
== wxVERTICAL
);
2440 // always draw the line at the end position
2441 DrawLine(dc
, x2
, y1
, x2
, y2
, orient
== wxVERTICAL
);
2444 // ----------------------------------------------------------------------------
2446 // ----------------------------------------------------------------------------
2450 // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2451 class WXDLLEXPORT wxWin32MenuGeometryInfo
: public wxMenuGeometryInfo
2454 virtual wxSize
GetSize() const { return m_size
; }
2456 wxCoord
GetLabelOffset() const { return m_ofsLabel
; }
2457 wxCoord
GetAccelOffset() const { return m_ofsAccel
; }
2459 wxCoord
GetItemHeight() const { return m_heightItem
; }
2462 // the total size of the menu
2465 // the offset of the start of the menu item label
2468 // the offset of the start of the accel label
2471 // the height of a normal (not separator) item
2472 wxCoord m_heightItem
;
2474 friend wxMenuGeometryInfo
*wxWin32Renderer::
2475 GetMenuGeometry(wxWindow
*, const wxMenu
&) const;
2478 #endif // wxUSE_MENUS
2480 // FIXME: all constants are hardcoded but shouldn't be
2481 static const wxCoord MENU_LEFT_MARGIN
= 9;
2482 static const wxCoord MENU_RIGHT_MARGIN
= 18;
2483 static const wxCoord MENU_VERT_MARGIN
= 3;
2485 // the margin around bitmap/check marks (on each side)
2486 static const wxCoord MENU_BMP_MARGIN
= 2;
2488 // the margin between the labels and accel strings
2489 static const wxCoord MENU_ACCEL_MARGIN
= 8;
2491 // the separator height in pixels: in fact, strangely enough, the real height
2492 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2494 static const wxCoord MENU_SEPARATOR_HEIGHT
= 3;
2496 // the size of the standard checkmark bitmap
2497 static const wxCoord MENU_CHECK_SIZE
= 9;
2499 // we can't implement these methods without wxMenuGeometryInfo implementation
2500 // which we don't have if !wxUSE_MENUS
2503 void wxWin32Renderer::DrawMenuBarItem(wxDC
& dc
,
2504 const wxRect
& rectOrig
,
2505 const wxString
& label
,
2509 wxRect rect
= rectOrig
;
2512 wxDCTextColourChanger
colChanger(dc
);
2514 if ( flags
& wxCONTROL_SELECTED
)
2516 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2518 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2519 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2520 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2521 dc
.DrawRectangle(rect
);
2524 // don't draw the focus rect around menu bar items
2525 DrawLabel(dc
, label
, rect
, flags
& ~wxCONTROL_FOCUSED
,
2526 wxALIGN_CENTRE
, indexAccel
);
2529 void wxWin32Renderer::DrawMenuItem(wxDC
& dc
,
2531 const wxMenuGeometryInfo
& gi
,
2532 const wxString
& label
,
2533 const wxString
& accel
,
2534 const wxBitmap
& bitmap
,
2538 const wxWin32MenuGeometryInfo
& geometryInfo
=
2539 (const wxWin32MenuGeometryInfo
&)gi
;
2544 rect
.width
= geometryInfo
.GetSize().x
;
2545 rect
.height
= geometryInfo
.GetItemHeight();
2547 // draw the selected item specially
2548 wxDCTextColourChanger
colChanger(dc
);
2549 if ( flags
& wxCONTROL_SELECTED
)
2551 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2553 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2554 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2555 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2556 dc
.DrawRectangle(rect
);
2559 // draw the bitmap: use the bitmap provided or the standard checkmark for
2560 // the checkable items
2561 wxBitmap bmp
= bitmap
;
2562 if ( !bmp
.Ok() && (flags
& wxCONTROL_CHECKED
) )
2564 bmp
= GetIndicator(IndicatorType_Menu
, flags
);
2569 rect
.SetRight(geometryInfo
.GetLabelOffset());
2570 wxControlRenderer::DrawBitmap(dc
, bmp
, rect
);
2574 rect
.x
= geometryInfo
.GetLabelOffset();
2575 rect
.SetRight(geometryInfo
.GetAccelOffset());
2577 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
, indexAccel
);
2579 // draw the accel string
2580 rect
.x
= geometryInfo
.GetAccelOffset();
2581 rect
.SetRight(geometryInfo
.GetSize().x
);
2583 // NB: no accel index here
2584 DrawLabel(dc
, accel
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
);
2586 // draw the submenu indicator
2587 if ( flags
& wxCONTROL_ISSUBMENU
)
2589 rect
.x
= geometryInfo
.GetSize().x
- MENU_RIGHT_MARGIN
;
2590 rect
.width
= MENU_RIGHT_MARGIN
;
2592 wxArrowStyle arrowStyle
;
2593 if ( flags
& wxCONTROL_DISABLED
)
2594 arrowStyle
= flags
& wxCONTROL_SELECTED
? Arrow_InversedDisabled
2596 else if ( flags
& wxCONTROL_SELECTED
)
2597 arrowStyle
= Arrow_Inversed
;
2599 arrowStyle
= Arrow_Normal
;
2601 DrawArrow(dc
, rect
, Arrow_Right
, arrowStyle
);
2605 void wxWin32Renderer::DrawMenuSeparator(wxDC
& dc
,
2607 const wxMenuGeometryInfo
& geomInfo
)
2609 DrawHorizontalLine(dc
, y
+ MENU_VERT_MARGIN
, 0, geomInfo
.GetSize().x
);
2612 wxSize
wxWin32Renderer::GetMenuBarItemSize(const wxSize
& sizeText
) const
2614 wxSize size
= sizeText
;
2616 // FIXME: menubar height is configurable under Windows
2623 wxMenuGeometryInfo
*wxWin32Renderer::GetMenuGeometry(wxWindow
*win
,
2624 const wxMenu
& menu
) const
2626 // prepare the dc: for now we draw all the items with the system font
2628 dc
.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
));
2630 // the height of a normal item
2631 wxCoord heightText
= dc
.GetCharHeight();
2636 // the max length of label and accel strings: the menu width is the sum of
2637 // them, even if they're for different items (as the accels should be
2640 // the max length of the bitmap is never 0 as Windows always leaves enough
2641 // space for a check mark indicator
2642 wxCoord widthLabelMax
= 0,
2644 widthBmpMax
= MENU_LEFT_MARGIN
;
2646 for ( wxMenuItemList::Node
*node
= menu
.GetMenuItems().GetFirst();
2648 node
= node
->GetNext() )
2650 // height of this item
2653 wxMenuItem
*item
= node
->GetData();
2654 if ( item
->IsSeparator() )
2656 h
= MENU_SEPARATOR_HEIGHT
;
2658 else // not separator
2663 dc
.GetTextExtent(item
->GetLabel(), &widthLabel
, NULL
);
2664 if ( widthLabel
> widthLabelMax
)
2666 widthLabelMax
= widthLabel
;
2670 dc
.GetTextExtent(item
->GetAccelString(), &widthAccel
, NULL
);
2671 if ( widthAccel
> widthAccelMax
)
2673 widthAccelMax
= widthAccel
;
2676 const wxBitmap
& bmp
= item
->GetBitmap();
2679 wxCoord widthBmp
= bmp
.GetWidth();
2680 if ( widthBmp
> widthBmpMax
)
2681 widthBmpMax
= widthBmp
;
2683 //else if ( item->IsCheckable() ): no need to check for this as
2684 // MENU_LEFT_MARGIN is big enough to show the check mark
2687 h
+= 2*MENU_VERT_MARGIN
;
2689 // remember the item position and height
2690 item
->SetGeometry(height
, h
);
2695 // bundle the metrics into a struct and return it
2696 wxWin32MenuGeometryInfo
*gi
= new wxWin32MenuGeometryInfo
;
2698 gi
->m_ofsLabel
= widthBmpMax
+ 2*MENU_BMP_MARGIN
;
2699 gi
->m_ofsAccel
= gi
->m_ofsLabel
+ widthLabelMax
;
2700 if ( widthAccelMax
> 0 )
2702 // if we actually have any accesl, add a margin
2703 gi
->m_ofsAccel
+= MENU_ACCEL_MARGIN
;
2706 gi
->m_heightItem
= heightText
+ 2*MENU_VERT_MARGIN
;
2708 gi
->m_size
.x
= gi
->m_ofsAccel
+ widthAccelMax
+ MENU_RIGHT_MARGIN
;
2709 gi
->m_size
.y
= height
;
2714 #else // !wxUSE_MENUS
2717 void wxWin32Renderer::DrawMenuBarItem(wxDC& WXUNUSED(dc),
2718 const wxRect& WXUNUSED(rectOrig),
2719 const wxString& WXUNUSED(label),
2720 int WXUNUSED(flags),
2721 int WXUNUSED(indexAccel))
2725 void wxWin32Renderer::DrawMenuItem(wxDC& WXUNUSED(dc),
2726 wxCoord WXUNUSED(y),
2727 const wxMenuGeometryInfo& WXUNUSED(gi),
2728 const wxString& WXUNUSED(label),
2729 const wxString& WXUNUSED(accel),
2730 const wxBitmap& WXUNUSED(bitmap),
2731 int WXUNUSED(flags),
2732 int WXUNUSED(indexAccel))
2736 void wxWin32Renderer::DrawMenuSeparator(wxDC& WXUNUSED(dc),
2737 wxCoord WXUNUSED(y),
2738 const wxMenuGeometryInfo& WXUNUSED(gi))
2742 wxSize wxWin32Renderer::GetMenuBarItemSize(const wxSize& size) const
2747 wxMenuGeometryInfo *
2748 wxWin32Renderer::GetMenuGeometry(wxWindow *WXUNUSED(win),
2749 const wxMenu& WXUNUSED(menu)) const
2755 #endif // wxUSE_MENUS/!wxUSE_MENUS
2757 // ----------------------------------------------------------------------------
2759 // ----------------------------------------------------------------------------
2761 void wxWin32Renderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
2762 wxBitmap
*bmpPressed
,
2763 wxBitmap
*bmpDisabled
)
2765 static const wxCoord widthCombo
= 16;
2766 static const wxCoord heightCombo
= 17;
2772 bmpNormal
->Create(widthCombo
, heightCombo
);
2773 dcMem
.SelectObject(*bmpNormal
);
2774 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2775 Arrow_Down
, Arrow_Normal
);
2780 bmpPressed
->Create(widthCombo
, heightCombo
);
2781 dcMem
.SelectObject(*bmpPressed
);
2782 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2783 Arrow_Down
, Arrow_Pressed
);
2788 bmpDisabled
->Create(widthCombo
, heightCombo
);
2789 dcMem
.SelectObject(*bmpDisabled
);
2790 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2791 Arrow_Down
, Arrow_Disabled
);
2795 // ----------------------------------------------------------------------------
2797 // ----------------------------------------------------------------------------
2799 void wxWin32Renderer::DoDrawBackground(wxDC
& dc
,
2800 const wxColour
& col
,
2803 wxBrush
brush(col
, wxSOLID
);
2805 dc
.SetPen(*wxTRANSPARENT_PEN
);
2806 dc
.DrawRectangle(rect
);
2809 void wxWin32Renderer::DrawBackground(wxDC
& dc
,
2810 const wxColour
& col
,
2814 // just fill it with the given or default bg colour
2815 wxColour colBg
= col
.Ok() ? col
: wxSCHEME_COLOUR(m_scheme
, CONTROL
);
2816 DoDrawBackground(dc
, colBg
, rect
);
2819 // ----------------------------------------------------------------------------
2821 // ----------------------------------------------------------------------------
2823 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2828 // get the bitmap for this arrow
2829 wxArrowDirection arrowDir
;
2832 case wxLEFT
: arrowDir
= Arrow_Left
; break;
2833 case wxRIGHT
: arrowDir
= Arrow_Right
; break;
2834 case wxUP
: arrowDir
= Arrow_Up
; break;
2835 case wxDOWN
: arrowDir
= Arrow_Down
; break;
2838 wxFAIL_MSG(_T("unknown arrow direction"));
2842 wxArrowStyle arrowStyle
;
2843 if ( flags
& wxCONTROL_PRESSED
)
2845 // can't be pressed and disabled
2846 arrowStyle
= Arrow_Pressed
;
2850 arrowStyle
= flags
& wxCONTROL_DISABLED
? Arrow_Disabled
: Arrow_Normal
;
2853 DrawArrowButton(dc
, rect
, arrowDir
, arrowStyle
);
2856 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2858 wxArrowDirection arrowDir
,
2859 wxArrowStyle arrowStyle
)
2861 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
2863 // under Windows the arrows always have the same size so just centre it in
2864 // the provided rectangle
2865 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
2866 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
2868 // Windows does it like this...
2869 if ( arrowDir
== Arrow_Left
)
2873 dc
.DrawBitmap(bmp
, x
, y
, TRUE
/* use mask */);
2876 void wxWin32Renderer::DrawArrowButton(wxDC
& dc
,
2877 const wxRect
& rectAll
,
2878 wxArrowDirection arrowDir
,
2879 wxArrowStyle arrowStyle
)
2881 wxRect rect
= rectAll
;
2882 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2883 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
2884 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
2887 void wxWin32Renderer::DrawScrollbarThumb(wxDC
& dc
,
2888 wxOrientation orient
,
2892 // we don't use the flags, the thumb never changes appearance
2893 wxRect rectThumb
= rect
;
2894 DrawArrowBorder(dc
, &rectThumb
);
2895 DrawBackground(dc
, wxNullColour
, rectThumb
);
2898 void wxWin32Renderer::DrawScrollbarShaft(wxDC
& dc
,
2899 wxOrientation orient
,
2900 const wxRect
& rectBar
,
2903 wxColourScheme::StdColour col
= flags
& wxCONTROL_PRESSED
2904 ? wxColourScheme::SCROLLBAR_PRESSED
2905 : wxColourScheme::SCROLLBAR
;
2906 DoDrawBackground(dc
, m_scheme
->Get(col
), rectBar
);
2909 void wxWin32Renderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
2911 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2914 wxRect
wxWin32Renderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
2915 wxScrollBar::Element elem
,
2918 return StandardGetScrollbarRect(scrollbar
, elem
,
2919 thumbPos
, m_sizeScrollbarArrow
);
2922 wxCoord
wxWin32Renderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
2924 return StandardScrollBarSize(scrollbar
, m_sizeScrollbarArrow
);
2927 wxHitTest
wxWin32Renderer::HitTestScrollbar(const wxScrollBar
*scrollbar
,
2928 const wxPoint
& pt
) const
2930 return StandardHitTestScrollbar(scrollbar
, pt
, m_sizeScrollbarArrow
);
2933 wxCoord
wxWin32Renderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
2936 return StandardScrollbarToPixel(scrollbar
, thumbPos
, m_sizeScrollbarArrow
);
2939 int wxWin32Renderer::PixelToScrollbar(const wxScrollBar
*scrollbar
,
2942 return StandardPixelToScrollbar(scrollbar
, coord
, m_sizeScrollbarArrow
);
2945 // ----------------------------------------------------------------------------
2946 // text control geometry
2947 // ----------------------------------------------------------------------------
2949 static inline int GetTextBorderWidth()
2954 wxRect
wxWin32Renderer::GetTextTotalArea(const wxTextCtrl
*text
,
2957 wxRect rectTotal
= rect
;
2959 wxCoord widthBorder
= GetTextBorderWidth();
2960 rectTotal
.Inflate(widthBorder
);
2962 // this is what Windows does
2968 wxRect
wxWin32Renderer::GetTextClientArea(const wxTextCtrl
*text
,
2970 wxCoord
*extraSpaceBeyond
)
2972 wxRect rectText
= rect
;
2974 // undo GetTextTotalArea()
2975 if ( rectText
.height
> 0 )
2978 wxCoord widthBorder
= GetTextBorderWidth();
2979 rectText
.Inflate(-widthBorder
);
2981 if ( extraSpaceBeyond
)
2982 *extraSpaceBeyond
= 0;
2987 // ----------------------------------------------------------------------------
2989 // ----------------------------------------------------------------------------
2991 void wxWin32Renderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
2994 if ( wxDynamicCast(window
, wxScrollBar
) )
2996 // we only set the width of vert scrollbars and height of the
2998 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
2999 size
->y
= m_sizeScrollbarArrow
.y
;
3001 size
->x
= m_sizeScrollbarArrow
.x
;
3003 // skip border width adjustments, they don't make sense for us
3006 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
3009 if ( wxDynamicCast(window
, wxButton
) )
3012 size
->x
+= 3*window
->GetCharWidth();
3013 #if 0 // do allow creating small buttons if wanted
3014 wxSize sizeDef
= wxButton::GetDefaultSize();
3015 if ( size
->x
< sizeDef
.x
)
3016 size
->x
= sizeDef
.x
;
3019 wxCoord heightBtn
= (11*(window
->GetCharHeight() + 8))/10;
3020 if ( size
->y
< heightBtn
- 8 )
3021 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
);