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 case CONTROL_PRESSED
:
1095 case CONTROL_CURRENT
:
1096 case CONTROL
: return wxColour(0xc0c0c0);
1098 case CONTROL_TEXT
: return *wxBLACK
;
1100 case SCROLLBAR
: return wxColour(0xe0e0e0);
1101 case SCROLLBAR_PRESSED
: return *wxBLACK
;
1103 case HIGHLIGHT
: return wxColour(0x800000);
1104 case HIGHLIGHT_TEXT
: return wxColour(0xffffff);
1106 case SHADOW_DARK
: return *wxBLACK
;
1108 case CONTROL_TEXT_DISABLED
:
1109 case SHADOW_HIGHLIGHT
: return wxColour(0xe0e0e0);
1111 case SHADOW_IN
: return wxColour(0xc0c0c0);
1113 case CONTROL_TEXT_DISABLED_SHADOW
:
1114 case SHADOW_OUT
: return wxColour(0x7f7f7f);
1118 wxFAIL_MSG(_T("invalid standard colour"));
1123 // ============================================================================
1125 // ============================================================================
1127 // ----------------------------------------------------------------------------
1129 // ----------------------------------------------------------------------------
1131 wxWin32Renderer::wxWin32Renderer(const wxColourScheme
*scheme
)
1135 m_sizeScrollbarArrow
= wxSize(16, 16);
1137 // init colours and pens
1138 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
), 0, wxSOLID
);
1140 m_colDarkGrey
= wxSCHEME_COLOUR(scheme
, SHADOW_OUT
);
1141 m_penDarkGrey
= wxPen(m_colDarkGrey
, 0, wxSOLID
);
1143 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
), 0, wxSOLID
);
1145 m_colHighlight
= wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
);
1146 m_penHighlight
= wxPen(m_colHighlight
, 0, wxSOLID
);
1148 // init the arrow bitmaps
1149 static const size_t ARROW_WIDTH
= 7;
1150 static const size_t ARROW_LENGTH
= 4;
1153 wxMemoryDC dcNormal
,
1156 for ( size_t n
= 0; n
< Arrow_Max
; n
++ )
1158 bool isVertical
= n
> Arrow_Right
;
1171 // disabled arrow is larger because of the shadow
1172 m_bmpArrows
[Arrow_Normal
][n
].Create(w
, h
);
1173 m_bmpArrows
[Arrow_Disabled
][n
].Create(w
+ 1, h
+ 1);
1175 dcNormal
.SelectObject(m_bmpArrows
[Arrow_Normal
][n
]);
1176 dcDisabled
.SelectObject(m_bmpArrows
[Arrow_Disabled
][n
]);
1178 dcNormal
.SetBackground(*wxWHITE_BRUSH
);
1179 dcDisabled
.SetBackground(*wxWHITE_BRUSH
);
1183 dcNormal
.SetPen(m_penBlack
);
1184 dcDisabled
.SetPen(m_penDarkGrey
);
1186 // calculate the position of the point of the arrow
1190 x1
= (ARROW_WIDTH
- 1)/2;
1191 y1
= n
== Arrow_Up
? 0 : ARROW_LENGTH
- 1;
1195 x1
= n
== Arrow_Left
? 0 : ARROW_LENGTH
- 1;
1196 y1
= (ARROW_WIDTH
- 1)/2;
1207 for ( size_t i
= 0; i
< ARROW_LENGTH
; i
++ )
1209 dcNormal
.DrawLine(x1
, y1
, x2
, y2
);
1210 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1217 if ( n
== Arrow_Up
)
1228 else // left or right arrow
1233 if ( n
== Arrow_Left
)
1246 // draw the shadow for the disabled one
1247 dcDisabled
.SetPen(m_penHighlight
);
1252 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1256 x1
= ARROW_LENGTH
- 1;
1257 y1
= (ARROW_WIDTH
- 1)/2 + 1;
1260 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1261 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1266 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1270 x1
= ARROW_WIDTH
- 1;
1272 x2
= (ARROW_WIDTH
- 1)/2;
1274 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1275 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1280 // create the inversed bitmap but only for the right arrow as we only
1281 // use it for the menus
1282 if ( n
== Arrow_Right
)
1284 m_bmpArrows
[Arrow_Inversed
][n
].Create(w
, h
);
1285 dcInverse
.SelectObject(m_bmpArrows
[Arrow_Inversed
][n
]);
1287 dcInverse
.Blit(0, 0, w
, h
,
1290 dcInverse
.SelectObject(wxNullBitmap
);
1292 mask
= new wxMask(m_bmpArrows
[Arrow_Inversed
][n
], *wxBLACK
);
1293 m_bmpArrows
[Arrow_Inversed
][n
].SetMask(mask
);
1295 m_bmpArrows
[Arrow_InversedDisabled
][n
].Create(w
, h
);
1296 dcInverse
.SelectObject(m_bmpArrows
[Arrow_InversedDisabled
][n
]);
1298 dcInverse
.Blit(0, 0, w
, h
,
1301 dcInverse
.SelectObject(wxNullBitmap
);
1303 mask
= new wxMask(m_bmpArrows
[Arrow_InversedDisabled
][n
], *wxBLACK
);
1304 m_bmpArrows
[Arrow_InversedDisabled
][n
].SetMask(mask
);
1307 dcNormal
.SelectObject(wxNullBitmap
);
1308 dcDisabled
.SelectObject(wxNullBitmap
);
1310 mask
= new wxMask(m_bmpArrows
[Arrow_Normal
][n
], *wxWHITE
);
1311 m_bmpArrows
[Arrow_Normal
][n
].SetMask(mask
);
1312 mask
= new wxMask(m_bmpArrows
[Arrow_Disabled
][n
], *wxWHITE
);
1313 m_bmpArrows
[Arrow_Disabled
][n
].SetMask(mask
);
1315 m_bmpArrows
[Arrow_Pressed
][n
] = m_bmpArrows
[Arrow_Normal
][n
];
1319 // ----------------------------------------------------------------------------
1321 // ----------------------------------------------------------------------------
1324 The raised border in Win32 looks like this:
1326 IIIIIIIIIIIIIIIIIIIIIIB
1328 I GB I = white (HILIGHT)
1329 I GB H = light grey (LIGHT)
1330 I GB G = dark grey (SHADOI)
1331 I GB B = black (DKSHADOI)
1332 I GB I = hIghlight (COLOR_3DHILIGHT)
1334 IGGGGGGGGGGGGGGGGGGGGGB
1335 BBBBBBBBBBBBBBBBBBBBBBB
1337 The sunken border looks like this:
1339 GGGGGGGGGGGGGGGGGGGGGGI
1340 GBBBBBBBBBBBBBBBBBBBBHI
1347 GHHHHHHHHHHHHHHHHHHHHHI
1348 IIIIIIIIIIIIIIIIIIIIIII
1350 The static border (used for the controls which don't get focus) is like
1353 GGGGGGGGGGGGGGGGGGGGGGW
1361 WWWWWWWWWWWWWWWWWWWWWWW
1363 The most complicated is the double border:
1365 HHHHHHHHHHHHHHHHHHHHHHB
1366 HWWWWWWWWWWWWWWWWWWWWGB
1367 HWHHHHHHHHHHHHHHHHHHHGB
1372 HWHHHHHHHHHHHHHHHHHHHGB
1373 HGGGGGGGGGGGGGGGGGGGGGB
1374 BBBBBBBBBBBBBBBBBBBBBBB
1376 And the simple border is, well, simple:
1378 BBBBBBBBBBBBBBBBBBBBBBB
1387 BBBBBBBBBBBBBBBBBBBBBBB
1390 void wxWin32Renderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1394 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1395 dc
.DrawRectangle(*rect
);
1401 void wxWin32Renderer::DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1403 // draw the bottom and right sides
1405 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1406 rect
->GetRight() + 1, rect
->GetBottom());
1407 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1408 rect
->GetRight(), rect
->GetBottom());
1415 void wxWin32Renderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
1416 const wxPen
& pen1
, const wxPen
& pen2
)
1418 // draw the rectangle
1420 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
1421 rect
->GetLeft(), rect
->GetBottom());
1422 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
1423 rect
->GetRight(), rect
->GetTop());
1425 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1426 rect
->GetRight(), rect
->GetBottom());
1427 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1428 rect
->GetRight() + 1, rect
->GetBottom());
1434 void wxWin32Renderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
1436 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
1437 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
1440 void wxWin32Renderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
1442 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
1443 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
1446 void wxWin32Renderer::DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
)
1450 DrawRect(dc
, rect
, m_penDarkGrey
);
1452 // the arrow is usually drawn inside border of width 2 and is offset by
1453 // another pixel in both directions when it's pressed - as the border
1454 // in this case is more narrow as well, we have to adjust rect like
1462 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
1463 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
1467 void wxWin32Renderer::DrawBorder(wxDC
& dc
,
1469 const wxRect
& rectTotal
,
1470 int WXUNUSED(flags
),
1475 wxRect rect
= rectTotal
;
1479 case wxBORDER_SUNKEN
:
1480 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1482 DrawSunkenBorder(dc
, &rect
);
1486 case wxBORDER_STATIC
:
1487 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1490 case wxBORDER_RAISED
:
1491 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1493 DrawRaisedBorder(dc
, &rect
);
1497 case wxBORDER_DOUBLE
:
1498 DrawArrowBorder(dc
, &rect
);
1499 DrawRect(dc
, &rect
, m_penLightGrey
);
1502 case wxBORDER_SIMPLE
:
1503 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1505 DrawRect(dc
, &rect
, m_penBlack
);
1510 wxFAIL_MSG(_T("unknown border type"));
1513 case wxBORDER_DEFAULT
:
1522 wxRect
wxWin32Renderer::GetBorderDimensions(wxBorder border
) const
1527 case wxBORDER_RAISED
:
1528 case wxBORDER_SUNKEN
:
1529 width
= BORDER_THICKNESS
;
1532 case wxBORDER_SIMPLE
:
1533 case wxBORDER_STATIC
:
1537 case wxBORDER_DOUBLE
:
1542 wxFAIL_MSG(_T("unknown border type"));
1545 case wxBORDER_DEFAULT
:
1555 rect
.height
= width
;
1560 bool wxWin32Renderer::AreScrollbarsInsideBorder() const
1565 // ----------------------------------------------------------------------------
1567 // ----------------------------------------------------------------------------
1569 void wxWin32Renderer::DrawTextBorder(wxDC
& dc
,
1575 // text controls are not special under windows
1576 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
1579 void wxWin32Renderer::DrawButtonBorder(wxDC
& dc
,
1580 const wxRect
& rectTotal
,
1584 wxRect rect
= rectTotal
;
1586 if ( flags
& wxCONTROL_PRESSED
)
1588 // button pressed: draw a double border around it
1589 DrawRect(dc
, &rect
, m_penBlack
);
1590 DrawRect(dc
, &rect
, m_penDarkGrey
);
1594 // button not pressed
1596 if ( flags
& (wxCONTROL_FOCUSED
| wxCONTROL_ISDEFAULT
) )
1598 // button either default or focused (or both): add an extra border around it
1599 DrawRect(dc
, &rect
, m_penBlack
);
1602 // now draw a normal button
1603 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penBlack
);
1604 DrawHalfRect(dc
, &rect
, m_penDarkGrey
);
1613 // ----------------------------------------------------------------------------
1615 // ----------------------------------------------------------------------------
1617 void wxWin32Renderer::DrawHorizontalLine(wxDC
& dc
,
1618 wxCoord y
, wxCoord x1
, wxCoord x2
)
1620 dc
.SetPen(m_penDarkGrey
);
1621 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1622 dc
.SetPen(m_penHighlight
);
1624 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1627 void wxWin32Renderer::DrawVerticalLine(wxDC
& dc
,
1628 wxCoord x
, wxCoord y1
, wxCoord y2
)
1630 dc
.SetPen(m_penDarkGrey
);
1631 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1632 dc
.SetPen(m_penHighlight
);
1634 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1637 void wxWin32Renderer::DrawFrame(wxDC
& dc
,
1638 const wxString
& label
,
1644 wxCoord height
= 0; // of the label
1645 wxRect rectFrame
= rect
;
1646 if ( !label
.empty() )
1648 // the text should touch the top border of the rect, so the frame
1649 // itself should be lower
1650 dc
.GetTextExtent(label
, NULL
, &height
);
1651 rectFrame
.y
+= height
/ 2;
1652 rectFrame
.height
-= height
/ 2;
1654 // we have to draw each part of the frame individually as we can't
1655 // erase the background beyond the label as it might contain some
1656 // pixmap already, so drawing everything and then overwriting part of
1657 // the frame with label doesn't work
1659 // TODO: the +5 and space insertion should be customizable
1662 rectText
.x
= rectFrame
.x
+ 5;
1663 rectText
.y
= rect
.y
;
1664 rectText
.width
= rectFrame
.width
- 7; // +2 border width
1665 rectText
.height
= height
;
1668 label2
<< _T(' ') << label
<< _T(' ');
1669 if ( indexAccel
!= -1 )
1671 // adjust it as we prepended a space
1676 DrawLabel(dc
, label2
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
1678 StandardDrawFrame(dc
, rectFrame
, rectLabel
);
1682 // just draw the complete frame
1683 DrawShadedRect(dc
, &rectFrame
, m_penDarkGrey
, m_penHighlight
);
1684 DrawShadedRect(dc
, &rectFrame
, m_penHighlight
, m_penDarkGrey
);
1688 // ----------------------------------------------------------------------------
1690 // ----------------------------------------------------------------------------
1692 void wxWin32Renderer::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
1694 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
1695 // pixels each while we really need dots here... PS_ALTERNATE might
1696 // work, but it is for NT 5 only
1698 DrawRect(dc
, &rect
, wxPen(*wxBLACK
, 0, wxDOT
));
1700 // draw the pixels manually: note that to behave in the same manner as
1701 // DrawRect(), we must exclude the bottom and right borders from the
1703 wxCoord x1
= rect
.GetLeft(),
1705 x2
= rect
.GetRight(),
1706 y2
= rect
.GetBottom();
1708 dc
.SetPen(wxPen(*wxBLACK
, 0, wxSOLID
));
1710 // this seems to be closer than what Windows does than wxINVERT although
1711 // I'm still not sure if it's correct
1712 dc
.SetLogicalFunction(wxAND_REVERSE
);
1715 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
1716 dc
.DrawPoint(z
, rect
.GetTop());
1718 wxCoord shift
= z
== x2
? 0 : 1;
1719 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
1720 dc
.DrawPoint(x2
, z
);
1722 shift
= z
== y2
? 0 : 1;
1723 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
1724 dc
.DrawPoint(z
, y2
);
1726 shift
= z
== x1
? 0 : 1;
1727 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
1728 dc
.DrawPoint(x1
, z
);
1730 dc
.SetLogicalFunction(wxCOPY
);
1734 void wxWin32Renderer::DrawLabelShadow(wxDC
& dc
,
1735 const wxString
& label
,
1740 // draw shadow of the text
1741 dc
.SetTextForeground(m_colHighlight
);
1742 wxRect rectShadow
= rect
;
1745 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
1747 // make the text grey
1748 dc
.SetTextForeground(m_colDarkGrey
);
1751 void wxWin32Renderer::DrawLabel(wxDC
& dc
,
1752 const wxString
& label
,
1759 DoDrawLabel(dc
, label
, rect
, flags
, alignment
, indexAccel
, rectBounds
);
1762 void wxWin32Renderer::DoDrawLabel(wxDC
& dc
,
1763 const wxString
& label
,
1769 const wxPoint
& focusOffset
)
1771 // the underscores are not drawn for focused controls in wxMSW
1772 if ( flags
& wxCONTROL_FOCUSED
)
1777 if ( flags
& wxCONTROL_DISABLED
)
1779 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
1780 // currently only can happen for a menu item and it seems that Windows
1781 // doesn't draw the shadow in this case, so we don't do it neither
1782 if ( flags
& wxCONTROL_SELECTED
)
1784 // just make the label text greyed out
1785 dc
.SetTextForeground(m_colDarkGrey
);
1787 else // draw normal disabled label
1789 DrawLabelShadow(dc
, label
, rect
, alignment
, indexAccel
);
1794 dc
.DrawLabel(label
, wxNullBitmap
, rect
, alignment
, indexAccel
, &rectLabel
);
1796 if ( flags
& wxCONTROL_DISABLED
)
1798 // restore the fg colour
1799 dc
.SetTextForeground(*wxBLACK
);
1802 if ( flags
& wxCONTROL_FOCUSED
)
1804 if ( focusOffset
.x
|| focusOffset
.y
)
1806 rectLabel
.Inflate(focusOffset
.x
, focusOffset
.y
);
1809 DrawFocusRect(dc
, rectLabel
);
1813 *rectBounds
= rectLabel
;
1816 void wxWin32Renderer::DrawButtonLabel(wxDC
& dc
,
1817 const wxString
& label
,
1818 const wxBitmap
& image
,
1825 // the underscores are not drawn for focused controls in wxMSW
1826 if ( flags
& wxCONTROL_PRESSED
)
1831 wxRect rectLabel
= rect
;
1832 if ( !label
.empty() )
1834 // shift the label if a button is pressed
1835 if ( flags
& wxCONTROL_PRESSED
)
1841 if ( flags
& wxCONTROL_DISABLED
)
1843 DrawLabelShadow(dc
, label
, rectLabel
, alignment
, indexAccel
);
1846 // leave enough space for the focus rectangle
1847 if ( flags
& wxCONTROL_FOCUSED
)
1849 rectLabel
.Inflate(-2);
1853 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
1855 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
1857 if ( flags
& wxCONTROL_PRESSED
)
1859 // the focus rectangle is never pressed, so undo the shift done
1867 DrawFocusRect(dc
, rectLabel
);
1871 // ----------------------------------------------------------------------------
1872 // (check)listbox items
1873 // ----------------------------------------------------------------------------
1875 void wxWin32Renderer::DrawItem(wxDC
& dc
,
1876 const wxString
& label
,
1880 wxDCTextColourChanger
colChanger(dc
);
1882 if ( flags
& wxCONTROL_SELECTED
)
1884 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
1886 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
1887 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
1888 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
1889 dc
.DrawRectangle(rect
);
1892 wxRect rectText
= rect
;
1894 rectText
.width
-= 2;
1895 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
1897 if ( flags
& wxCONTROL_FOCUSED
)
1899 DrawFocusRect(dc
, rect
);
1903 void wxWin32Renderer::DrawCheckItem(wxDC
& dc
,
1904 const wxString
& label
,
1905 const wxBitmap
& bitmap
,
1914 else // use default bitmap
1916 bmp
= wxBitmap(flags
& wxCONTROL_CHECKED
? checked_item_xpm
1917 : unchecked_item_xpm
);
1920 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2 - 1,
1921 TRUE
/* use mask */);
1923 wxRect rectLabel
= rect
;
1924 int bmpWidth
= bmp
.GetWidth();
1925 rectLabel
.x
+= bmpWidth
;
1926 rectLabel
.width
-= bmpWidth
;
1928 DrawItem(dc
, label
, rectLabel
, flags
);
1931 // ----------------------------------------------------------------------------
1932 // check/radio buttons
1933 // ----------------------------------------------------------------------------
1935 wxBitmap
wxWin32Renderer::GetIndicator(IndicatorType indType
, int flags
)
1937 IndicatorState indState
;
1938 if ( flags
& wxCONTROL_SELECTED
)
1939 indState
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
1940 : IndicatorState_Selected
;
1941 else if ( flags
& wxCONTROL_DISABLED
)
1942 indState
= IndicatorState_Disabled
;
1943 else if ( flags
& wxCONTROL_PRESSED
)
1944 indState
= IndicatorState_Pressed
;
1946 indState
= IndicatorState_Normal
;
1948 IndicatorStatus indStatus
= flags
& wxCONTROL_CHECKED
1949 ? IndicatorStatus_Checked
1950 : IndicatorStatus_Unchecked
;
1952 const char **xpm
= bmpIndicators
[indType
][indState
][indStatus
];
1953 return xpm
? wxBitmap(xpm
) : wxNullBitmap
;
1956 void wxWin32Renderer::DrawCheckOrRadioButton(wxDC
& dc
,
1957 const wxString
& label
,
1958 const wxBitmap
& bitmap
,
1963 wxCoord focusOffsetY
)
1965 // calculate the position of the bitmap and of the label
1966 wxCoord heightBmp
= bitmap
.GetHeight();
1968 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
1971 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
1972 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
1974 // align label vertically with the bitmap - looks nicer like this
1975 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
1977 // calc horz position
1978 if ( align
== wxALIGN_RIGHT
)
1980 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
1981 rectLabel
.x
= rect
.x
+ 3;
1982 rectLabel
.SetRight(xBmp
);
1984 else // normal (checkbox to the left of the text) case
1987 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
1988 rectLabel
.SetRight(rect
.GetRight());
1991 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, TRUE
/* use mask */);
1994 dc
, label
, rectLabel
,
1996 wxALIGN_LEFT
| wxALIGN_TOP
,
1998 NULL
, // we don't need bounding rect
1999 // use custom vert focus rect offset
2000 wxPoint(FOCUS_RECT_OFFSET_X
, focusOffsetY
)
2004 void wxWin32Renderer::DrawRadioButton(wxDC
& dc
,
2005 const wxString
& label
,
2006 const wxBitmap
& bitmap
,
2012 DrawCheckOrRadioButton(dc
, label
,
2013 bitmap
.Ok() ? bitmap
: GetRadioBitmap(flags
),
2014 rect
, flags
, align
, indexAccel
,
2015 FOCUS_RECT_OFFSET_Y
); // default focus rect offset
2018 void wxWin32Renderer::DrawCheckButton(wxDC
& dc
,
2019 const wxString
& label
,
2020 const wxBitmap
& bitmap
,
2026 DrawCheckOrRadioButton(dc
, label
,
2027 bitmap
.Ok() ? bitmap
: GetCheckBitmap(flags
),
2028 rect
, flags
, align
, indexAccel
,
2029 0); // no focus rect offset for checkboxes
2032 // ----------------------------------------------------------------------------
2034 // ----------------------------------------------------------------------------
2036 void wxWin32Renderer::DrawTextLine(wxDC
& dc
,
2037 const wxString
& text
,
2043 // nothing special to do here
2044 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
2047 void wxWin32Renderer::DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
)
2049 // we don't draw them
2052 // ----------------------------------------------------------------------------
2054 // ----------------------------------------------------------------------------
2056 void wxWin32Renderer::DrawTab(wxDC
& dc
,
2057 const wxRect
& rectOrig
,
2059 const wxString
& label
,
2060 const wxBitmap
& bitmap
,
2064 wxRect rect
= rectOrig
;
2066 // the current tab is drawn indented (to the top for default case) and
2067 // bigger than the other ones
2068 const wxSize indent
= GetTabIndent();
2069 if ( flags
& wxCONTROL_SELECTED
)
2074 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2078 rect
.Inflate(indent
.x
, 0);
2080 rect
.height
+= indent
.y
;
2084 rect
.Inflate(indent
.x
, 0);
2085 rect
.height
+= indent
.y
;
2090 wxFAIL_MSG(_T("TODO"));
2095 // draw the text, image and the focus around them (if necessary)
2096 wxRect rectLabel
= rect
;
2097 rectLabel
.Deflate(1, 1);
2098 DrawButtonLabel(dc
, label
, bitmap
, rectLabel
,
2099 flags
, wxALIGN_CENTRE
, indexAccel
);
2101 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2102 static const wxCoord CUTOFF
= 2; // radius of the rounded corner
2105 x2
= rect
.GetRight(),
2106 y2
= rect
.GetBottom();
2108 // FIXME: all this code will break if the tab indent or the border width,
2109 // it is tied to the fact that both of them are equal to 2
2114 dc
.SetPen(m_penHighlight
);
2115 dc
.DrawLine(x
, y2
, x
, y
+ CUTOFF
);
2116 dc
.DrawLine(x
, y
+ CUTOFF
, x
+ CUTOFF
, y
);
2117 dc
.DrawLine(x
+ CUTOFF
, y
, x2
- CUTOFF
+ 1, y
);
2119 dc
.SetPen(m_penBlack
);
2120 dc
.DrawLine(x2
, y2
, x2
, y
+ CUTOFF
);
2121 dc
.DrawLine(x2
, y
+ CUTOFF
, x2
- CUTOFF
, y
);
2123 dc
.SetPen(m_penDarkGrey
);
2124 dc
.DrawLine(x2
- 1, y2
, x2
- 1, y
+ CUTOFF
- 1);
2126 if ( flags
& wxCONTROL_SELECTED
)
2128 dc
.SetPen(m_penLightGrey
);
2130 // overwrite the part of the border below this tab
2131 dc
.DrawLine(x
+ 1, y2
+ 1, x2
- 1, y2
+ 1);
2133 // and the shadow of the tab to the left of us
2134 dc
.DrawLine(x
+ 1, y
+ CUTOFF
+ 1, x
+ 1, y2
+ 1);
2139 dc
.SetPen(m_penHighlight
);
2140 // we need to continue one pixel further to overwrite the corner of
2141 // the border for the selected tab
2142 dc
.DrawLine(x
, y
- (flags
& wxCONTROL_SELECTED
? 1 : 0),
2144 dc
.DrawLine(x
, y2
- CUTOFF
, x
+ CUTOFF
, y2
);
2146 dc
.SetPen(m_penBlack
);
2147 dc
.DrawLine(x
+ CUTOFF
, y2
, x2
- CUTOFF
+ 1, y2
);
2148 dc
.DrawLine(x2
, y
, x2
, y2
- CUTOFF
);
2149 dc
.DrawLine(x2
, y2
- CUTOFF
, x2
- CUTOFF
, y2
);
2151 dc
.SetPen(m_penDarkGrey
);
2152 dc
.DrawLine(x
+ CUTOFF
, y2
- 1, x2
- CUTOFF
+ 1, y2
- 1);
2153 dc
.DrawLine(x2
- 1, y
, x2
- 1, y2
- CUTOFF
+ 1);
2155 if ( flags
& wxCONTROL_SELECTED
)
2157 dc
.SetPen(m_penLightGrey
);
2159 // overwrite the part of the (double!) border above this tab
2160 dc
.DrawLine(x
+ 1, y
- 1, x2
- 1, y
- 1);
2161 dc
.DrawLine(x
+ 1, y
- 2, x2
- 1, y
- 2);
2163 // and the shadow of the tab to the left of us
2164 dc
.DrawLine(x
+ 1, y2
- CUTOFF
, x
+ 1, y
- 1);
2170 wxFAIL_MSG(_T("TODO"));
2174 // ----------------------------------------------------------------------------
2176 // ----------------------------------------------------------------------------
2178 wxSize
wxWin32Renderer::GetSliderThumbSize(const wxRect
& rect
,
2179 wxOrientation orient
) const
2183 wxRect rectShaft
= GetSliderShaftRect(rect
, orient
);
2184 if ( orient
== wxHORIZONTAL
)
2186 size
.y
= rect
.height
- 6;
2187 size
.x
= wxMin(size
.y
/ 2, rectShaft
.width
);
2191 size
.x
= rect
.width
- 6;
2192 size
.y
= wxMin(size
.x
/ 2, rectShaft
.height
);
2198 wxRect
wxWin32Renderer::GetSliderShaftRect(const wxRect
& rectOrig
,
2199 wxOrientation orient
) const
2201 static const wxCoord SLIDER_MARGIN
= 6;
2203 wxRect rect
= rectOrig
;
2205 if ( orient
== wxHORIZONTAL
)
2207 // make the rect of minimal width and centre it
2208 rect
.height
= 2*BORDER_THICKNESS
;
2209 rect
.y
= rectOrig
.y
+ (rectOrig
.height
- rect
.height
) / 2;
2213 // leave margins on the sides
2214 rect
.Deflate(SLIDER_MARGIN
, 0);
2218 // same as above but in other direction
2219 rect
.width
= 2*BORDER_THICKNESS
;
2220 rect
.x
= rectOrig
.x
+ (rectOrig
.width
- rect
.width
) / 2;
2224 rect
.Deflate(0, SLIDER_MARGIN
);
2230 void wxWin32Renderer::DrawSliderShaft(wxDC
& dc
,
2231 const wxRect
& rectOrig
,
2232 wxOrientation orient
,
2236 if ( flags
& wxCONTROL_FOCUSED
)
2238 DrawFocusRect(dc
, rectOrig
);
2241 wxRect rect
= GetSliderShaftRect(rectOrig
, orient
);
2246 DrawSunkenBorder(dc
, &rect
);
2249 void wxWin32Renderer::DrawSliderThumb(wxDC
& dc
,
2251 wxOrientation orient
,
2255 we are drawing a shape of this form
2260 H DB where H is hightlight colour
2273 The interior of this shape is filled with the hatched brush if the thumb
2277 DrawBackground(dc
, wxNullColour
, rect
, flags
);
2279 bool transpose
= orient
== wxVERTICAL
;
2281 wxCoord x
, y
, x2
, y2
;
2286 x2
= rect
.GetBottom();
2287 y2
= rect
.GetRight();
2293 x2
= rect
.GetRight();
2294 y2
= rect
.GetBottom();
2297 // the size of the pointed part of the thumb
2298 wxCoord sizeArrow
= (transpose
? rect
.height
: rect
.width
) / 2;
2300 wxCoord x3
= x
+ sizeArrow
,
2301 y3
= y2
- sizeArrow
;
2303 dc
.SetPen(m_penHighlight
);
2304 DrawLine(dc
, x
, y
, x2
, y
, transpose
);
2305 DrawLine(dc
, x
, y
+ 1, x
, y2
- sizeArrow
, transpose
);
2306 DrawLine(dc
, x
, y3
, x3
, y2
, transpose
);
2308 dc
.SetPen(m_penBlack
);
2309 DrawLine(dc
, x3
, y2
, x2
, y3
, transpose
);
2310 DrawLine(dc
, x2
, y3
, x2
, y
- 1, transpose
);
2312 dc
.SetPen(m_penDarkGrey
);
2313 DrawLine(dc
, x3
, y2
- 1, x2
- 1, y3
, transpose
);
2314 DrawLine(dc
, x2
- 1, y3
, x2
- 1, y
, transpose
);
2316 if ( flags
& wxCONTROL_PRESSED
)
2318 // TODO: MSW fills the entire area inside, not just the rect
2319 wxRect rectInt
= rect
;
2321 rectInt
.SetRight(y3
);
2323 rectInt
.SetBottom(y3
);
2326 static const char *stipple_xpm
[] = {
2327 /* columns rows colors chars-per-pixel */
2335 dc
.SetBrush(wxBrush(stipple_xpm
));
2337 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, SHADOW_HIGHLIGHT
));
2338 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, CONTROL
));
2339 dc
.SetPen(*wxTRANSPARENT_PEN
);
2340 dc
.DrawRectangle(rectInt
);
2344 void wxWin32Renderer::DrawSliderTicks(wxDC
& dc
,
2346 const wxSize
& sizeThumb
,
2347 wxOrientation orient
,
2359 // the variable names correspond to horizontal case, but they can be used
2360 // for both orientations
2361 wxCoord x1
, x2
, y1
, y2
, len
, widthThumb
;
2362 if ( orient
== wxHORIZONTAL
)
2364 x1
= rect
.GetLeft();
2365 x2
= rect
.GetRight();
2367 // draw from bottom to top to leave one pixel space between the ticks
2368 // and the slider as Windows do
2369 y1
= rect
.GetBottom();
2374 widthThumb
= sizeThumb
.x
;
2379 x2
= rect
.GetBottom();
2381 y1
= rect
.GetRight();
2382 y2
= rect
.GetLeft();
2386 widthThumb
= sizeThumb
.y
;
2389 // the first tick should be positioned in such way that a thumb drawn in
2390 // the first position points down directly to it
2391 x1
+= widthThumb
/ 2;
2392 x2
-= widthThumb
/ 2;
2394 // this also means that we have slightly less space for the ticks in
2395 // between the first and the last
2398 dc
.SetPen(m_penBlack
);
2400 int range
= end
- start
;
2401 for ( int n
= 0; n
< range
; n
+= step
)
2403 wxCoord x
= x1
+ (len
*n
) / range
;
2405 DrawLine(dc
, x
, y1
, x
, y2
, orient
== wxVERTICAL
);
2408 // always draw the line at the end position
2409 DrawLine(dc
, x2
, y1
, x2
, y2
, orient
== wxVERTICAL
);
2412 // ----------------------------------------------------------------------------
2414 // ----------------------------------------------------------------------------
2418 // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2419 class WXDLLEXPORT wxWin32MenuGeometryInfo
: public wxMenuGeometryInfo
2422 virtual wxSize
GetSize() const { return m_size
; }
2424 wxCoord
GetLabelOffset() const { return m_ofsLabel
; }
2425 wxCoord
GetAccelOffset() const { return m_ofsAccel
; }
2427 wxCoord
GetItemHeight() const { return m_heightItem
; }
2430 // the total size of the menu
2433 // the offset of the start of the menu item label
2436 // the offset of the start of the accel label
2439 // the height of a normal (not separator) item
2440 wxCoord m_heightItem
;
2442 friend wxMenuGeometryInfo
*wxWin32Renderer::
2443 GetMenuGeometry(wxWindow
*, const wxMenu
&) const;
2446 #endif // wxUSE_MENUS
2448 // FIXME: all constants are hardcoded but shouldn't be
2449 static const wxCoord MENU_LEFT_MARGIN
= 9;
2450 static const wxCoord MENU_RIGHT_MARGIN
= 18;
2451 static const wxCoord MENU_VERT_MARGIN
= 3;
2453 // the margin around bitmap/check marks (on each side)
2454 static const wxCoord MENU_BMP_MARGIN
= 2;
2456 // the margin between the labels and accel strings
2457 static const wxCoord MENU_ACCEL_MARGIN
= 8;
2459 // the separator height in pixels: in fact, strangely enough, the real height
2460 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2462 static const wxCoord MENU_SEPARATOR_HEIGHT
= 3;
2464 // the size of the standard checkmark bitmap
2465 static const wxCoord MENU_CHECK_SIZE
= 9;
2467 // we can't implement these methods without wxMenuGeometryInfo implementation
2468 // which we don't have if !wxUSE_MENUS
2471 void wxWin32Renderer::DrawMenuBarItem(wxDC
& dc
,
2472 const wxRect
& rectOrig
,
2473 const wxString
& label
,
2477 wxRect rect
= rectOrig
;
2480 wxDCTextColourChanger
colChanger(dc
);
2482 if ( flags
& wxCONTROL_SELECTED
)
2484 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2486 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2487 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2488 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2489 dc
.DrawRectangle(rect
);
2492 // don't draw the focus rect around menu bar items
2493 DrawLabel(dc
, label
, rect
, flags
& ~wxCONTROL_FOCUSED
,
2494 wxALIGN_CENTRE
, indexAccel
);
2497 void wxWin32Renderer::DrawMenuItem(wxDC
& dc
,
2499 const wxMenuGeometryInfo
& gi
,
2500 const wxString
& label
,
2501 const wxString
& accel
,
2502 const wxBitmap
& bitmap
,
2506 const wxWin32MenuGeometryInfo
& geometryInfo
=
2507 (const wxWin32MenuGeometryInfo
&)gi
;
2512 rect
.width
= geometryInfo
.GetSize().x
;
2513 rect
.height
= geometryInfo
.GetItemHeight();
2515 // draw the selected item specially
2516 wxDCTextColourChanger
colChanger(dc
);
2517 if ( flags
& wxCONTROL_SELECTED
)
2519 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2521 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2522 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2523 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2524 dc
.DrawRectangle(rect
);
2527 // draw the bitmap: use the bitmap provided or the standard checkmark for
2528 // the checkable items
2529 wxBitmap bmp
= bitmap
;
2530 if ( !bmp
.Ok() && (flags
& wxCONTROL_CHECKED
) )
2532 bmp
= GetIndicator(IndicatorType_Menu
, flags
);
2537 rect
.SetRight(geometryInfo
.GetLabelOffset());
2538 wxControlRenderer::DrawBitmap(dc
, bmp
, rect
);
2542 rect
.x
= geometryInfo
.GetLabelOffset();
2543 rect
.SetRight(geometryInfo
.GetAccelOffset());
2545 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
, indexAccel
);
2547 // draw the accel string
2548 rect
.x
= geometryInfo
.GetAccelOffset();
2549 rect
.SetRight(geometryInfo
.GetSize().x
);
2551 // NB: no accel index here
2552 DrawLabel(dc
, accel
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
);
2554 // draw the submenu indicator
2555 if ( flags
& wxCONTROL_ISSUBMENU
)
2557 rect
.x
= geometryInfo
.GetSize().x
- MENU_RIGHT_MARGIN
;
2558 rect
.width
= MENU_RIGHT_MARGIN
;
2560 wxArrowStyle arrowStyle
;
2561 if ( flags
& wxCONTROL_DISABLED
)
2562 arrowStyle
= flags
& wxCONTROL_SELECTED
? Arrow_InversedDisabled
2564 else if ( flags
& wxCONTROL_SELECTED
)
2565 arrowStyle
= Arrow_Inversed
;
2567 arrowStyle
= Arrow_Normal
;
2569 DrawArrow(dc
, rect
, Arrow_Right
, arrowStyle
);
2573 void wxWin32Renderer::DrawMenuSeparator(wxDC
& dc
,
2575 const wxMenuGeometryInfo
& geomInfo
)
2577 DrawHorizontalLine(dc
, y
+ MENU_VERT_MARGIN
, 0, geomInfo
.GetSize().x
);
2580 wxSize
wxWin32Renderer::GetMenuBarItemSize(const wxSize
& sizeText
) const
2582 wxSize size
= sizeText
;
2584 // FIXME: menubar height is configurable under Windows
2591 wxMenuGeometryInfo
*wxWin32Renderer::GetMenuGeometry(wxWindow
*win
,
2592 const wxMenu
& menu
) const
2594 // prepare the dc: for now we draw all the items with the system font
2596 dc
.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
));
2598 // the height of a normal item
2599 wxCoord heightText
= dc
.GetCharHeight();
2604 // the max length of label and accel strings: the menu width is the sum of
2605 // them, even if they're for different items (as the accels should be
2608 // the max length of the bitmap is never 0 as Windows always leaves enough
2609 // space for a check mark indicator
2610 wxCoord widthLabelMax
= 0,
2612 widthBmpMax
= MENU_LEFT_MARGIN
;
2614 for ( wxMenuItemList::Node
*node
= menu
.GetMenuItems().GetFirst();
2616 node
= node
->GetNext() )
2618 // height of this item
2621 wxMenuItem
*item
= node
->GetData();
2622 if ( item
->IsSeparator() )
2624 h
= MENU_SEPARATOR_HEIGHT
;
2626 else // not separator
2631 dc
.GetTextExtent(item
->GetLabel(), &widthLabel
, NULL
);
2632 if ( widthLabel
> widthLabelMax
)
2634 widthLabelMax
= widthLabel
;
2638 dc
.GetTextExtent(item
->GetAccelString(), &widthAccel
, NULL
);
2639 if ( widthAccel
> widthAccelMax
)
2641 widthAccelMax
= widthAccel
;
2644 const wxBitmap
& bmp
= item
->GetBitmap();
2647 wxCoord widthBmp
= bmp
.GetWidth();
2648 if ( widthBmp
> widthBmpMax
)
2649 widthBmpMax
= widthBmp
;
2651 //else if ( item->IsCheckable() ): no need to check for this as
2652 // MENU_LEFT_MARGIN is big enough to show the check mark
2655 h
+= 2*MENU_VERT_MARGIN
;
2657 // remember the item position and height
2658 item
->SetGeometry(height
, h
);
2663 // bundle the metrics into a struct and return it
2664 wxWin32MenuGeometryInfo
*gi
= new wxWin32MenuGeometryInfo
;
2666 gi
->m_ofsLabel
= widthBmpMax
+ 2*MENU_BMP_MARGIN
;
2667 gi
->m_ofsAccel
= gi
->m_ofsLabel
+ widthLabelMax
;
2668 if ( widthAccelMax
> 0 )
2670 // if we actually have any accesl, add a margin
2671 gi
->m_ofsAccel
+= MENU_ACCEL_MARGIN
;
2674 gi
->m_heightItem
= heightText
+ 2*MENU_VERT_MARGIN
;
2676 gi
->m_size
.x
= gi
->m_ofsAccel
+ widthAccelMax
+ MENU_RIGHT_MARGIN
;
2677 gi
->m_size
.y
= height
;
2682 #else // !wxUSE_MENUS
2685 void wxWin32Renderer::DrawMenuBarItem(wxDC& WXUNUSED(dc),
2686 const wxRect& WXUNUSED(rectOrig),
2687 const wxString& WXUNUSED(label),
2688 int WXUNUSED(flags),
2689 int WXUNUSED(indexAccel))
2693 void wxWin32Renderer::DrawMenuItem(wxDC& WXUNUSED(dc),
2694 wxCoord WXUNUSED(y),
2695 const wxMenuGeometryInfo& WXUNUSED(gi),
2696 const wxString& WXUNUSED(label),
2697 const wxString& WXUNUSED(accel),
2698 const wxBitmap& WXUNUSED(bitmap),
2699 int WXUNUSED(flags),
2700 int WXUNUSED(indexAccel))
2704 void wxWin32Renderer::DrawMenuSeparator(wxDC& WXUNUSED(dc),
2705 wxCoord WXUNUSED(y),
2706 const wxMenuGeometryInfo& WXUNUSED(gi))
2710 wxSize wxWin32Renderer::GetMenuBarItemSize(const wxSize& size) const
2715 wxMenuGeometryInfo *
2716 wxWin32Renderer::GetMenuGeometry(wxWindow *WXUNUSED(win),
2717 const wxMenu& WXUNUSED(menu)) const
2723 #endif // wxUSE_MENUS/!wxUSE_MENUS
2725 // ----------------------------------------------------------------------------
2727 // ----------------------------------------------------------------------------
2729 void wxWin32Renderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
2730 wxBitmap
*bmpPressed
,
2731 wxBitmap
*bmpDisabled
)
2733 static const wxCoord widthCombo
= 16;
2734 static const wxCoord heightCombo
= 17;
2740 bmpNormal
->Create(widthCombo
, heightCombo
);
2741 dcMem
.SelectObject(*bmpNormal
);
2742 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2743 Arrow_Down
, Arrow_Normal
);
2748 bmpPressed
->Create(widthCombo
, heightCombo
);
2749 dcMem
.SelectObject(*bmpPressed
);
2750 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2751 Arrow_Down
, Arrow_Pressed
);
2756 bmpDisabled
->Create(widthCombo
, heightCombo
);
2757 dcMem
.SelectObject(*bmpDisabled
);
2758 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2759 Arrow_Down
, Arrow_Disabled
);
2763 // ----------------------------------------------------------------------------
2765 // ----------------------------------------------------------------------------
2767 void wxWin32Renderer::DoDrawBackground(wxDC
& dc
,
2768 const wxColour
& col
,
2771 wxBrush
brush(col
, wxSOLID
);
2773 dc
.SetPen(*wxTRANSPARENT_PEN
);
2774 dc
.DrawRectangle(rect
);
2777 void wxWin32Renderer::DrawBackground(wxDC
& dc
,
2778 const wxColour
& col
,
2782 // just fill it with the given or default bg colour
2783 wxColour colBg
= col
.Ok() ? col
: wxSCHEME_COLOUR(m_scheme
, CONTROL
);
2784 DoDrawBackground(dc
, colBg
, rect
);
2787 // ----------------------------------------------------------------------------
2789 // ----------------------------------------------------------------------------
2791 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2796 // get the bitmap for this arrow
2797 wxArrowDirection arrowDir
;
2800 case wxLEFT
: arrowDir
= Arrow_Left
; break;
2801 case wxRIGHT
: arrowDir
= Arrow_Right
; break;
2802 case wxUP
: arrowDir
= Arrow_Up
; break;
2803 case wxDOWN
: arrowDir
= Arrow_Down
; break;
2806 wxFAIL_MSG(_T("unknown arrow direction"));
2810 wxArrowStyle arrowStyle
;
2811 if ( flags
& wxCONTROL_PRESSED
)
2813 // can't be pressed and disabled
2814 arrowStyle
= Arrow_Pressed
;
2818 arrowStyle
= flags
& wxCONTROL_DISABLED
? Arrow_Disabled
: Arrow_Normal
;
2821 DrawArrowButton(dc
, rect
, arrowDir
, arrowStyle
);
2824 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2826 wxArrowDirection arrowDir
,
2827 wxArrowStyle arrowStyle
)
2829 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
2831 // under Windows the arrows always have the same size so just centre it in
2832 // the provided rectangle
2833 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
2834 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
2836 // Windows does it like this...
2837 if ( arrowDir
== Arrow_Left
)
2841 dc
.DrawBitmap(bmp
, x
, y
, TRUE
/* use mask */);
2844 void wxWin32Renderer::DrawArrowButton(wxDC
& dc
,
2845 const wxRect
& rectAll
,
2846 wxArrowDirection arrowDir
,
2847 wxArrowStyle arrowStyle
)
2849 wxRect rect
= rectAll
;
2850 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2851 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
2852 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
2855 void wxWin32Renderer::DrawScrollbarThumb(wxDC
& dc
,
2856 wxOrientation orient
,
2860 // we don't use the flags, the thumb never changes appearance
2861 wxRect rectThumb
= rect
;
2862 DrawArrowBorder(dc
, &rectThumb
);
2863 DrawBackground(dc
, wxNullColour
, rectThumb
);
2866 void wxWin32Renderer::DrawScrollbarShaft(wxDC
& dc
,
2867 wxOrientation orient
,
2868 const wxRect
& rectBar
,
2871 wxColourScheme::StdColour col
= flags
& wxCONTROL_PRESSED
2872 ? wxColourScheme::SCROLLBAR_PRESSED
2873 : wxColourScheme::SCROLLBAR
;
2874 DoDrawBackground(dc
, m_scheme
->Get(col
), rectBar
);
2877 void wxWin32Renderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
2879 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2882 wxRect
wxWin32Renderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
2883 wxScrollBar::Element elem
,
2886 return StandardGetScrollbarRect(scrollbar
, elem
,
2887 thumbPos
, m_sizeScrollbarArrow
);
2890 wxCoord
wxWin32Renderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
2892 return StandardScrollBarSize(scrollbar
, m_sizeScrollbarArrow
);
2895 wxHitTest
wxWin32Renderer::HitTestScrollbar(const wxScrollBar
*scrollbar
,
2896 const wxPoint
& pt
) const
2898 return StandardHitTestScrollbar(scrollbar
, pt
, m_sizeScrollbarArrow
);
2901 wxCoord
wxWin32Renderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
2904 return StandardScrollbarToPixel(scrollbar
, thumbPos
, m_sizeScrollbarArrow
);
2907 int wxWin32Renderer::PixelToScrollbar(const wxScrollBar
*scrollbar
,
2910 return StandardPixelToScrollbar(scrollbar
, coord
, m_sizeScrollbarArrow
);
2913 // ----------------------------------------------------------------------------
2914 // text control geometry
2915 // ----------------------------------------------------------------------------
2917 static inline int GetTextBorderWidth()
2922 wxRect
wxWin32Renderer::GetTextTotalArea(const wxTextCtrl
*text
,
2925 wxRect rectTotal
= rect
;
2927 wxCoord widthBorder
= GetTextBorderWidth();
2928 rectTotal
.Inflate(widthBorder
);
2930 // this is what Windows does
2936 wxRect
wxWin32Renderer::GetTextClientArea(const wxTextCtrl
*text
,
2938 wxCoord
*extraSpaceBeyond
)
2940 wxRect rectText
= rect
;
2942 // undo GetTextTotalArea()
2943 if ( rectText
.height
> 0 )
2946 wxCoord widthBorder
= GetTextBorderWidth();
2947 rectText
.Inflate(-widthBorder
);
2949 if ( extraSpaceBeyond
)
2950 *extraSpaceBeyond
= 0;
2955 // ----------------------------------------------------------------------------
2957 // ----------------------------------------------------------------------------
2959 void wxWin32Renderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
2962 if ( wxDynamicCast(window
, wxScrollBar
) )
2964 // we only set the width of vert scrollbars and height of the
2966 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
2967 size
->y
= m_sizeScrollbarArrow
.y
;
2969 size
->x
= m_sizeScrollbarArrow
.x
;
2971 // skip border width adjustments, they don't make sense for us
2974 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
2977 if ( wxDynamicCast(window
, wxButton
) )
2980 size
->x
+= 3*window
->GetCharWidth();
2981 #if 0 // do allow creating small buttons if wanted
2982 wxSize sizeDef
= wxButton::GetDefaultSize();
2983 if ( size
->x
< sizeDef
.x
)
2984 size
->x
= sizeDef
.x
;
2987 wxCoord heightBtn
= (11*(window
->GetCharHeight() + 8))/10;
2988 if ( size
->y
< heightBtn
- 8 )
2989 size
->y
= heightBtn
;
2993 // no border width adjustments for buttons
2996 #endif // wxUSE_BUTTON
2998 // take into account the border width
2999 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
3000 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
3001 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
3004 // ============================================================================
3006 // ============================================================================
3008 // ----------------------------------------------------------------------------
3009 // wxWin32InputHandler
3010 // ----------------------------------------------------------------------------
3012 wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer
*renderer
)
3014 m_renderer
= renderer
;
3017 bool wxWin32InputHandler::HandleKey(wxControl
*control
,
3018 const wxKeyEvent
& event
,
3024 bool wxWin32InputHandler::HandleMouse(wxControl
*control
,
3025 const wxMouseEvent
& event
)
3030 // ----------------------------------------------------------------------------
3031 // wxWin32ScrollBarInputHandler
3032 // ----------------------------------------------------------------------------
3034 wxWin32ScrollBarInputHandler::
3035 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
3036 wxInputHandler
*handler
)
3037 : wxStdScrollBarInputHandler(renderer
, handler
)
3039 m_scrollPaused
= FALSE
;
3043 bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar
*scrollbar
,
3044 const wxControlAction
& action
)
3046 // stop if went beyond the position of the original click (this can only
3047 // happen when we scroll by pages)
3049 if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
3051 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3052 != wxHT_SCROLLBAR_BAR_2
;
3054 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
3056 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3057 != wxHT_SCROLLBAR_BAR_1
;
3062 StopScrolling(scrollbar
);
3064 scrollbar
->Refresh();
3069 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar
, action
);
3072 bool wxWin32ScrollBarInputHandler::HandleMouse(wxControl
*control
,
3073 const wxMouseEvent
& event
)
3075 // remember the current state
3076 bool wasDraggingThumb
= m_htLast
== wxHT_SCROLLBAR_THUMB
;
3078 // do process the message
3079 bool rc
= wxStdScrollBarInputHandler::HandleMouse(control
, event
);
3081 // analyse the changes
3082 if ( !wasDraggingThumb
&& (m_htLast
== wxHT_SCROLLBAR_THUMB
) )
3084 // we just started dragging the thumb, remember its initial position to
3085 // be able to restore it if the drag is cancelled later
3086 m_eventStartDrag
= event
;
3092 bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl
*control
,
3093 const wxMouseEvent
& event
)
3095 // we don't highlight scrollbar elements, so there is no need to process
3096 // mouse move events normally - only do it while mouse is captured (i.e.
3097 // when we're dragging the thumb or pressing on something)
3098 if ( !m_winCapture
)
3101 if ( event
.Entering() )
3103 // we're not interested in this at all
3107 wxScrollBar
*scrollbar
= wxStaticCast(control
, wxScrollBar
);
3109 if ( m_scrollPaused
)
3111 // check if the mouse returned to its original location
3113 if ( event
.Leaving() )
3119 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3120 if ( ht
== m_htLast
)
3122 // yes it did, resume scrolling
3123 m_scrollPaused
= FALSE
;
3124 if ( m_timerScroll
)
3126 // we were scrolling by line/page, restart timer
3127 m_timerScroll
->Start(m_interval
);
3129 Press(scrollbar
, TRUE
);
3131 else // we were dragging the thumb
3133 // restore its last location
3134 HandleThumbMove(scrollbar
, m_eventLastDrag
);
3140 else // normal case, scrolling hasn't been paused
3142 // if we're scrolling the scrollbar because the arrow or the shaft was
3143 // pressed, check that the mouse stays on the same scrollbar element
3145 if ( event
.Moving() )
3147 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3149 else // event.Leaving()
3154 // if we're dragging the thumb and the mouse stays in the scrollbar, it
3155 // is still ok - we only want to catch the case when the mouse leaves
3156 // the scrollbar here
3157 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
&& ht
!= wxHT_NOWHERE
)
3159 ht
= wxHT_SCROLLBAR_THUMB
;
3162 if ( ht
!= m_htLast
)
3164 // what were we doing? 2 possibilities: either an arrow/shaft was
3165 // pressed in which case we have a timer and so we just stop it or
3166 // we were dragging the thumb
3167 if ( m_timerScroll
)
3170 m_interval
= m_timerScroll
->GetInterval();
3171 m_timerScroll
->Stop();
3172 m_scrollPaused
= TRUE
;
3174 // unpress the arrow
3175 Press(scrollbar
, FALSE
);
3177 else // we were dragging the thumb
3179 // remember the current thumb position to be able to restore it
3180 // if the mouse returns to it later
3181 m_eventLastDrag
= event
;
3183 // and restore the original position (before dragging) of the
3185 HandleThumbMove(scrollbar
, m_eventStartDrag
);
3192 return wxStdScrollBarInputHandler::HandleMouseMove(control
, event
);
3195 // ----------------------------------------------------------------------------
3196 // wxWin32CheckboxInputHandler
3197 // ----------------------------------------------------------------------------
3199 bool wxWin32CheckboxInputHandler::HandleKey(wxControl
*control
,
3200 const wxKeyEvent
& event
,
3205 wxControlAction action
;
3206 int keycode
= event
.GetKeyCode();
3210 action
= wxACTION_CHECKBOX_TOGGLE
;
3214 case WXK_NUMPAD_SUBTRACT
:
3215 action
= wxACTION_CHECKBOX_CHECK
;
3219 case WXK_NUMPAD_ADD
:
3220 case WXK_NUMPAD_EQUAL
:
3221 action
= wxACTION_CHECKBOX_CLEAR
;
3227 control
->PerformAction(action
);
3236 // ----------------------------------------------------------------------------
3237 // wxWin32TextCtrlInputHandler
3238 // ----------------------------------------------------------------------------
3240 bool wxWin32TextCtrlInputHandler::HandleKey(wxControl
*control
,
3241 const wxKeyEvent
& event
,
3244 // handle only MSW-specific text bindings here, the others are handled in
3248 int keycode
= event
.GetKeyCode();
3250 wxControlAction action
;
3251 if ( keycode
== WXK_DELETE
&& event
.ShiftDown() )
3253 action
= wxACTION_TEXT_CUT
;
3255 else if ( keycode
== WXK_INSERT
)
3257 if ( event
.ControlDown() )
3258 action
= wxACTION_TEXT_COPY
;
3259 else if ( event
.ShiftDown() )
3260 action
= wxACTION_TEXT_PASTE
;
3263 if ( action
!= wxACTION_NONE
)
3265 control
->PerformAction(action
);
3271 return wxStdTextCtrlInputHandler::HandleKey(control
, event
, pressed
);