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 // ----------------------------------------------------------------------------
92 // wxWin32Renderer: draw the GUI elements in Win32 style
93 // ----------------------------------------------------------------------------
95 class wxWin32Renderer
: public wxRenderer
114 Arrow_InversedDisabled
,
119 wxWin32Renderer(const wxColourScheme
*scheme
);
121 // implement the base class pure virtuals
122 virtual void DrawBackground(wxDC
& dc
,
126 virtual void DrawLabel(wxDC
& dc
,
127 const wxString
& label
,
130 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
132 wxRect
*rectBounds
= NULL
);
133 virtual void DrawButtonLabel(wxDC
& dc
,
134 const wxString
& label
,
135 const wxBitmap
& image
,
138 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
140 wxRect
*rectBounds
= NULL
);
141 virtual void DrawBorder(wxDC
& dc
,
145 wxRect
*rectIn
= (wxRect
*)NULL
);
146 virtual void DrawHorizontalLine(wxDC
& dc
,
147 wxCoord y
, wxCoord x1
, wxCoord x2
);
148 virtual void DrawVerticalLine(wxDC
& dc
,
149 wxCoord x
, wxCoord y1
, wxCoord y2
);
150 virtual void DrawFrame(wxDC
& dc
,
151 const wxString
& label
,
154 int alignment
= wxALIGN_LEFT
,
155 int indexAccel
= -1);
156 virtual void DrawTextBorder(wxDC
& dc
,
160 wxRect
*rectIn
= (wxRect
*)NULL
);
161 virtual void DrawButtonBorder(wxDC
& dc
,
164 wxRect
*rectIn
= (wxRect
*)NULL
);
165 virtual void DrawArrow(wxDC
& dc
,
169 virtual void DrawScrollbarArrow(wxDC
& dc
,
173 { DrawArrow(dc
, dir
, rect
, flags
); }
174 virtual void DrawScrollbarThumb(wxDC
& dc
,
175 wxOrientation orient
,
178 virtual void DrawScrollbarShaft(wxDC
& dc
,
179 wxOrientation orient
,
182 virtual void DrawScrollCorner(wxDC
& dc
,
184 virtual void DrawItem(wxDC
& dc
,
185 const wxString
& label
,
188 virtual void DrawCheckItem(wxDC
& dc
,
189 const wxString
& label
,
190 const wxBitmap
& bitmap
,
193 virtual void DrawCheckButton(wxDC
& dc
,
194 const wxString
& label
,
195 const wxBitmap
& bitmap
,
198 wxAlignment align
= wxALIGN_LEFT
,
199 int indexAccel
= -1);
200 virtual void DrawRadioButton(wxDC
& dc
,
201 const wxString
& label
,
202 const wxBitmap
& bitmap
,
205 wxAlignment align
= wxALIGN_LEFT
,
206 int indexAccel
= -1);
207 virtual void DrawTextLine(wxDC
& dc
,
208 const wxString
& text
,
213 virtual void DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
);
214 virtual void DrawTab(wxDC
& dc
,
217 const wxString
& label
,
218 const wxBitmap
& bitmap
= wxNullBitmap
,
220 int indexAccel
= -1);
222 virtual void DrawSliderShaft(wxDC
& dc
,
224 wxOrientation orient
,
226 wxRect
*rectShaft
= NULL
);
227 virtual void DrawSliderThumb(wxDC
& dc
,
229 wxOrientation orient
,
231 virtual void DrawSliderTicks(wxDC
& dc
,
233 const wxSize
& sizeThumb
,
234 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); }
302 virtual wxSize
GetMenuBarItemSize(const wxSize
& sizeText
) const;
303 virtual wxMenuGeometryInfo
*GetMenuGeometry(wxWindow
*win
,
304 const wxMenu
& menu
) const;
307 // helper of DrawLabel() and DrawCheckOrRadioButton()
308 void DoDrawLabel(wxDC
& dc
,
309 const wxString
& label
,
312 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
314 wxRect
*rectBounds
= NULL
,
315 const wxPoint
& focusOffset
316 = wxPoint(FOCUS_RECT_OFFSET_X
, FOCUS_RECT_OFFSET_Y
));
318 // common part of DrawLabel() and DrawItem()
319 void DrawFocusRect(wxDC
& dc
, const wxRect
& rect
);
321 // DrawLabel() and DrawButtonLabel() helper
322 void DrawLabelShadow(wxDC
& dc
,
323 const wxString
& label
,
328 // DrawButtonBorder() helper
329 void DoDrawBackground(wxDC
& dc
,
333 // DrawBorder() helpers: all of them shift and clip the DC after drawing
336 // just draw a rectangle with the given pen
337 void DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
339 // draw the lower left part of rectangle
340 void DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
342 // draw the rectange using the first brush for the left and top sides and
343 // the second one for the bottom and right ones
344 void DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
345 const wxPen
& pen1
, const wxPen
& pen2
);
347 // draw the normal 3D border
348 void DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
);
350 // draw the sunken 3D border
351 void DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
);
353 // draw the border used for scrollbar arrows
354 void DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
= FALSE
);
356 // public DrawArrow()s helper
357 void DrawArrow(wxDC
& dc
, const wxRect
& rect
,
358 wxArrowDirection arrowDir
, wxArrowStyle arrowStyle
);
360 // DrawArrowButton is used by DrawScrollbar and DrawComboButton
361 void DrawArrowButton(wxDC
& dc
, const wxRect
& rect
,
362 wxArrowDirection arrowDir
,
363 wxArrowStyle arrowStyle
);
365 // DrawCheckButton/DrawRadioButton helper
366 void DrawCheckOrRadioButton(wxDC
& dc
,
367 const wxString
& label
,
368 const wxBitmap
& bitmap
,
373 wxCoord focusOffsetY
);
375 // draw a normal or transposed line (useful for using the same code fo both
376 // horizontal and vertical widgets)
377 void DrawLine(wxDC
& dc
,
378 wxCoord x1
, wxCoord y1
,
379 wxCoord x2
, wxCoord y2
,
380 bool transpose
= FALSE
)
383 dc
.DrawLine(y1
, x1
, y2
, x2
);
385 dc
.DrawLine(x1
, y1
, x2
, y2
);
388 // get the standard check/radio button bitmap
389 wxBitmap
GetIndicator(IndicatorType indType
, int flags
);
390 wxBitmap
GetCheckBitmap(int flags
)
391 { return GetIndicator(IndicatorType_Check
, flags
); }
392 wxBitmap
GetRadioBitmap(int flags
)
393 { return GetIndicator(IndicatorType_Radio
, flags
); }
396 const wxColourScheme
*m_scheme
;
398 // the sizing parameters (TODO make them changeable)
399 wxSize m_sizeScrollbarArrow
;
401 // GDI objects we use for drawing
402 wxColour m_colDarkGrey
,
410 // first row is for the normal state, second - for the disabled
411 wxBitmap m_bmpArrows
[Arrow_StateMax
][Arrow_Max
];
414 // ----------------------------------------------------------------------------
415 // wxWin32InputHandler and derived classes: process the keyboard and mouse
416 // messages according to Windows standards
417 // ----------------------------------------------------------------------------
419 class wxWin32InputHandler
: public wxInputHandler
422 wxWin32InputHandler(wxWin32Renderer
*renderer
);
424 virtual bool HandleKey(wxControl
*control
,
425 const wxKeyEvent
& event
,
427 virtual bool HandleMouse(wxControl
*control
,
428 const wxMouseEvent
& event
);
431 wxWin32Renderer
*m_renderer
;
434 class wxWin32ScrollBarInputHandler
: public wxStdScrollBarInputHandler
437 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
438 wxInputHandler
*handler
);
440 virtual bool HandleMouse(wxControl
*control
, const wxMouseEvent
& event
);
441 virtual bool HandleMouseMove(wxControl
*control
, const wxMouseEvent
& event
);
443 virtual bool OnScrollTimer(wxScrollBar
*scrollbar
,
444 const wxControlAction
& action
);
447 virtual bool IsAllowedButton(int button
) { return button
== 1; }
449 virtual void Highlight(wxScrollBar
*scrollbar
, bool doIt
)
451 // we don't highlight anything
454 // the first and last event which caused the thumb to move
455 wxMouseEvent m_eventStartDrag
,
458 // have we paused the scrolling because the mouse moved?
461 // we remember the interval of the timer to be able to restart it
465 class wxWin32CheckboxInputHandler
: public wxStdCheckboxInputHandler
468 wxWin32CheckboxInputHandler(wxInputHandler
*handler
)
469 : wxStdCheckboxInputHandler(handler
) { }
471 virtual bool HandleKey(wxControl
*control
,
472 const wxKeyEvent
& event
,
476 class wxWin32TextCtrlInputHandler
: public wxStdTextCtrlInputHandler
479 wxWin32TextCtrlInputHandler(wxInputHandler
*handler
)
480 : wxStdTextCtrlInputHandler(handler
) { }
482 virtual bool HandleKey(wxControl
*control
,
483 const wxKeyEvent
& event
,
487 // ----------------------------------------------------------------------------
488 // wxWin32ColourScheme: uses (default) Win32 colours
489 // ----------------------------------------------------------------------------
491 class wxWin32ColourScheme
: public wxColourScheme
494 virtual wxColour
Get(StdColour col
) const;
495 virtual wxColour
GetBackground(wxWindow
*win
) const;
498 // ----------------------------------------------------------------------------
500 // ----------------------------------------------------------------------------
502 WX_DEFINE_ARRAY(wxInputHandler
*, wxArrayHandlers
);
504 class wxWin32Theme
: public wxTheme
508 virtual ~wxWin32Theme();
510 virtual wxRenderer
*GetRenderer() { return m_renderer
; }
511 virtual wxInputHandler
*GetInputHandler(const wxString
& control
);
512 virtual wxColourScheme
*GetColourScheme();
515 // get the default input handler
516 wxInputHandler
*GetDefaultInputHandler();
518 wxWin32Renderer
*m_renderer
;
520 // the names of the already created handlers and the handlers themselves
521 // (these arrays are synchronized)
522 wxSortedArrayString m_handlerNames
;
523 wxArrayHandlers m_handlers
;
525 wxWin32InputHandler
*m_handlerDefault
;
527 wxWin32ColourScheme
*m_scheme
;
529 WX_DECLARE_THEME(win32
)
532 // ----------------------------------------------------------------------------
534 // ----------------------------------------------------------------------------
538 static const char *checked_menu_xpm
[] = {
539 /* columns rows colors chars-per-pixel */
555 static const char *selected_checked_menu_xpm
[] = {
556 /* columns rows colors chars-per-pixel */
572 static const char *disabled_checked_menu_xpm
[] = {
573 /* columns rows colors chars-per-pixel */
590 static const char *selected_disabled_checked_menu_xpm
[] = {
591 /* columns rows colors chars-per-pixel */
607 // checkbox and radiobox bitmaps below
609 static const char *checked_xpm
[] = {
610 /* columns rows colors chars-per-pixel */
633 static const char *pressed_checked_xpm
[] = {
634 /* columns rows colors chars-per-pixel */
656 static const char *pressed_disabled_checked_xpm
[] = {
657 /* columns rows colors chars-per-pixel */
679 static const char *checked_item_xpm
[] = {
680 /* columns rows colors chars-per-pixel */
701 static const char *unchecked_xpm
[] = {
702 /* columns rows colors chars-per-pixel */
725 static const char *pressed_unchecked_xpm
[] = {
726 /* columns rows colors chars-per-pixel */
748 static const char *unchecked_item_xpm
[] = {
749 /* columns rows colors chars-per-pixel */
769 static const char *checked_radio_xpm
[] = {
770 /* columns rows colors chars-per-pixel */
793 static const char *pressed_checked_radio_xpm
[] = {
794 /* columns rows colors chars-per-pixel */
817 static const char *pressed_disabled_checked_radio_xpm
[] = {
818 /* columns rows colors chars-per-pixel */
841 static const char *unchecked_radio_xpm
[] = {
842 /* columns rows colors chars-per-pixel */
865 static const char *pressed_unchecked_radio_xpm
[] = {
866 /* columns rows colors chars-per-pixel */
890 bmpIndicators
[IndicatorType_Max
][IndicatorState_Max
][IndicatorStatus_Max
] =
895 { checked_xpm
, unchecked_xpm
},
898 { pressed_checked_xpm
, pressed_unchecked_xpm
},
901 { pressed_disabled_checked_xpm
, pressed_unchecked_xpm
},
907 { checked_radio_xpm
, unchecked_radio_xpm
},
910 { pressed_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
913 { pressed_disabled_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
919 { checked_menu_xpm
, NULL
},
922 { selected_checked_menu_xpm
, NULL
},
925 { disabled_checked_menu_xpm
, NULL
},
927 // disabled selected state
928 { selected_disabled_checked_menu_xpm
, NULL
},
932 // ============================================================================
934 // ============================================================================
936 WX_IMPLEMENT_THEME(wxWin32Theme
, win32
, wxTRANSLATE("Win32 theme"));
938 // ----------------------------------------------------------------------------
940 // ----------------------------------------------------------------------------
942 wxWin32Theme::wxWin32Theme()
944 m_scheme
= new wxWin32ColourScheme
;
945 m_renderer
= new wxWin32Renderer(m_scheme
);
946 m_handlerDefault
= NULL
;
949 wxWin32Theme::~wxWin32Theme()
951 size_t count
= m_handlers
.GetCount();
952 for ( size_t n
= 0; n
< count
; n
++ )
954 if ( m_handlers
[n
] != m_handlerDefault
)
955 delete m_handlers
[n
];
958 delete m_handlerDefault
;
964 wxInputHandler
*wxWin32Theme::GetDefaultInputHandler()
966 if ( !m_handlerDefault
)
968 m_handlerDefault
= new wxWin32InputHandler(m_renderer
);
971 return m_handlerDefault
;
974 wxInputHandler
*wxWin32Theme::GetInputHandler(const wxString
& control
)
976 wxInputHandler
*handler
;
977 int n
= m_handlerNames
.Index(control
);
978 if ( n
== wxNOT_FOUND
)
980 // create a new handler
981 if ( control
== wxINP_HANDLER_SCROLLBAR
)
982 handler
= new wxWin32ScrollBarInputHandler(m_renderer
,
983 GetDefaultInputHandler());
985 else if ( control
== wxINP_HANDLER_BUTTON
)
986 handler
= new wxStdButtonInputHandler(GetDefaultInputHandler());
987 #endif // wxUSE_BUTTON
989 else if ( control
== wxINP_HANDLER_CHECKBOX
)
990 handler
= new wxWin32CheckboxInputHandler(GetDefaultInputHandler());
991 #endif // wxUSE_CHECKBOX
993 else if ( control
== wxINP_HANDLER_COMBOBOX
)
994 handler
= new wxStdComboBoxInputHandler(GetDefaultInputHandler());
995 #endif // wxUSE_COMBOBOX
997 else if ( control
== wxINP_HANDLER_LISTBOX
)
998 handler
= new wxStdListboxInputHandler(GetDefaultInputHandler());
999 #endif // wxUSE_LISTBOX
1000 #if wxUSE_CHECKLISTBOX
1001 else if ( control
== wxINP_HANDLER_CHECKLISTBOX
)
1002 handler
= new wxStdCheckListboxInputHandler(GetDefaultInputHandler());
1003 #endif // wxUSE_CHECKLISTBOX
1005 else if ( control
== wxINP_HANDLER_TEXTCTRL
)
1006 handler
= new wxWin32TextCtrlInputHandler(GetDefaultInputHandler());
1007 #endif // wxUSE_TEXTCTRL
1009 else if ( control
== wxINP_HANDLER_SLIDER
)
1010 handler
= new wxStdSliderButtonInputHandler(GetDefaultInputHandler());
1011 #endif // wxUSE_SLIDER
1013 else if ( control
== wxINP_HANDLER_SPINBTN
)
1014 handler
= new wxStdSpinButtonInputHandler(GetDefaultInputHandler());
1015 #endif // wxUSE_SPINBTN
1017 else if ( control
== wxINP_HANDLER_NOTEBOOK
)
1018 handler
= new wxStdNotebookInputHandler(GetDefaultInputHandler());
1019 #endif // wxUSE_NOTEBOOK
1021 handler
= GetDefaultInputHandler();
1023 n
= m_handlerNames
.Add(control
);
1024 m_handlers
.Insert(handler
, n
);
1026 else // we already have it
1028 handler
= m_handlers
[n
];
1034 wxColourScheme
*wxWin32Theme::GetColourScheme()
1039 // ============================================================================
1040 // wxWin32ColourScheme
1041 // ============================================================================
1043 wxColour
wxWin32ColourScheme::GetBackground(wxWindow
*win
) const
1046 if ( win
->UseBgCol() )
1048 // use the user specified colour
1049 col
= win
->GetBackgroundColour();
1052 if ( win
->IsContainerWindow() )
1054 wxTextCtrl
*text
= wxDynamicCast(win
, wxTextCtrl
);
1057 if ( !text
->IsEnabled() ) // not IsEditable()
1059 //else: execute code below
1064 // doesn't depend on the state
1070 int flags
= win
->GetStateFlags();
1072 // the colour set by the user should be used for the normal state
1073 // and for the states for which we don't have any specific colours
1074 if ( !col
.Ok() || (flags
!= 0) )
1076 if ( wxDynamicCast(win
, wxScrollBar
) )
1077 col
= Get(flags
& wxCONTROL_PRESSED
? SCROLLBAR_PRESSED
1087 wxColour
wxWin32ColourScheme::Get(wxWin32ColourScheme::StdColour col
) const
1091 case WINDOW
: return *wxWHITE
;
1093 case CONTROL_PRESSED
:
1094 case CONTROL_CURRENT
:
1095 case CONTROL
: return wxColour(0xc0c0c0);
1097 case CONTROL_TEXT
: return *wxBLACK
;
1099 case SCROLLBAR
: return wxColour(0xe0e0e0);
1100 case SCROLLBAR_PRESSED
: return *wxBLACK
;
1102 case HIGHLIGHT
: return wxColour(0x800000);
1103 case HIGHLIGHT_TEXT
: return wxColour(0xffffff);
1105 case SHADOW_DARK
: return *wxBLACK
;
1107 case CONTROL_TEXT_DISABLED
:
1108 case SHADOW_HIGHLIGHT
: return wxColour(0xe0e0e0);
1110 case SHADOW_IN
: return wxColour(0xc0c0c0);
1112 case CONTROL_TEXT_DISABLED_SHADOW
:
1113 case SHADOW_OUT
: return wxColour(0x7f7f7f);
1117 wxFAIL_MSG(_T("invalid standard colour"));
1122 // ============================================================================
1124 // ============================================================================
1126 // ----------------------------------------------------------------------------
1128 // ----------------------------------------------------------------------------
1130 wxWin32Renderer::wxWin32Renderer(const wxColourScheme
*scheme
)
1134 m_sizeScrollbarArrow
= wxSize(16, 16);
1136 // init colours and pens
1137 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
), 0, wxSOLID
);
1139 m_colDarkGrey
= wxSCHEME_COLOUR(scheme
, SHADOW_OUT
);
1140 m_penDarkGrey
= wxPen(m_colDarkGrey
, 0, wxSOLID
);
1142 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
), 0, wxSOLID
);
1144 m_colHighlight
= wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
);
1145 m_penHighlight
= wxPen(m_colHighlight
, 0, wxSOLID
);
1147 // init the arrow bitmaps
1148 static const size_t ARROW_WIDTH
= 7;
1149 static const size_t ARROW_LENGTH
= 4;
1152 wxMemoryDC dcNormal
,
1155 for ( size_t n
= 0; n
< Arrow_Max
; n
++ )
1157 bool isVertical
= n
> Arrow_Right
;
1170 // disabled arrow is larger because of the shadow
1171 m_bmpArrows
[Arrow_Normal
][n
].Create(w
, h
);
1172 m_bmpArrows
[Arrow_Disabled
][n
].Create(w
+ 1, h
+ 1);
1174 dcNormal
.SelectObject(m_bmpArrows
[Arrow_Normal
][n
]);
1175 dcDisabled
.SelectObject(m_bmpArrows
[Arrow_Disabled
][n
]);
1177 dcNormal
.SetBackground(*wxWHITE_BRUSH
);
1178 dcDisabled
.SetBackground(*wxWHITE_BRUSH
);
1182 dcNormal
.SetPen(m_penBlack
);
1183 dcDisabled
.SetPen(m_penDarkGrey
);
1185 // calculate the position of the point of the arrow
1189 x1
= (ARROW_WIDTH
- 1)/2;
1190 y1
= n
== Arrow_Up
? 0 : ARROW_LENGTH
- 1;
1194 x1
= n
== Arrow_Left
? 0 : ARROW_LENGTH
- 1;
1195 y1
= (ARROW_WIDTH
- 1)/2;
1206 for ( size_t i
= 0; i
< ARROW_LENGTH
; i
++ )
1208 dcNormal
.DrawLine(x1
, y1
, x2
, y2
);
1209 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1216 if ( n
== Arrow_Up
)
1227 else // left or right arrow
1232 if ( n
== Arrow_Left
)
1245 // draw the shadow for the disabled one
1246 dcDisabled
.SetPen(m_penHighlight
);
1251 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1255 x1
= ARROW_LENGTH
- 1;
1256 y1
= (ARROW_WIDTH
- 1)/2 + 1;
1259 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1260 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1265 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1269 x1
= ARROW_WIDTH
- 1;
1271 x2
= (ARROW_WIDTH
- 1)/2;
1273 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1274 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1279 // create the inversed bitmap but only for the right arrow as we only
1280 // use it for the menus
1281 if ( n
== Arrow_Right
)
1283 m_bmpArrows
[Arrow_Inversed
][n
].Create(w
, h
);
1284 dcInverse
.SelectObject(m_bmpArrows
[Arrow_Inversed
][n
]);
1286 dcInverse
.Blit(0, 0, w
, h
,
1289 dcInverse
.SelectObject(wxNullBitmap
);
1291 mask
= new wxMask(m_bmpArrows
[Arrow_Inversed
][n
], *wxBLACK
);
1292 m_bmpArrows
[Arrow_Inversed
][n
].SetMask(mask
);
1294 m_bmpArrows
[Arrow_InversedDisabled
][n
].Create(w
, h
);
1295 dcInverse
.SelectObject(m_bmpArrows
[Arrow_InversedDisabled
][n
]);
1297 dcInverse
.Blit(0, 0, w
, h
,
1300 dcInverse
.SelectObject(wxNullBitmap
);
1302 mask
= new wxMask(m_bmpArrows
[Arrow_InversedDisabled
][n
], *wxBLACK
);
1303 m_bmpArrows
[Arrow_InversedDisabled
][n
].SetMask(mask
);
1306 dcNormal
.SelectObject(wxNullBitmap
);
1307 dcDisabled
.SelectObject(wxNullBitmap
);
1309 mask
= new wxMask(m_bmpArrows
[Arrow_Normal
][n
], *wxWHITE
);
1310 m_bmpArrows
[Arrow_Normal
][n
].SetMask(mask
);
1311 mask
= new wxMask(m_bmpArrows
[Arrow_Disabled
][n
], *wxWHITE
);
1312 m_bmpArrows
[Arrow_Disabled
][n
].SetMask(mask
);
1314 m_bmpArrows
[Arrow_Pressed
][n
] = m_bmpArrows
[Arrow_Normal
][n
];
1318 // ----------------------------------------------------------------------------
1320 // ----------------------------------------------------------------------------
1323 The raised border in Win32 looks like this:
1325 IIIIIIIIIIIIIIIIIIIIIIB
1327 I GB I = white (HILIGHT)
1328 I GB H = light grey (LIGHT)
1329 I GB G = dark grey (SHADOI)
1330 I GB B = black (DKSHADOI)
1331 I GB I = hIghlight (COLOR_3DHILIGHT)
1333 IGGGGGGGGGGGGGGGGGGGGGB
1334 BBBBBBBBBBBBBBBBBBBBBBB
1336 The sunken border looks like this:
1338 GGGGGGGGGGGGGGGGGGGGGGI
1339 GBBBBBBBBBBBBBBBBBBBBHI
1346 GHHHHHHHHHHHHHHHHHHHHHI
1347 IIIIIIIIIIIIIIIIIIIIIII
1349 The static border (used for the controls which don't get focus) is like
1352 GGGGGGGGGGGGGGGGGGGGGGW
1360 WWWWWWWWWWWWWWWWWWWWWWW
1362 The most complicated is the double border:
1364 HHHHHHHHHHHHHHHHHHHHHHB
1365 HWWWWWWWWWWWWWWWWWWWWGB
1366 HWHHHHHHHHHHHHHHHHHHHGB
1371 HWHHHHHHHHHHHHHHHHHHHGB
1372 HGGGGGGGGGGGGGGGGGGGGGB
1373 BBBBBBBBBBBBBBBBBBBBBBB
1375 And the simple border is, well, simple:
1377 BBBBBBBBBBBBBBBBBBBBBBB
1386 BBBBBBBBBBBBBBBBBBBBBBB
1389 void wxWin32Renderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1393 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1394 dc
.DrawRectangle(*rect
);
1400 void wxWin32Renderer::DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1402 // draw the bottom and right sides
1404 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1405 rect
->GetRight() + 1, rect
->GetBottom());
1406 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1407 rect
->GetRight(), rect
->GetBottom());
1414 void wxWin32Renderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
1415 const wxPen
& pen1
, const wxPen
& pen2
)
1417 // draw the rectangle
1419 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
1420 rect
->GetLeft(), rect
->GetBottom());
1421 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
1422 rect
->GetRight(), rect
->GetTop());
1424 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1425 rect
->GetRight(), rect
->GetBottom());
1426 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1427 rect
->GetRight() + 1, rect
->GetBottom());
1433 void wxWin32Renderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
1435 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
1436 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
1439 void wxWin32Renderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
1441 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
1442 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
1445 void wxWin32Renderer::DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
)
1449 DrawRect(dc
, rect
, m_penDarkGrey
);
1451 // the arrow is usually drawn inside border of width 2 and is offset by
1452 // another pixel in both directions when it's pressed - as the border
1453 // in this case is more narrow as well, we have to adjust rect like
1461 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
1462 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
1466 void wxWin32Renderer::DrawBorder(wxDC
& dc
,
1468 const wxRect
& rectTotal
,
1469 int WXUNUSED(flags
),
1474 wxRect rect
= rectTotal
;
1478 case wxBORDER_SUNKEN
:
1479 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1481 DrawSunkenBorder(dc
, &rect
);
1485 case wxBORDER_STATIC
:
1486 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1489 case wxBORDER_RAISED
:
1490 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1492 DrawRaisedBorder(dc
, &rect
);
1496 case wxBORDER_DOUBLE
:
1497 DrawArrowBorder(dc
, &rect
);
1498 DrawRect(dc
, &rect
, m_penLightGrey
);
1501 case wxBORDER_SIMPLE
:
1502 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1504 DrawRect(dc
, &rect
, m_penBlack
);
1509 wxFAIL_MSG(_T("unknown border type"));
1512 case wxBORDER_DEFAULT
:
1521 wxRect
wxWin32Renderer::GetBorderDimensions(wxBorder border
) const
1526 case wxBORDER_RAISED
:
1527 case wxBORDER_SUNKEN
:
1528 width
= BORDER_THICKNESS
;
1531 case wxBORDER_SIMPLE
:
1532 case wxBORDER_STATIC
:
1536 case wxBORDER_DOUBLE
:
1541 wxFAIL_MSG(_T("unknown border type"));
1544 case wxBORDER_DEFAULT
:
1554 rect
.height
= width
;
1559 bool wxWin32Renderer::AreScrollbarsInsideBorder() const
1564 // ----------------------------------------------------------------------------
1566 // ----------------------------------------------------------------------------
1568 void wxWin32Renderer::DrawTextBorder(wxDC
& dc
,
1574 // text controls are not special under windows
1575 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
1578 void wxWin32Renderer::DrawButtonBorder(wxDC
& dc
,
1579 const wxRect
& rectTotal
,
1583 wxRect rect
= rectTotal
;
1585 if ( flags
& wxCONTROL_PRESSED
)
1587 // button pressed: draw a double border around it
1588 DrawRect(dc
, &rect
, m_penBlack
);
1589 DrawRect(dc
, &rect
, m_penDarkGrey
);
1593 // button not pressed
1595 if ( flags
& (wxCONTROL_FOCUSED
| wxCONTROL_ISDEFAULT
) )
1597 // button either default or focused (or both): add an extra border around it
1598 DrawRect(dc
, &rect
, m_penBlack
);
1601 // now draw a normal button
1602 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penBlack
);
1603 DrawHalfRect(dc
, &rect
, m_penDarkGrey
);
1612 // ----------------------------------------------------------------------------
1614 // ----------------------------------------------------------------------------
1616 void wxWin32Renderer::DrawHorizontalLine(wxDC
& dc
,
1617 wxCoord y
, wxCoord x1
, wxCoord x2
)
1619 dc
.SetPen(m_penDarkGrey
);
1620 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1621 dc
.SetPen(m_penHighlight
);
1623 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1626 void wxWin32Renderer::DrawVerticalLine(wxDC
& dc
,
1627 wxCoord x
, wxCoord y1
, wxCoord y2
)
1629 dc
.SetPen(m_penDarkGrey
);
1630 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1631 dc
.SetPen(m_penHighlight
);
1633 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1636 void wxWin32Renderer::DrawFrame(wxDC
& dc
,
1637 const wxString
& label
,
1643 wxCoord height
= 0; // of the label
1644 wxRect rectFrame
= rect
;
1645 if ( !label
.empty() )
1647 // the text should touch the top border of the rect, so the frame
1648 // itself should be lower
1649 dc
.GetTextExtent(label
, NULL
, &height
);
1650 rectFrame
.y
+= height
/ 2;
1651 rectFrame
.height
-= height
/ 2;
1653 // we have to draw each part of the frame individually as we can't
1654 // erase the background beyond the label as it might contain some
1655 // pixmap already, so drawing everything and then overwriting part of
1656 // the frame with label doesn't work
1658 // TODO: the +5 and space insertion should be customizable
1661 rectText
.x
= rectFrame
.x
+ 5;
1662 rectText
.y
= rect
.y
;
1663 rectText
.width
= rectFrame
.width
- 7; // +2 border width
1664 rectText
.height
= height
;
1667 label2
<< _T(' ') << label
<< _T(' ');
1668 if ( indexAccel
!= -1 )
1670 // adjust it as we prepended a space
1675 DrawLabel(dc
, label2
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
1677 StandardDrawFrame(dc
, rectFrame
, rectLabel
);
1681 // just draw the complete frame
1682 DrawShadedRect(dc
, &rectFrame
, m_penDarkGrey
, m_penHighlight
);
1683 DrawShadedRect(dc
, &rectFrame
, m_penHighlight
, m_penDarkGrey
);
1687 // ----------------------------------------------------------------------------
1689 // ----------------------------------------------------------------------------
1691 void wxWin32Renderer::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
1693 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
1694 // pixels each while we really need dots here... PS_ALTERNATE might
1695 // work, but it is for NT 5 only
1697 DrawRect(dc
, &rect
, wxPen(*wxBLACK
, 0, wxDOT
));
1699 // draw the pixels manually: note that to behave in the same manner as
1700 // DrawRect(), we must exclude the bottom and right borders from the
1702 wxCoord x1
= rect
.GetLeft(),
1704 x2
= rect
.GetRight(),
1705 y2
= rect
.GetBottom();
1707 dc
.SetPen(wxPen(*wxBLACK
, 0, wxSOLID
));
1709 // this seems to be closer than what Windows does than wxINVERT although
1710 // I'm still not sure if it's correct
1711 dc
.SetLogicalFunction(wxAND_REVERSE
);
1714 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
1715 dc
.DrawPoint(z
, rect
.GetTop());
1717 wxCoord shift
= z
== x2
? 0 : 1;
1718 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
1719 dc
.DrawPoint(x2
, z
);
1721 shift
= z
== y2
? 0 : 1;
1722 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
1723 dc
.DrawPoint(z
, y2
);
1725 shift
= z
== x1
? 0 : 1;
1726 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
1727 dc
.DrawPoint(x1
, z
);
1729 dc
.SetLogicalFunction(wxCOPY
);
1733 void wxWin32Renderer::DrawLabelShadow(wxDC
& dc
,
1734 const wxString
& label
,
1739 // draw shadow of the text
1740 dc
.SetTextForeground(m_colHighlight
);
1741 wxRect rectShadow
= rect
;
1744 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
1746 // make the text grey
1747 dc
.SetTextForeground(m_colDarkGrey
);
1750 void wxWin32Renderer::DrawLabel(wxDC
& dc
,
1751 const wxString
& label
,
1758 DoDrawLabel(dc
, label
, rect
, flags
, alignment
, indexAccel
, rectBounds
);
1761 void wxWin32Renderer::DoDrawLabel(wxDC
& dc
,
1762 const wxString
& label
,
1768 const wxPoint
& focusOffset
)
1770 // the underscores are not drawn for focused controls in wxMSW
1771 if ( flags
& wxCONTROL_FOCUSED
)
1776 if ( flags
& wxCONTROL_DISABLED
)
1778 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
1779 // currently only can happen for a menu item and it seems that Windows
1780 // doesn't draw the shadow in this case, so we don't do it neither
1781 if ( flags
& wxCONTROL_SELECTED
)
1783 // just make the label text greyed out
1784 dc
.SetTextForeground(m_colDarkGrey
);
1786 else // draw normal disabled label
1788 DrawLabelShadow(dc
, label
, rect
, alignment
, indexAccel
);
1793 dc
.DrawLabel(label
, wxNullBitmap
, rect
, alignment
, indexAccel
, &rectLabel
);
1795 if ( flags
& wxCONTROL_DISABLED
)
1797 // restore the fg colour
1798 dc
.SetTextForeground(*wxBLACK
);
1801 if ( flags
& wxCONTROL_FOCUSED
)
1803 if ( focusOffset
.x
|| focusOffset
.y
)
1805 rectLabel
.Inflate(focusOffset
.x
, focusOffset
.y
);
1808 DrawFocusRect(dc
, rectLabel
);
1812 *rectBounds
= rectLabel
;
1815 void wxWin32Renderer::DrawButtonLabel(wxDC
& dc
,
1816 const wxString
& label
,
1817 const wxBitmap
& image
,
1824 // the underscores are not drawn for focused controls in wxMSW
1825 if ( flags
& wxCONTROL_PRESSED
)
1830 wxRect rectLabel
= rect
;
1831 if ( !label
.empty() )
1833 // shift the label if a button is pressed
1834 if ( flags
& wxCONTROL_PRESSED
)
1840 if ( flags
& wxCONTROL_DISABLED
)
1842 DrawLabelShadow(dc
, label
, rectLabel
, alignment
, indexAccel
);
1845 // leave enough space for the focus rectangle
1846 if ( flags
& wxCONTROL_FOCUSED
)
1848 rectLabel
.Inflate(-2);
1852 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
1854 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
1856 if ( flags
& wxCONTROL_PRESSED
)
1858 // the focus rectangle is never pressed, so undo the shift done
1866 DrawFocusRect(dc
, rectLabel
);
1870 // ----------------------------------------------------------------------------
1871 // (check)listbox items
1872 // ----------------------------------------------------------------------------
1874 void wxWin32Renderer::DrawItem(wxDC
& dc
,
1875 const wxString
& label
,
1879 wxDCTextColourChanger
colChanger(dc
);
1881 if ( flags
& wxCONTROL_SELECTED
)
1883 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
1885 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
1886 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
1887 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
1888 dc
.DrawRectangle(rect
);
1891 wxRect rectText
= rect
;
1893 rectText
.width
-= 2;
1894 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
1896 if ( flags
& wxCONTROL_FOCUSED
)
1898 DrawFocusRect(dc
, rect
);
1902 void wxWin32Renderer::DrawCheckItem(wxDC
& dc
,
1903 const wxString
& label
,
1904 const wxBitmap
& bitmap
,
1913 else // use default bitmap
1915 bmp
= wxBitmap(flags
& wxCONTROL_CHECKED
? checked_item_xpm
1916 : unchecked_item_xpm
);
1919 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2 - 1,
1920 TRUE
/* use mask */);
1922 wxRect rectLabel
= rect
;
1923 int bmpWidth
= bmp
.GetWidth();
1924 rectLabel
.x
+= bmpWidth
;
1925 rectLabel
.width
-= bmpWidth
;
1927 DrawItem(dc
, label
, rectLabel
, flags
);
1930 // ----------------------------------------------------------------------------
1931 // check/radio buttons
1932 // ----------------------------------------------------------------------------
1934 wxBitmap
wxWin32Renderer::GetIndicator(IndicatorType indType
, int flags
)
1936 IndicatorState indState
;
1937 if ( flags
& wxCONTROL_SELECTED
)
1938 indState
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
1939 : IndicatorState_Selected
;
1940 else if ( flags
& wxCONTROL_DISABLED
)
1941 indState
= IndicatorState_Disabled
;
1942 else if ( flags
& wxCONTROL_PRESSED
)
1943 indState
= IndicatorState_Pressed
;
1945 indState
= IndicatorState_Normal
;
1947 IndicatorStatus indStatus
= flags
& wxCONTROL_CHECKED
1948 ? IndicatorStatus_Checked
1949 : IndicatorStatus_Unchecked
;
1951 const char **xpm
= bmpIndicators
[indType
][indState
][indStatus
];
1952 return xpm
? wxBitmap(xpm
) : wxNullBitmap
;
1955 void wxWin32Renderer::DrawCheckOrRadioButton(wxDC
& dc
,
1956 const wxString
& label
,
1957 const wxBitmap
& bitmap
,
1962 wxCoord focusOffsetY
)
1964 // calculate the position of the bitmap and of the label
1965 wxCoord heightBmp
= bitmap
.GetHeight();
1967 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
1970 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
1971 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
1973 // align label vertically with the bitmap - looks nicer like this
1974 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
1976 // calc horz position
1977 if ( align
== wxALIGN_RIGHT
)
1979 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
1980 rectLabel
.x
= rect
.x
+ 3;
1981 rectLabel
.SetRight(xBmp
);
1983 else // normal (checkbox to the left of the text) case
1986 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
1987 rectLabel
.SetRight(rect
.GetRight());
1990 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, TRUE
/* use mask */);
1993 dc
, label
, rectLabel
,
1995 wxALIGN_LEFT
| wxALIGN_TOP
,
1997 NULL
, // we don't need bounding rect
1998 // use custom vert focus rect offset
1999 wxPoint(FOCUS_RECT_OFFSET_X
, focusOffsetY
)
2003 void wxWin32Renderer::DrawRadioButton(wxDC
& dc
,
2004 const wxString
& label
,
2005 const wxBitmap
& bitmap
,
2011 DrawCheckOrRadioButton(dc
, label
,
2012 bitmap
.Ok() ? bitmap
: GetRadioBitmap(flags
),
2013 rect
, flags
, align
, indexAccel
,
2014 FOCUS_RECT_OFFSET_Y
); // default focus rect offset
2017 void wxWin32Renderer::DrawCheckButton(wxDC
& dc
,
2018 const wxString
& label
,
2019 const wxBitmap
& bitmap
,
2025 DrawCheckOrRadioButton(dc
, label
,
2026 bitmap
.Ok() ? bitmap
: GetCheckBitmap(flags
),
2027 rect
, flags
, align
, indexAccel
,
2028 0); // no focus rect offset for checkboxes
2031 // ----------------------------------------------------------------------------
2033 // ----------------------------------------------------------------------------
2035 void wxWin32Renderer::DrawTextLine(wxDC
& dc
,
2036 const wxString
& text
,
2042 // nothing special to do here
2043 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
2046 void wxWin32Renderer::DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
)
2048 // we don't draw them
2051 // ----------------------------------------------------------------------------
2053 // ----------------------------------------------------------------------------
2055 void wxWin32Renderer::DrawTab(wxDC
& dc
,
2056 const wxRect
& rectOrig
,
2058 const wxString
& label
,
2059 const wxBitmap
& bitmap
,
2063 wxRect rect
= rectOrig
;
2065 // the current tab is drawn indented (to the top for default case) and
2066 // bigger than the other ones
2067 const wxSize indent
= GetTabIndent();
2068 if ( flags
& wxCONTROL_SELECTED
)
2073 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2077 rect
.Inflate(indent
.x
, 0);
2079 rect
.height
+= indent
.y
;
2083 rect
.Inflate(indent
.x
, 0);
2084 rect
.height
+= indent
.y
;
2089 wxFAIL_MSG(_T("TODO"));
2094 // draw the text, image and the focus around them (if necessary)
2095 wxRect rectLabel
= rect
;
2096 rectLabel
.Deflate(1, 1);
2097 DrawButtonLabel(dc
, label
, bitmap
, rectLabel
,
2098 flags
, wxALIGN_CENTRE
, indexAccel
);
2100 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2101 static const wxCoord CUTOFF
= 2; // radius of the rounded corner
2104 x2
= rect
.GetRight(),
2105 y2
= rect
.GetBottom();
2107 // FIXME: all this code will break if the tab indent or the border width,
2108 // it is tied to the fact that both of them are equal to 2
2113 dc
.SetPen(m_penHighlight
);
2114 dc
.DrawLine(x
, y2
, x
, y
+ CUTOFF
);
2115 dc
.DrawLine(x
, y
+ CUTOFF
, x
+ CUTOFF
, y
);
2116 dc
.DrawLine(x
+ CUTOFF
, y
, x2
- CUTOFF
+ 1, y
);
2118 dc
.SetPen(m_penBlack
);
2119 dc
.DrawLine(x2
, y2
, x2
, y
+ CUTOFF
);
2120 dc
.DrawLine(x2
, y
+ CUTOFF
, x2
- CUTOFF
, y
);
2122 dc
.SetPen(m_penDarkGrey
);
2123 dc
.DrawLine(x2
- 1, y2
, x2
- 1, y
+ CUTOFF
- 1);
2125 if ( flags
& wxCONTROL_SELECTED
)
2127 dc
.SetPen(m_penLightGrey
);
2129 // overwrite the part of the border below this tab
2130 dc
.DrawLine(x
+ 1, y2
+ 1, x2
- 1, y2
+ 1);
2132 // and the shadow of the tab to the left of us
2133 dc
.DrawLine(x
+ 1, y
+ CUTOFF
+ 1, x
+ 1, y2
+ 1);
2138 dc
.SetPen(m_penHighlight
);
2139 // we need to continue one pixel further to overwrite the corner of
2140 // the border for the selected tab
2141 dc
.DrawLine(x
, y
- (flags
& wxCONTROL_SELECTED
? 1 : 0),
2143 dc
.DrawLine(x
, y2
- CUTOFF
, x
+ CUTOFF
, y2
);
2145 dc
.SetPen(m_penBlack
);
2146 dc
.DrawLine(x
+ CUTOFF
, y2
, x2
- CUTOFF
+ 1, y2
);
2147 dc
.DrawLine(x2
, y
, x2
, y2
- CUTOFF
);
2148 dc
.DrawLine(x2
, y2
- CUTOFF
, x2
- CUTOFF
, y2
);
2150 dc
.SetPen(m_penDarkGrey
);
2151 dc
.DrawLine(x
+ CUTOFF
, y2
- 1, x2
- CUTOFF
+ 1, y2
- 1);
2152 dc
.DrawLine(x2
- 1, y
, x2
- 1, y2
- CUTOFF
+ 1);
2154 if ( flags
& wxCONTROL_SELECTED
)
2156 dc
.SetPen(m_penLightGrey
);
2158 // overwrite the part of the (double!) border above this tab
2159 dc
.DrawLine(x
+ 1, y
- 1, x2
- 1, y
- 1);
2160 dc
.DrawLine(x
+ 1, y
- 2, x2
- 1, y
- 2);
2162 // and the shadow of the tab to the left of us
2163 dc
.DrawLine(x
+ 1, y2
- CUTOFF
, x
+ 1, y
- 1);
2169 wxFAIL_MSG(_T("TODO"));
2173 // ----------------------------------------------------------------------------
2175 // ----------------------------------------------------------------------------
2177 wxSize
wxWin32Renderer::GetSliderThumbSize(const wxRect
& rect
,
2178 wxOrientation orient
) const
2182 wxRect rectShaft
= GetSliderShaftRect(rect
, orient
);
2183 if ( orient
== wxHORIZONTAL
)
2185 size
.y
= rect
.height
- 6;
2186 size
.x
= wxMin(size
.y
/ 2, rectShaft
.width
);
2190 size
.x
= rect
.width
- 6;
2191 size
.y
= wxMin(size
.x
/ 2, rectShaft
.height
);
2197 wxRect
wxWin32Renderer::GetSliderShaftRect(const wxRect
& rectOrig
,
2198 wxOrientation orient
) const
2200 static const wxCoord SLIDER_MARGIN
= 6;
2202 wxRect rect
= rectOrig
;
2204 if ( orient
== wxHORIZONTAL
)
2206 // make the rect of minimal width and centre it
2207 rect
.height
= 2*BORDER_THICKNESS
;
2208 rect
.y
= rectOrig
.y
+ (rectOrig
.height
- rect
.height
) / 2;
2212 // leave margins on the sides
2213 rect
.Deflate(SLIDER_MARGIN
, 0);
2217 // same as above but in other direction
2218 rect
.width
= 2*BORDER_THICKNESS
;
2219 rect
.x
= rectOrig
.x
+ (rectOrig
.width
- rect
.width
) / 2;
2223 rect
.Deflate(0, SLIDER_MARGIN
);
2229 void wxWin32Renderer::DrawSliderShaft(wxDC
& dc
,
2230 const wxRect
& rectOrig
,
2231 wxOrientation orient
,
2235 if ( flags
& wxCONTROL_FOCUSED
)
2237 DrawFocusRect(dc
, rectOrig
);
2240 wxRect rect
= GetSliderShaftRect(rectOrig
, orient
);
2245 DrawSunkenBorder(dc
, &rect
);
2248 void wxWin32Renderer::DrawSliderThumb(wxDC
& dc
,
2250 wxOrientation orient
,
2254 we are drawing a shape of this form
2259 H DB where H is hightlight colour
2272 The interior of this shape is filled with the hatched brush if the thumb
2276 DrawBackground(dc
, wxNullColour
, rect
, flags
);
2278 bool transpose
= orient
== wxVERTICAL
;
2280 wxCoord x
, y
, x2
, y2
;
2285 x2
= rect
.GetBottom();
2286 y2
= rect
.GetRight();
2292 x2
= rect
.GetRight();
2293 y2
= rect
.GetBottom();
2296 // the size of the pointed part of the thumb
2297 wxCoord sizeArrow
= (transpose
? rect
.height
: rect
.width
) / 2;
2299 wxCoord x3
= x
+ sizeArrow
,
2300 y3
= y2
- sizeArrow
;
2302 dc
.SetPen(m_penHighlight
);
2303 DrawLine(dc
, x
, y
, x2
, y
, transpose
);
2304 DrawLine(dc
, x
, y
+ 1, x
, y2
- sizeArrow
, transpose
);
2305 DrawLine(dc
, x
, y3
, x3
, y2
, transpose
);
2307 dc
.SetPen(m_penBlack
);
2308 DrawLine(dc
, x3
, y2
, x2
, y3
, transpose
);
2309 DrawLine(dc
, x2
, y3
, x2
, y
- 1, transpose
);
2311 dc
.SetPen(m_penDarkGrey
);
2312 DrawLine(dc
, x3
, y2
- 1, x2
- 1, y3
, transpose
);
2313 DrawLine(dc
, x2
- 1, y3
, x2
- 1, y
, transpose
);
2315 if ( flags
& wxCONTROL_PRESSED
)
2317 // TODO: MSW fills the entire area inside, not just the rect
2318 wxRect rectInt
= rect
;
2320 rectInt
.SetRight(y3
);
2322 rectInt
.SetBottom(y3
);
2325 static const char *stipple_xpm
[] = {
2326 /* columns rows colors chars-per-pixel */
2334 dc
.SetBrush(wxBrush(stipple_xpm
));
2336 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, SHADOW_HIGHLIGHT
));
2337 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, CONTROL
));
2338 dc
.SetPen(*wxTRANSPARENT_PEN
);
2339 dc
.DrawRectangle(rectInt
);
2343 void wxWin32Renderer::DrawSliderTicks(wxDC
& dc
,
2345 const wxSize
& sizeThumb
,
2346 wxOrientation orient
,
2358 // the variable names correspond to horizontal case, but they can be used
2359 // for both orientations
2360 wxCoord x1
, x2
, y1
, y2
, len
, widthThumb
;
2361 if ( orient
== wxHORIZONTAL
)
2363 x1
= rect
.GetLeft();
2364 x2
= rect
.GetRight();
2366 // draw from bottom to top to leave one pixel space between the ticks
2367 // and the slider as Windows do
2368 y1
= rect
.GetBottom();
2373 widthThumb
= sizeThumb
.x
;
2378 x2
= rect
.GetBottom();
2380 y1
= rect
.GetRight();
2381 y2
= rect
.GetLeft();
2385 widthThumb
= sizeThumb
.y
;
2388 // the first tick should be positioned in such way that a thumb drawn in
2389 // the first position points down directly to it
2390 x1
+= widthThumb
/ 2;
2391 x2
-= widthThumb
/ 2;
2393 // this also means that we have slightly less space for the ticks in
2394 // between the first and the last
2397 dc
.SetPen(m_penBlack
);
2399 int range
= end
- start
;
2400 for ( int n
= 0; n
< range
; n
+= step
)
2402 wxCoord x
= x1
+ (len
*n
) / range
;
2404 DrawLine(dc
, x
, y1
, x
, y2
, orient
== wxVERTICAL
);
2407 // always draw the line at the end position
2408 DrawLine(dc
, x2
, y1
, x2
, y2
, orient
== wxVERTICAL
);
2411 // ----------------------------------------------------------------------------
2413 // ----------------------------------------------------------------------------
2417 // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2418 class WXDLLEXPORT wxWin32MenuGeometryInfo
: public wxMenuGeometryInfo
2421 virtual wxSize
GetSize() const { return m_size
; }
2423 wxCoord
GetLabelOffset() const { return m_ofsLabel
; }
2424 wxCoord
GetAccelOffset() const { return m_ofsAccel
; }
2426 wxCoord
GetItemHeight() const { return m_heightItem
; }
2429 // the total size of the menu
2432 // the offset of the start of the menu item label
2435 // the offset of the start of the accel label
2438 // the height of a normal (not separator) item
2439 wxCoord m_heightItem
;
2441 friend wxMenuGeometryInfo
*wxWin32Renderer::
2442 GetMenuGeometry(wxWindow
*, const wxMenu
&) const;
2445 #endif // wxUSE_WAVE
2447 // FIXME: all constants are hardcoded but shouldn't be
2448 static const wxCoord MENU_LEFT_MARGIN
= 9;
2449 static const wxCoord MENU_RIGHT_MARGIN
= 18;
2450 static const wxCoord MENU_VERT_MARGIN
= 3;
2452 // the margin around bitmap/check marks (on each side)
2453 static const wxCoord MENU_BMP_MARGIN
= 2;
2455 // the margin between the labels and accel strings
2456 static const wxCoord MENU_ACCEL_MARGIN
= 8;
2458 // the separator height in pixels: in fact, strangely enough, the real height
2459 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2461 static const wxCoord MENU_SEPARATOR_HEIGHT
= 3;
2463 // the size of the standard checkmark bitmap
2464 static const wxCoord MENU_CHECK_SIZE
= 9;
2466 // we can't implement these methods without wxMenuGeometryInfo implementation
2467 // which we don't have if !wxUSE_MENUS
2470 void wxWin32Renderer::DrawMenuBarItem(wxDC
& dc
,
2471 const wxRect
& rectOrig
,
2472 const wxString
& label
,
2476 wxRect rect
= rectOrig
;
2479 wxDCTextColourChanger
colChanger(dc
);
2481 if ( flags
& wxCONTROL_SELECTED
)
2483 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2485 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2486 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2487 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2488 dc
.DrawRectangle(rect
);
2491 // don't draw the focus rect around menu bar items
2492 DrawLabel(dc
, label
, rect
, flags
& ~wxCONTROL_FOCUSED
,
2493 wxALIGN_CENTRE
, indexAccel
);
2496 void wxWin32Renderer::DrawMenuItem(wxDC
& dc
,
2498 const wxMenuGeometryInfo
& gi
,
2499 const wxString
& label
,
2500 const wxString
& accel
,
2501 const wxBitmap
& bitmap
,
2505 const wxWin32MenuGeometryInfo
& geometryInfo
=
2506 (const wxWin32MenuGeometryInfo
&)gi
;
2511 rect
.width
= geometryInfo
.GetSize().x
;
2512 rect
.height
= geometryInfo
.GetItemHeight();
2514 // draw the selected item specially
2515 wxDCTextColourChanger
colChanger(dc
);
2516 if ( flags
& wxCONTROL_SELECTED
)
2518 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2520 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2521 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2522 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2523 dc
.DrawRectangle(rect
);
2526 // draw the bitmap: use the bitmap provided or the standard checkmark for
2527 // the checkable items
2528 wxBitmap bmp
= bitmap
;
2529 if ( !bmp
.Ok() && (flags
& wxCONTROL_CHECKED
) )
2531 bmp
= GetIndicator(IndicatorType_Menu
, flags
);
2536 rect
.SetRight(geometryInfo
.GetLabelOffset());
2537 wxControlRenderer::DrawBitmap(dc
, bmp
, rect
);
2541 rect
.x
= geometryInfo
.GetLabelOffset();
2542 rect
.SetRight(geometryInfo
.GetAccelOffset());
2544 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
, indexAccel
);
2546 // draw the accel string
2547 rect
.x
= geometryInfo
.GetAccelOffset();
2548 rect
.SetRight(geometryInfo
.GetSize().x
);
2550 // NB: no accel index here
2551 DrawLabel(dc
, accel
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
);
2553 // draw the submenu indicator
2554 if ( flags
& wxCONTROL_ISSUBMENU
)
2556 rect
.x
= geometryInfo
.GetSize().x
- MENU_RIGHT_MARGIN
;
2557 rect
.width
= MENU_RIGHT_MARGIN
;
2559 wxArrowStyle arrowStyle
;
2560 if ( flags
& wxCONTROL_DISABLED
)
2561 arrowStyle
= flags
& wxCONTROL_SELECTED
? Arrow_InversedDisabled
2563 else if ( flags
& wxCONTROL_SELECTED
)
2564 arrowStyle
= Arrow_Inversed
;
2566 arrowStyle
= Arrow_Normal
;
2568 DrawArrow(dc
, rect
, Arrow_Right
, arrowStyle
);
2572 void wxWin32Renderer::DrawMenuSeparator(wxDC
& dc
,
2574 const wxMenuGeometryInfo
& geomInfo
)
2576 DrawHorizontalLine(dc
, y
+ MENU_VERT_MARGIN
, 0, geomInfo
.GetSize().x
);
2579 wxSize
wxWin32Renderer::GetMenuBarItemSize(const wxSize
& sizeText
) const
2581 wxSize size
= sizeText
;
2583 // FIXME: menubar height is configurable under Windows
2590 wxMenuGeometryInfo
*wxWin32Renderer::GetMenuGeometry(wxWindow
*win
,
2591 const wxMenu
& menu
) const
2593 // prepare the dc: for now we draw all the items with the system font
2595 dc
.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
));
2597 // the height of a normal item
2598 wxCoord heightText
= dc
.GetCharHeight();
2603 // the max length of label and accel strings: the menu width is the sum of
2604 // them, even if they're for different items (as the accels should be
2607 // the max length of the bitmap is never 0 as Windows always leaves enough
2608 // space for a check mark indicator
2609 wxCoord widthLabelMax
= 0,
2611 widthBmpMax
= MENU_LEFT_MARGIN
;
2613 for ( wxMenuItemList::Node
*node
= menu
.GetMenuItems().GetFirst();
2615 node
= node
->GetNext() )
2617 // height of this item
2620 wxMenuItem
*item
= node
->GetData();
2621 if ( item
->IsSeparator() )
2623 h
= MENU_SEPARATOR_HEIGHT
;
2625 else // not separator
2630 dc
.GetTextExtent(item
->GetLabel(), &widthLabel
, NULL
);
2631 if ( widthLabel
> widthLabelMax
)
2633 widthLabelMax
= widthLabel
;
2637 dc
.GetTextExtent(item
->GetAccelString(), &widthAccel
, NULL
);
2638 if ( widthAccel
> widthAccelMax
)
2640 widthAccelMax
= widthAccel
;
2643 const wxBitmap
& bmp
= item
->GetBitmap();
2646 wxCoord widthBmp
= bmp
.GetWidth();
2647 if ( widthBmp
> widthBmpMax
)
2648 widthBmpMax
= widthBmp
;
2650 //else if ( item->IsCheckable() ): no need to check for this as
2651 // MENU_LEFT_MARGIN is big enough to show the check mark
2654 h
+= 2*MENU_VERT_MARGIN
;
2656 // remember the item position and height
2657 item
->SetGeometry(height
, h
);
2662 // bundle the metrics into a struct and return it
2663 wxWin32MenuGeometryInfo
*gi
= new wxWin32MenuGeometryInfo
;
2665 gi
->m_ofsLabel
= widthBmpMax
+ 2*MENU_BMP_MARGIN
;
2666 gi
->m_ofsAccel
= gi
->m_ofsLabel
+ widthLabelMax
;
2667 if ( widthAccelMax
> 0 )
2669 // if we actually have any accesl, add a margin
2670 gi
->m_ofsAccel
+= MENU_ACCEL_MARGIN
;
2673 gi
->m_heightItem
= heightText
+ 2*MENU_VERT_MARGIN
;
2675 gi
->m_size
.x
= gi
->m_ofsAccel
+ widthAccelMax
+ MENU_RIGHT_MARGIN
;
2676 gi
->m_size
.y
= height
;
2681 #else // !wxUSE_MENUS
2683 void wxWin32Renderer::DrawMenuBarItem(wxDC
& WXUNUSED(dc
),
2684 const wxRect
& WXUNUSED(rectOrig
),
2685 const wxString
& WXUNUSED(label
),
2686 int WXUNUSED(flags
),
2687 int WXUNUSED(indexAccel
))
2691 void wxWin32Renderer::DrawMenuItem(wxDC
& WXUNUSED(dc
),
2692 wxCoord
WXUNUSED(y
),
2693 const wxMenuGeometryInfo
& WXUNUSED(gi
),
2694 const wxString
& WXUNUSED(label
),
2695 const wxString
& WXUNUSED(accel
),
2696 const wxBitmap
& WXUNUSED(bitmap
),
2697 int WXUNUSED(flags
),
2698 int WXUNUSED(indexAccel
))
2702 void wxWin32Renderer::DrawMenuSeparator(wxDC
& WXUNUSED(dc
),
2703 wxCoord
WXUNUSED(y
),
2704 const wxMenuGeometryInfo
& WXUNUSED(gi
))
2708 wxSize
wxWin32Renderer::GetMenuBarItemSize(const wxSize
& size
) const
2713 wxMenuGeometryInfo
*
2714 wxWin32Renderer::GetMenuGeometry(wxWindow
*WXUNUSED(win
),
2715 const wxMenu
& WXUNUSED(menu
)) const
2720 #endif // wxUSE_MENUS/!wxUSE_MENUS
2722 // ----------------------------------------------------------------------------
2724 // ----------------------------------------------------------------------------
2726 void wxWin32Renderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
2727 wxBitmap
*bmpPressed
,
2728 wxBitmap
*bmpDisabled
)
2730 static const wxCoord widthCombo
= 16;
2731 static const wxCoord heightCombo
= 17;
2737 bmpNormal
->Create(widthCombo
, heightCombo
);
2738 dcMem
.SelectObject(*bmpNormal
);
2739 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2740 Arrow_Down
, Arrow_Normal
);
2745 bmpPressed
->Create(widthCombo
, heightCombo
);
2746 dcMem
.SelectObject(*bmpPressed
);
2747 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2748 Arrow_Down
, Arrow_Pressed
);
2753 bmpDisabled
->Create(widthCombo
, heightCombo
);
2754 dcMem
.SelectObject(*bmpDisabled
);
2755 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2756 Arrow_Down
, Arrow_Disabled
);
2760 // ----------------------------------------------------------------------------
2762 // ----------------------------------------------------------------------------
2764 void wxWin32Renderer::DoDrawBackground(wxDC
& dc
,
2765 const wxColour
& col
,
2768 wxBrush
brush(col
, wxSOLID
);
2770 dc
.SetPen(*wxTRANSPARENT_PEN
);
2771 dc
.DrawRectangle(rect
);
2774 void wxWin32Renderer::DrawBackground(wxDC
& dc
,
2775 const wxColour
& col
,
2779 // just fill it with the given or default bg colour
2780 wxColour colBg
= col
.Ok() ? col
: wxSCHEME_COLOUR(m_scheme
, CONTROL
);
2781 DoDrawBackground(dc
, colBg
, rect
);
2784 // ----------------------------------------------------------------------------
2786 // ----------------------------------------------------------------------------
2788 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2793 // get the bitmap for this arrow
2794 wxArrowDirection arrowDir
;
2797 case wxLEFT
: arrowDir
= Arrow_Left
; break;
2798 case wxRIGHT
: arrowDir
= Arrow_Right
; break;
2799 case wxUP
: arrowDir
= Arrow_Up
; break;
2800 case wxDOWN
: arrowDir
= Arrow_Down
; break;
2803 wxFAIL_MSG(_T("unknown arrow direction"));
2807 wxArrowStyle arrowStyle
;
2808 if ( flags
& wxCONTROL_PRESSED
)
2810 // can't be pressed and disabled
2811 arrowStyle
= Arrow_Pressed
;
2815 arrowStyle
= flags
& wxCONTROL_DISABLED
? Arrow_Disabled
: Arrow_Normal
;
2818 DrawArrowButton(dc
, rect
, arrowDir
, arrowStyle
);
2821 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2823 wxArrowDirection arrowDir
,
2824 wxArrowStyle arrowStyle
)
2826 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
2828 // under Windows the arrows always have the same size so just centre it in
2829 // the provided rectangle
2830 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
2831 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
2833 // Windows does it like this...
2834 if ( arrowDir
== Arrow_Left
)
2838 dc
.DrawBitmap(bmp
, x
, y
, TRUE
/* use mask */);
2841 void wxWin32Renderer::DrawArrowButton(wxDC
& dc
,
2842 const wxRect
& rectAll
,
2843 wxArrowDirection arrowDir
,
2844 wxArrowStyle arrowStyle
)
2846 wxRect rect
= rectAll
;
2847 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2848 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
2849 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
2852 void wxWin32Renderer::DrawScrollbarThumb(wxDC
& dc
,
2853 wxOrientation orient
,
2857 // we don't use the flags, the thumb never changes appearance
2858 wxRect rectThumb
= rect
;
2859 DrawArrowBorder(dc
, &rectThumb
);
2860 DrawBackground(dc
, wxNullColour
, rectThumb
);
2863 void wxWin32Renderer::DrawScrollbarShaft(wxDC
& dc
,
2864 wxOrientation orient
,
2865 const wxRect
& rectBar
,
2868 wxColourScheme::StdColour col
= flags
& wxCONTROL_PRESSED
2869 ? wxColourScheme::SCROLLBAR_PRESSED
2870 : wxColourScheme::SCROLLBAR
;
2871 DoDrawBackground(dc
, m_scheme
->Get(col
), rectBar
);
2874 void wxWin32Renderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
2876 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2879 wxRect
wxWin32Renderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
2880 wxScrollBar::Element elem
,
2883 return StandardGetScrollbarRect(scrollbar
, elem
,
2884 thumbPos
, m_sizeScrollbarArrow
);
2887 wxCoord
wxWin32Renderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
2889 return StandardScrollBarSize(scrollbar
, m_sizeScrollbarArrow
);
2892 wxHitTest
wxWin32Renderer::HitTestScrollbar(const wxScrollBar
*scrollbar
,
2893 const wxPoint
& pt
) const
2895 return StandardHitTestScrollbar(scrollbar
, pt
, m_sizeScrollbarArrow
);
2898 wxCoord
wxWin32Renderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
2901 return StandardScrollbarToPixel(scrollbar
, thumbPos
, m_sizeScrollbarArrow
);
2904 int wxWin32Renderer::PixelToScrollbar(const wxScrollBar
*scrollbar
,
2907 return StandardPixelToScrollbar(scrollbar
, coord
, m_sizeScrollbarArrow
);
2910 // ----------------------------------------------------------------------------
2911 // text control geometry
2912 // ----------------------------------------------------------------------------
2914 static inline int GetTextBorderWidth()
2919 wxRect
wxWin32Renderer::GetTextTotalArea(const wxTextCtrl
*text
,
2922 wxRect rectTotal
= rect
;
2924 wxCoord widthBorder
= GetTextBorderWidth();
2925 rectTotal
.Inflate(widthBorder
);
2927 // this is what Windows does
2933 wxRect
wxWin32Renderer::GetTextClientArea(const wxTextCtrl
*text
,
2935 wxCoord
*extraSpaceBeyond
)
2937 wxRect rectText
= rect
;
2939 // undo GetTextTotalArea()
2940 if ( rectText
.height
> 0 )
2943 wxCoord widthBorder
= GetTextBorderWidth();
2944 rectText
.Inflate(-widthBorder
);
2946 if ( extraSpaceBeyond
)
2947 *extraSpaceBeyond
= 0;
2952 // ----------------------------------------------------------------------------
2954 // ----------------------------------------------------------------------------
2956 void wxWin32Renderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
2959 if ( wxDynamicCast(window
, wxScrollBar
) )
2961 // we only set the width of vert scrollbars and height of the
2963 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
2964 size
->y
= m_sizeScrollbarArrow
.y
;
2966 size
->x
= m_sizeScrollbarArrow
.x
;
2968 // skip border width adjustments, they don't make sense for us
2971 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
2974 if ( wxDynamicCast(window
, wxButton
) )
2977 size
->x
+= 3*window
->GetCharWidth();
2978 #if 0 // do allow creating small buttons if wanted
2979 wxSize sizeDef
= wxButton::GetDefaultSize();
2980 if ( size
->x
< sizeDef
.x
)
2981 size
->x
= sizeDef
.x
;
2984 wxCoord heightBtn
= (11*(window
->GetCharHeight() + 8))/10;
2985 if ( size
->y
< heightBtn
- 8 )
2986 size
->y
= heightBtn
;
2990 // no border width adjustments for buttons
2993 #endif // wxUSE_BUTTON
2995 // take into account the border width
2996 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
2997 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
2998 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
3001 // ============================================================================
3003 // ============================================================================
3005 // ----------------------------------------------------------------------------
3006 // wxWin32InputHandler
3007 // ----------------------------------------------------------------------------
3009 wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer
*renderer
)
3011 m_renderer
= renderer
;
3014 bool wxWin32InputHandler::HandleKey(wxControl
*control
,
3015 const wxKeyEvent
& event
,
3021 bool wxWin32InputHandler::HandleMouse(wxControl
*control
,
3022 const wxMouseEvent
& event
)
3027 // ----------------------------------------------------------------------------
3028 // wxWin32ScrollBarInputHandler
3029 // ----------------------------------------------------------------------------
3031 wxWin32ScrollBarInputHandler::
3032 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
3033 wxInputHandler
*handler
)
3034 : wxStdScrollBarInputHandler(renderer
, handler
)
3036 m_scrollPaused
= FALSE
;
3040 bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar
*scrollbar
,
3041 const wxControlAction
& action
)
3043 // stop if went beyond the position of the original click (this can only
3044 // happen when we scroll by pages)
3046 if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
3048 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3049 != wxHT_SCROLLBAR_BAR_2
;
3051 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
3053 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3054 != wxHT_SCROLLBAR_BAR_1
;
3059 StopScrolling(scrollbar
);
3061 scrollbar
->Refresh();
3066 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar
, action
);
3069 bool wxWin32ScrollBarInputHandler::HandleMouse(wxControl
*control
,
3070 const wxMouseEvent
& event
)
3072 // remember the current state
3073 bool wasDraggingThumb
= m_htLast
== wxHT_SCROLLBAR_THUMB
;
3075 // do process the message
3076 bool rc
= wxStdScrollBarInputHandler::HandleMouse(control
, event
);
3078 // analyse the changes
3079 if ( !wasDraggingThumb
&& (m_htLast
== wxHT_SCROLLBAR_THUMB
) )
3081 // we just started dragging the thumb, remember its initial position to
3082 // be able to restore it if the drag is cancelled later
3083 m_eventStartDrag
= event
;
3089 bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl
*control
,
3090 const wxMouseEvent
& event
)
3092 // we don't highlight scrollbar elements, so there is no need to process
3093 // mouse move events normally - only do it while mouse is captured (i.e.
3094 // when we're dragging the thumb or pressing on something)
3095 if ( !m_winCapture
)
3098 if ( event
.Entering() )
3100 // we're not interested in this at all
3104 wxScrollBar
*scrollbar
= wxStaticCast(control
, wxScrollBar
);
3106 if ( m_scrollPaused
)
3108 // check if the mouse returned to its original location
3110 if ( event
.Leaving() )
3116 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3117 if ( ht
== m_htLast
)
3119 // yes it did, resume scrolling
3120 m_scrollPaused
= FALSE
;
3121 if ( m_timerScroll
)
3123 // we were scrolling by line/page, restart timer
3124 m_timerScroll
->Start(m_interval
);
3126 Press(scrollbar
, TRUE
);
3128 else // we were dragging the thumb
3130 // restore its last location
3131 HandleThumbMove(scrollbar
, m_eventLastDrag
);
3137 else // normal case, scrolling hasn't been paused
3139 // if we're scrolling the scrollbar because the arrow or the shaft was
3140 // pressed, check that the mouse stays on the same scrollbar element
3142 if ( event
.Moving() )
3144 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3146 else // event.Leaving()
3151 // if we're dragging the thumb and the mouse stays in the scrollbar, it
3152 // is still ok - we only want to catch the case when the mouse leaves
3153 // the scrollbar here
3154 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
&& ht
!= wxHT_NOWHERE
)
3156 ht
= wxHT_SCROLLBAR_THUMB
;
3159 if ( ht
!= m_htLast
)
3161 // what were we doing? 2 possibilities: either an arrow/shaft was
3162 // pressed in which case we have a timer and so we just stop it or
3163 // we were dragging the thumb
3164 if ( m_timerScroll
)
3167 m_interval
= m_timerScroll
->GetInterval();
3168 m_timerScroll
->Stop();
3169 m_scrollPaused
= TRUE
;
3171 // unpress the arrow
3172 Press(scrollbar
, FALSE
);
3174 else // we were dragging the thumb
3176 // remember the current thumb position to be able to restore it
3177 // if the mouse returns to it later
3178 m_eventLastDrag
= event
;
3180 // and restore the original position (before dragging) of the
3182 HandleThumbMove(scrollbar
, m_eventStartDrag
);
3189 return wxStdScrollBarInputHandler::HandleMouseMove(control
, event
);
3192 // ----------------------------------------------------------------------------
3193 // wxWin32CheckboxInputHandler
3194 // ----------------------------------------------------------------------------
3196 bool wxWin32CheckboxInputHandler::HandleKey(wxControl
*control
,
3197 const wxKeyEvent
& event
,
3202 wxControlAction action
;
3203 int keycode
= event
.GetKeyCode();
3207 action
= wxACTION_CHECKBOX_TOGGLE
;
3211 case WXK_NUMPAD_SUBTRACT
:
3212 action
= wxACTION_CHECKBOX_CHECK
;
3216 case WXK_NUMPAD_ADD
:
3217 case WXK_NUMPAD_EQUAL
:
3218 action
= wxACTION_CHECKBOX_CLEAR
;
3224 control
->PerformAction(action
);
3233 // ----------------------------------------------------------------------------
3234 // wxWin32TextCtrlInputHandler
3235 // ----------------------------------------------------------------------------
3237 bool wxWin32TextCtrlInputHandler::HandleKey(wxControl
*control
,
3238 const wxKeyEvent
& event
,
3241 // handle only MSW-specific text bindings here, the others are handled in
3245 int keycode
= event
.GetKeyCode();
3247 wxControlAction action
;
3248 if ( keycode
== WXK_DELETE
&& event
.ShiftDown() )
3250 action
= wxACTION_TEXT_CUT
;
3252 else if ( keycode
== WXK_INSERT
)
3254 if ( event
.ControlDown() )
3255 action
= wxACTION_TEXT_COPY
;
3256 else if ( event
.ShiftDown() )
3257 action
= wxACTION_TEXT_PASTE
;
3260 if ( action
!= wxACTION_NONE
)
3262 control
->PerformAction(action
);
3268 return wxStdTextCtrlInputHandler::HandleKey(control
, event
, pressed
);