1 // Name: univ/themes/win32.cpp
2 // Purpose: wxUniversal theme implementing Win32-like LNF
3 // Author: Vadim Zeitlin
7 // Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
8 // Licence: wxWindows license
9 ///////////////////////////////////////////////////////////////////////////////
11 // ===========================================================================
13 // ===========================================================================
15 // ---------------------------------------------------------------------------
17 // ---------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
30 #include "wx/window.h"
32 #include "wx/dcmemory.h"
34 #include "wx/button.h"
35 #include "wx/listbox.h"
36 #include "wx/checklst.h"
37 #include "wx/combobox.h"
38 #include "wx/scrolbar.h"
39 #include "wx/slider.h"
40 #include "wx/textctrl.h"
43 #include "wx/notebook.h"
44 #include "wx/spinbutt.h"
45 #include "wx/settings.h"
48 #include "wx/univ/scrtimer.h"
50 #include "wx/univ/renderer.h"
51 #include "wx/univ/inphand.h"
52 #include "wx/univ/colschem.h"
53 #include "wx/univ/theme.h"
55 // ----------------------------------------------------------------------------
57 // ----------------------------------------------------------------------------
59 static const int BORDER_THICKNESS
= 2;
61 // the offset between the label and focus rect around it
62 static const int FOCUS_RECT_OFFSET_X
= 1;
63 static const int FOCUS_RECT_OFFSET_Y
= 1;
75 IndicatorState_Normal
,
76 IndicatorState_Pressed
, // this one is for check/radioboxes
77 IndicatorState_Selected
= IndicatorState_Pressed
, // for menus
78 IndicatorState_Disabled
,
79 IndicatorState_SelectedDisabled
, // only for the menus
85 IndicatorStatus_Checked
,
86 IndicatorStatus_Unchecked
,
90 // wxWin32Renderer: draw the GUI elements in Win32 style
91 // ----------------------------------------------------------------------------
93 class wxWin32Renderer
: public wxRenderer
112 Arrow_InversedDisabled
,
117 wxWin32Renderer(const wxColourScheme
*scheme
);
119 // implement the base class pure virtuals
120 virtual void DrawBackground(wxDC
& dc
,
124 virtual void DrawLabel(wxDC
& dc
,
125 const wxString
& label
,
128 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
130 wxRect
*rectBounds
= NULL
);
131 virtual void DrawButtonLabel(wxDC
& dc
,
132 const wxString
& label
,
133 const wxBitmap
& image
,
136 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
138 wxRect
*rectBounds
= NULL
);
139 virtual void DrawBorder(wxDC
& dc
,
143 wxRect
*rectIn
= (wxRect
*)NULL
);
144 virtual void DrawHorizontalLine(wxDC
& dc
,
145 wxCoord y
, wxCoord x1
, wxCoord x2
);
146 virtual void DrawVerticalLine(wxDC
& dc
,
147 wxCoord x
, wxCoord y1
, wxCoord y2
);
148 virtual void DrawFrame(wxDC
& dc
,
149 const wxString
& label
,
152 int alignment
= wxALIGN_LEFT
,
153 int indexAccel
= -1);
154 virtual void DrawTextBorder(wxDC
& dc
,
158 wxRect
*rectIn
= (wxRect
*)NULL
);
159 virtual void DrawButtonBorder(wxDC
& dc
,
162 wxRect
*rectIn
= (wxRect
*)NULL
);
163 virtual void DrawArrow(wxDC
& dc
,
167 virtual void DrawScrollbarArrow(wxDC
& dc
,
171 { DrawArrow(dc
, dir
, rect
, flags
); }
172 virtual void DrawScrollbarThumb(wxDC
& dc
,
173 wxOrientation orient
,
176 virtual void DrawScrollbarShaft(wxDC
& dc
,
177 wxOrientation orient
,
180 virtual void DrawScrollCorner(wxDC
& dc
,
182 virtual void DrawItem(wxDC
& dc
,
183 const wxString
& label
,
186 virtual void DrawCheckItem(wxDC
& dc
,
187 const wxString
& label
,
188 const wxBitmap
& bitmap
,
191 virtual void DrawCheckButton(wxDC
& dc
,
192 const wxString
& label
,
193 const wxBitmap
& bitmap
,
196 wxAlignment align
= wxALIGN_LEFT
,
197 int indexAccel
= -1);
198 virtual void DrawRadioButton(wxDC
& dc
,
199 const wxString
& label
,
200 const wxBitmap
& bitmap
,
203 wxAlignment align
= wxALIGN_LEFT
,
204 int indexAccel
= -1);
205 virtual void DrawTextLine(wxDC
& dc
,
206 const wxString
& text
,
211 virtual void DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
);
212 virtual void DrawTab(wxDC
& dc
,
215 const wxString
& label
,
216 const wxBitmap
& bitmap
= wxNullBitmap
,
218 int indexAccel
= -1);
220 virtual void DrawSliderShaft(wxDC
& dc
,
222 wxOrientation orient
,
224 wxRect
*rectShaft
= NULL
);
225 virtual void DrawSliderThumb(wxDC
& dc
,
227 wxOrientation orient
,
229 virtual void DrawSliderTicks(wxDC
& dc
,
231 const wxSize
& sizeThumb
,
232 wxOrientation orient
,
239 virtual void DrawMenuBarItem(wxDC
& dc
,
241 const wxString
& label
,
243 int indexAccel
= -1);
244 virtual void DrawMenuItem(wxDC
& dc
,
246 const wxMenuGeometryInfo
& geometryInfo
,
247 const wxString
& label
,
248 const wxString
& accel
,
249 const wxBitmap
& bitmap
= wxNullBitmap
,
251 int indexAccel
= -1);
252 virtual void DrawMenuSeparator(wxDC
& dc
,
254 const wxMenuGeometryInfo
& geomInfo
);
256 virtual void GetComboBitmaps(wxBitmap
*bmpNormal
,
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 // use the system colours under Windows
1093 #if defined(__WXMSW__)
1094 case WINDOW
: return wxColour(GetSysColor(COLOR_WINDOW
));
1096 case CONTROL_PRESSED
:
1097 case CONTROL_CURRENT
:
1098 case CONTROL
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1100 case CONTROL_TEXT
: return wxColour(GetSysColor(COLOR_BTNTEXT
));
1102 case SCROLLBAR
: return wxColour(GetSysColor(COLOR_SCROLLBAR
));
1103 case SCROLLBAR_PRESSED
: return wxColour(GetSysColor(COLOR_HIGHLIGHT
));
1105 case HIGHLIGHT
: return wxColour(GetSysColor(COLOR_HIGHLIGHT
));
1106 case HIGHLIGHT_TEXT
: return wxColour(GetSysColor(COLOR_HIGHLIGHTTEXT
));
1108 #if defined(COLOR_3DDKSHADOW)
1109 case SHADOW_DARK
: return wxColour(GetSysColor(COLOR_3DDKSHADOW
));
1111 case SHADOW_DARK
: return *wxBLACK
;
1114 case CONTROL_TEXT_DISABLED
:
1115 case SHADOW_HIGHLIGHT
: return wxColour(GetSysColor(COLOR_BTNHIGHLIGHT
));
1117 case SHADOW_IN
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1119 case CONTROL_TEXT_DISABLED_SHADOW
:
1120 case SHADOW_OUT
: return wxColour(GetSysColor(COLOR_BTNSHADOW
));
1122 // use the standard Windows colours elsewhere
1123 case WINDOW
: return *wxWHITE
;
1125 case CONTROL_PRESSED
:
1126 case CONTROL_CURRENT
:
1127 case CONTROL
: return wxColour(0xc0c0c0);
1129 case CONTROL_TEXT
: return *wxBLACK
;
1131 case SCROLLBAR
: return wxColour(0xe0e0e0);
1132 case SCROLLBAR_PRESSED
: return *wxBLACK
;
1134 case HIGHLIGHT
: return wxColour(0x800000);
1135 case HIGHLIGHT_TEXT
: return wxColour(0xffffff);
1137 case SHADOW_DARK
: return *wxBLACK
;
1139 case CONTROL_TEXT_DISABLED
:
1140 case SHADOW_HIGHLIGHT
: return wxColour(0xe0e0e0);
1142 case SHADOW_IN
: return wxColour(0xc0c0c0);
1144 case CONTROL_TEXT_DISABLED_SHADOW
:
1145 case SHADOW_OUT
: return wxColour(0x7f7f7f);
1150 wxFAIL_MSG(_T("invalid standard colour"));
1155 // ============================================================================
1157 // ============================================================================
1159 // ----------------------------------------------------------------------------
1161 // ----------------------------------------------------------------------------
1163 wxWin32Renderer::wxWin32Renderer(const wxColourScheme
*scheme
)
1167 m_sizeScrollbarArrow
= wxSize(16, 16);
1169 // init colours and pens
1170 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
), 0, wxSOLID
);
1172 m_colDarkGrey
= wxSCHEME_COLOUR(scheme
, SHADOW_OUT
);
1173 m_penDarkGrey
= wxPen(m_colDarkGrey
, 0, wxSOLID
);
1175 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
), 0, wxSOLID
);
1177 m_colHighlight
= wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
);
1178 m_penHighlight
= wxPen(m_colHighlight
, 0, wxSOLID
);
1180 // init the arrow bitmaps
1181 static const size_t ARROW_WIDTH
= 7;
1182 static const size_t ARROW_LENGTH
= 4;
1185 wxMemoryDC dcNormal
,
1188 for ( size_t n
= 0; n
< Arrow_Max
; n
++ )
1190 bool isVertical
= n
> Arrow_Right
;
1203 // disabled arrow is larger because of the shadow
1204 m_bmpArrows
[Arrow_Normal
][n
].Create(w
, h
);
1205 m_bmpArrows
[Arrow_Disabled
][n
].Create(w
+ 1, h
+ 1);
1207 dcNormal
.SelectObject(m_bmpArrows
[Arrow_Normal
][n
]);
1208 dcDisabled
.SelectObject(m_bmpArrows
[Arrow_Disabled
][n
]);
1210 dcNormal
.SetBackground(*wxWHITE_BRUSH
);
1211 dcDisabled
.SetBackground(*wxWHITE_BRUSH
);
1215 dcNormal
.SetPen(m_penBlack
);
1216 dcDisabled
.SetPen(m_penDarkGrey
);
1218 // calculate the position of the point of the arrow
1222 x1
= (ARROW_WIDTH
- 1)/2;
1223 y1
= n
== Arrow_Up
? 0 : ARROW_LENGTH
- 1;
1227 x1
= n
== Arrow_Left
? 0 : ARROW_LENGTH
- 1;
1228 y1
= (ARROW_WIDTH
- 1)/2;
1239 for ( size_t i
= 0; i
< ARROW_LENGTH
; i
++ )
1241 dcNormal
.DrawLine(x1
, y1
, x2
, y2
);
1242 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1249 if ( n
== Arrow_Up
)
1260 else // left or right arrow
1265 if ( n
== Arrow_Left
)
1278 // draw the shadow for the disabled one
1279 dcDisabled
.SetPen(m_penHighlight
);
1284 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1288 x1
= ARROW_LENGTH
- 1;
1289 y1
= (ARROW_WIDTH
- 1)/2 + 1;
1292 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1293 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1298 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1302 x1
= ARROW_WIDTH
- 1;
1304 x2
= (ARROW_WIDTH
- 1)/2;
1306 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1307 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1312 // create the inversed bitmap but only for the right arrow as we only
1313 // use it for the menus
1314 if ( n
== Arrow_Right
)
1316 m_bmpArrows
[Arrow_Inversed
][n
].Create(w
, h
);
1317 dcInverse
.SelectObject(m_bmpArrows
[Arrow_Inversed
][n
]);
1319 dcInverse
.Blit(0, 0, w
, h
,
1322 dcInverse
.SelectObject(wxNullBitmap
);
1324 mask
= new wxMask(m_bmpArrows
[Arrow_Inversed
][n
], *wxBLACK
);
1325 m_bmpArrows
[Arrow_Inversed
][n
].SetMask(mask
);
1327 m_bmpArrows
[Arrow_InversedDisabled
][n
].Create(w
, h
);
1328 dcInverse
.SelectObject(m_bmpArrows
[Arrow_InversedDisabled
][n
]);
1330 dcInverse
.Blit(0, 0, w
, h
,
1333 dcInverse
.SelectObject(wxNullBitmap
);
1335 mask
= new wxMask(m_bmpArrows
[Arrow_InversedDisabled
][n
], *wxBLACK
);
1336 m_bmpArrows
[Arrow_InversedDisabled
][n
].SetMask(mask
);
1339 dcNormal
.SelectObject(wxNullBitmap
);
1340 dcDisabled
.SelectObject(wxNullBitmap
);
1342 mask
= new wxMask(m_bmpArrows
[Arrow_Normal
][n
], *wxWHITE
);
1343 m_bmpArrows
[Arrow_Normal
][n
].SetMask(mask
);
1344 mask
= new wxMask(m_bmpArrows
[Arrow_Disabled
][n
], *wxWHITE
);
1345 m_bmpArrows
[Arrow_Disabled
][n
].SetMask(mask
);
1347 m_bmpArrows
[Arrow_Pressed
][n
] = m_bmpArrows
[Arrow_Normal
][n
];
1351 // ----------------------------------------------------------------------------
1353 // ----------------------------------------------------------------------------
1356 The raised border in Win32 looks like this:
1358 IIIIIIIIIIIIIIIIIIIIIIB
1360 I GB I = white (HILIGHT)
1361 I GB H = light grey (LIGHT)
1362 I GB G = dark grey (SHADOI)
1363 I GB B = black (DKSHADOI)
1364 I GB I = hIghlight (COLOR_3DHILIGHT)
1366 IGGGGGGGGGGGGGGGGGGGGGB
1367 BBBBBBBBBBBBBBBBBBBBBBB
1369 The sunken border looks like this:
1371 GGGGGGGGGGGGGGGGGGGGGGI
1372 GBBBBBBBBBBBBBBBBBBBBHI
1379 GHHHHHHHHHHHHHHHHHHHHHI
1380 IIIIIIIIIIIIIIIIIIIIIII
1382 The static border (used for the controls which don't get focus) is like
1385 GGGGGGGGGGGGGGGGGGGGGGW
1393 WWWWWWWWWWWWWWWWWWWWWWW
1395 The most complicated is the double border:
1397 HHHHHHHHHHHHHHHHHHHHHHB
1398 HWWWWWWWWWWWWWWWWWWWWGB
1399 HWHHHHHHHHHHHHHHHHHHHGB
1404 HWHHHHHHHHHHHHHHHHHHHGB
1405 HGGGGGGGGGGGGGGGGGGGGGB
1406 BBBBBBBBBBBBBBBBBBBBBBB
1408 And the simple border is, well, simple:
1410 BBBBBBBBBBBBBBBBBBBBBBB
1419 BBBBBBBBBBBBBBBBBBBBBBB
1422 void wxWin32Renderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1426 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1427 dc
.DrawRectangle(*rect
);
1433 void wxWin32Renderer::DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1435 // draw the bottom and right sides
1437 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1438 rect
->GetRight() + 1, rect
->GetBottom());
1439 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1440 rect
->GetRight(), rect
->GetBottom());
1447 void wxWin32Renderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
1448 const wxPen
& pen1
, const wxPen
& pen2
)
1450 // draw the rectangle
1452 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
1453 rect
->GetLeft(), rect
->GetBottom());
1454 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
1455 rect
->GetRight(), rect
->GetTop());
1457 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1458 rect
->GetRight(), rect
->GetBottom());
1459 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1460 rect
->GetRight() + 1, rect
->GetBottom());
1466 void wxWin32Renderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
1468 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
1469 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
1472 void wxWin32Renderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
1474 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
1475 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
1478 void wxWin32Renderer::DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
)
1482 DrawRect(dc
, rect
, m_penDarkGrey
);
1484 // the arrow is usually drawn inside border of width 2 and is offset by
1485 // another pixel in both directions when it's pressed - as the border
1486 // in this case is more narrow as well, we have to adjust rect like
1494 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
1495 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
1499 void wxWin32Renderer::DrawBorder(wxDC
& dc
,
1501 const wxRect
& rectTotal
,
1502 int WXUNUSED(flags
),
1507 wxRect rect
= rectTotal
;
1511 case wxBORDER_SUNKEN
:
1512 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1514 DrawSunkenBorder(dc
, &rect
);
1518 case wxBORDER_STATIC
:
1519 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1522 case wxBORDER_RAISED
:
1523 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1525 DrawRaisedBorder(dc
, &rect
);
1529 case wxBORDER_DOUBLE
:
1530 DrawArrowBorder(dc
, &rect
);
1531 DrawRect(dc
, &rect
, m_penLightGrey
);
1534 case wxBORDER_SIMPLE
:
1535 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1537 DrawRect(dc
, &rect
, m_penBlack
);
1542 wxFAIL_MSG(_T("unknown border type"));
1545 case wxBORDER_DEFAULT
:
1554 wxRect
wxWin32Renderer::GetBorderDimensions(wxBorder border
) const
1559 case wxBORDER_RAISED
:
1560 case wxBORDER_SUNKEN
:
1561 width
= BORDER_THICKNESS
;
1564 case wxBORDER_SIMPLE
:
1565 case wxBORDER_STATIC
:
1569 case wxBORDER_DOUBLE
:
1574 wxFAIL_MSG(_T("unknown border type"));
1577 case wxBORDER_DEFAULT
:
1587 rect
.height
= width
;
1592 bool wxWin32Renderer::AreScrollbarsInsideBorder() const
1597 // ----------------------------------------------------------------------------
1599 // ----------------------------------------------------------------------------
1601 void wxWin32Renderer::DrawTextBorder(wxDC
& dc
,
1607 // text controls are not special under windows
1608 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
1611 void wxWin32Renderer::DrawButtonBorder(wxDC
& dc
,
1612 const wxRect
& rectTotal
,
1616 wxRect rect
= rectTotal
;
1618 if ( flags
& wxCONTROL_PRESSED
)
1620 // button pressed: draw a double border around it
1621 DrawRect(dc
, &rect
, m_penBlack
);
1622 DrawRect(dc
, &rect
, m_penDarkGrey
);
1626 // button not pressed
1628 if ( flags
& (wxCONTROL_FOCUSED
| wxCONTROL_ISDEFAULT
) )
1630 // button either default or focused (or both): add an extra border around it
1631 DrawRect(dc
, &rect
, m_penBlack
);
1634 // now draw a normal button
1635 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penBlack
);
1636 DrawHalfRect(dc
, &rect
, m_penDarkGrey
);
1645 // ----------------------------------------------------------------------------
1647 // ----------------------------------------------------------------------------
1649 void wxWin32Renderer::DrawHorizontalLine(wxDC
& dc
,
1650 wxCoord y
, wxCoord x1
, wxCoord x2
)
1652 dc
.SetPen(m_penDarkGrey
);
1653 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1654 dc
.SetPen(m_penHighlight
);
1656 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1659 void wxWin32Renderer::DrawVerticalLine(wxDC
& dc
,
1660 wxCoord x
, wxCoord y1
, wxCoord y2
)
1662 dc
.SetPen(m_penDarkGrey
);
1663 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1664 dc
.SetPen(m_penHighlight
);
1666 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1669 void wxWin32Renderer::DrawFrame(wxDC
& dc
,
1670 const wxString
& label
,
1676 wxCoord height
= 0; // of the label
1677 wxRect rectFrame
= rect
;
1678 if ( !label
.empty() )
1680 // the text should touch the top border of the rect, so the frame
1681 // itself should be lower
1682 dc
.GetTextExtent(label
, NULL
, &height
);
1683 rectFrame
.y
+= height
/ 2;
1684 rectFrame
.height
-= height
/ 2;
1686 // we have to draw each part of the frame individually as we can't
1687 // erase the background beyond the label as it might contain some
1688 // pixmap already, so drawing everything and then overwriting part of
1689 // the frame with label doesn't work
1691 // TODO: the +5 and space insertion should be customizable
1694 rectText
.x
= rectFrame
.x
+ 5;
1695 rectText
.y
= rect
.y
;
1696 rectText
.width
= rectFrame
.width
- 7; // +2 border width
1697 rectText
.height
= height
;
1700 label2
<< _T(' ') << label
<< _T(' ');
1701 if ( indexAccel
!= -1 )
1703 // adjust it as we prepended a space
1708 DrawLabel(dc
, label2
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
1710 StandardDrawFrame(dc
, rectFrame
, rectLabel
);
1714 // just draw the complete frame
1715 DrawShadedRect(dc
, &rectFrame
, m_penDarkGrey
, m_penHighlight
);
1716 DrawShadedRect(dc
, &rectFrame
, m_penHighlight
, m_penDarkGrey
);
1720 // ----------------------------------------------------------------------------
1722 // ----------------------------------------------------------------------------
1724 void wxWin32Renderer::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
1726 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
1727 // pixels each while we really need dots here... PS_ALTERNATE might
1728 // work, but it is for NT 5 only
1730 DrawRect(dc
, &rect
, wxPen(*wxBLACK
, 0, wxDOT
));
1732 // draw the pixels manually: note that to behave in the same manner as
1733 // DrawRect(), we must exclude the bottom and right borders from the
1735 wxCoord x1
= rect
.GetLeft(),
1737 x2
= rect
.GetRight(),
1738 y2
= rect
.GetBottom();
1740 dc
.SetPen(wxPen(*wxBLACK
, 0, wxSOLID
));
1742 // this seems to be closer than what Windows does than wxINVERT although
1743 // I'm still not sure if it's correct
1744 dc
.SetLogicalFunction(wxAND_REVERSE
);
1747 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
1748 dc
.DrawPoint(z
, rect
.GetTop());
1750 wxCoord shift
= z
== x2
? 0 : 1;
1751 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
1752 dc
.DrawPoint(x2
, z
);
1754 shift
= z
== y2
? 0 : 1;
1755 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
1756 dc
.DrawPoint(z
, y2
);
1758 shift
= z
== x1
? 0 : 1;
1759 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
1760 dc
.DrawPoint(x1
, z
);
1762 dc
.SetLogicalFunction(wxCOPY
);
1766 void wxWin32Renderer::DrawLabelShadow(wxDC
& dc
,
1767 const wxString
& label
,
1772 // draw shadow of the text
1773 dc
.SetTextForeground(m_colHighlight
);
1774 wxRect rectShadow
= rect
;
1777 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
1779 // make the text grey
1780 dc
.SetTextForeground(m_colDarkGrey
);
1783 void wxWin32Renderer::DrawLabel(wxDC
& dc
,
1784 const wxString
& label
,
1791 DoDrawLabel(dc
, label
, rect
, flags
, alignment
, indexAccel
, rectBounds
);
1794 void wxWin32Renderer::DoDrawLabel(wxDC
& dc
,
1795 const wxString
& label
,
1801 const wxPoint
& focusOffset
)
1803 // the underscores are not drawn for focused controls in wxMSW
1804 if ( flags
& wxCONTROL_FOCUSED
)
1809 if ( flags
& wxCONTROL_DISABLED
)
1811 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
1812 // currently only can happen for a menu item and it seems that Windows
1813 // doesn't draw the shadow in this case, so we don't do it neither
1814 if ( flags
& wxCONTROL_SELECTED
)
1816 // just make the label text greyed out
1817 dc
.SetTextForeground(m_colDarkGrey
);
1819 else // draw normal disabled label
1821 DrawLabelShadow(dc
, label
, rect
, alignment
, indexAccel
);
1826 dc
.DrawLabel(label
, wxNullBitmap
, rect
, alignment
, indexAccel
, &rectLabel
);
1828 if ( flags
& wxCONTROL_DISABLED
)
1830 // restore the fg colour
1831 dc
.SetTextForeground(*wxBLACK
);
1834 if ( flags
& wxCONTROL_FOCUSED
)
1836 if ( focusOffset
.x
|| focusOffset
.y
)
1838 rectLabel
.Inflate(focusOffset
.x
, focusOffset
.y
);
1841 DrawFocusRect(dc
, rectLabel
);
1845 *rectBounds
= rectLabel
;
1848 void wxWin32Renderer::DrawButtonLabel(wxDC
& dc
,
1849 const wxString
& label
,
1850 const wxBitmap
& image
,
1857 // the underscores are not drawn for focused controls in wxMSW
1858 if ( flags
& wxCONTROL_PRESSED
)
1863 wxRect rectLabel
= rect
;
1864 if ( !label
.empty() )
1866 // shift the label if a button is pressed
1867 if ( flags
& wxCONTROL_PRESSED
)
1873 if ( flags
& wxCONTROL_DISABLED
)
1875 DrawLabelShadow(dc
, label
, rectLabel
, alignment
, indexAccel
);
1878 // leave enough space for the focus rectangle
1879 if ( flags
& wxCONTROL_FOCUSED
)
1881 rectLabel
.Inflate(-2);
1885 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
1887 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
1889 if ( flags
& wxCONTROL_PRESSED
)
1891 // the focus rectangle is never pressed, so undo the shift done
1899 DrawFocusRect(dc
, rectLabel
);
1903 // ----------------------------------------------------------------------------
1904 // (check)listbox items
1905 // ----------------------------------------------------------------------------
1907 void wxWin32Renderer::DrawItem(wxDC
& dc
,
1908 const wxString
& label
,
1912 wxDCTextColourChanger
colChanger(dc
);
1914 if ( flags
& wxCONTROL_SELECTED
)
1916 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
1918 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
1919 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
1920 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
1921 dc
.DrawRectangle(rect
);
1924 wxRect rectText
= rect
;
1926 rectText
.width
-= 2;
1927 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
1929 if ( flags
& wxCONTROL_FOCUSED
)
1931 DrawFocusRect(dc
, rect
);
1935 void wxWin32Renderer::DrawCheckItem(wxDC
& dc
,
1936 const wxString
& label
,
1937 const wxBitmap
& bitmap
,
1946 else // use default bitmap
1948 bmp
= wxBitmap(flags
& wxCONTROL_CHECKED
? checked_item_xpm
1949 : unchecked_item_xpm
);
1952 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2 - 1,
1953 TRUE
/* use mask */);
1955 wxRect rectLabel
= rect
;
1956 int bmpWidth
= bmp
.GetWidth();
1957 rectLabel
.x
+= bmpWidth
;
1958 rectLabel
.width
-= bmpWidth
;
1960 DrawItem(dc
, label
, rectLabel
, flags
);
1963 // ----------------------------------------------------------------------------
1964 // check/radio buttons
1965 // ----------------------------------------------------------------------------
1967 wxBitmap
wxWin32Renderer::GetIndicator(IndicatorType indType
, int flags
)
1969 IndicatorState indState
;
1970 if ( flags
& wxCONTROL_SELECTED
)
1971 indState
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
1972 : IndicatorState_Selected
;
1973 else if ( flags
& wxCONTROL_DISABLED
)
1974 indState
= IndicatorState_Disabled
;
1975 else if ( flags
& wxCONTROL_PRESSED
)
1976 indState
= IndicatorState_Pressed
;
1978 indState
= IndicatorState_Normal
;
1980 IndicatorStatus indStatus
= flags
& wxCONTROL_CHECKED
1981 ? IndicatorStatus_Checked
1982 : IndicatorStatus_Unchecked
;
1984 const char **xpm
= bmpIndicators
[indType
][indState
][indStatus
];
1985 return xpm
? wxBitmap(xpm
) : wxNullBitmap
;
1988 void wxWin32Renderer::DrawCheckOrRadioButton(wxDC
& dc
,
1989 const wxString
& label
,
1990 const wxBitmap
& bitmap
,
1995 wxCoord focusOffsetY
)
1997 // calculate the position of the bitmap and of the label
1998 wxCoord heightBmp
= bitmap
.GetHeight();
2000 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
2003 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
2004 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
2006 // align label vertically with the bitmap - looks nicer like this
2007 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
2009 // calc horz position
2010 if ( align
== wxALIGN_RIGHT
)
2012 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
2013 rectLabel
.x
= rect
.x
+ 3;
2014 rectLabel
.SetRight(xBmp
);
2016 else // normal (checkbox to the left of the text) case
2019 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
2020 rectLabel
.SetRight(rect
.GetRight());
2023 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, TRUE
/* use mask */);
2026 dc
, label
, rectLabel
,
2028 wxALIGN_LEFT
| wxALIGN_TOP
,
2030 NULL
, // we don't need bounding rect
2031 // use custom vert focus rect offset
2032 wxPoint(FOCUS_RECT_OFFSET_X
, focusOffsetY
)
2036 void wxWin32Renderer::DrawRadioButton(wxDC
& dc
,
2037 const wxString
& label
,
2038 const wxBitmap
& bitmap
,
2044 DrawCheckOrRadioButton(dc
, label
,
2045 bitmap
.Ok() ? bitmap
: GetRadioBitmap(flags
),
2046 rect
, flags
, align
, indexAccel
,
2047 FOCUS_RECT_OFFSET_Y
); // default focus rect offset
2050 void wxWin32Renderer::DrawCheckButton(wxDC
& dc
,
2051 const wxString
& label
,
2052 const wxBitmap
& bitmap
,
2058 DrawCheckOrRadioButton(dc
, label
,
2059 bitmap
.Ok() ? bitmap
: GetCheckBitmap(flags
),
2060 rect
, flags
, align
, indexAccel
,
2061 0); // no focus rect offset for checkboxes
2064 // ----------------------------------------------------------------------------
2066 // ----------------------------------------------------------------------------
2068 void wxWin32Renderer::DrawTextLine(wxDC
& dc
,
2069 const wxString
& text
,
2075 // nothing special to do here
2076 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
2079 void wxWin32Renderer::DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
)
2081 // we don't draw them
2084 // ----------------------------------------------------------------------------
2086 // ----------------------------------------------------------------------------
2088 void wxWin32Renderer::DrawTab(wxDC
& dc
,
2089 const wxRect
& rectOrig
,
2091 const wxString
& label
,
2092 const wxBitmap
& bitmap
,
2096 wxRect rect
= rectOrig
;
2098 // the current tab is drawn indented (to the top for default case) and
2099 // bigger than the other ones
2100 const wxSize indent
= GetTabIndent();
2101 if ( flags
& wxCONTROL_SELECTED
)
2106 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2110 rect
.Inflate(indent
.x
, 0);
2112 rect
.height
+= indent
.y
;
2116 rect
.Inflate(indent
.x
, 0);
2117 rect
.height
+= indent
.y
;
2122 wxFAIL_MSG(_T("TODO"));
2127 // draw the text, image and the focus around them (if necessary)
2128 wxRect rectLabel
= rect
;
2129 rectLabel
.Deflate(1, 1);
2130 DrawButtonLabel(dc
, label
, bitmap
, rectLabel
,
2131 flags
, wxALIGN_CENTRE
, indexAccel
);
2133 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2134 static const wxCoord CUTOFF
= 2; // radius of the rounded corner
2137 x2
= rect
.GetRight(),
2138 y2
= rect
.GetBottom();
2140 // FIXME: all this code will break if the tab indent or the border width,
2141 // it is tied to the fact that both of them are equal to 2
2146 dc
.SetPen(m_penHighlight
);
2147 dc
.DrawLine(x
, y2
, x
, y
+ CUTOFF
);
2148 dc
.DrawLine(x
, y
+ CUTOFF
, x
+ CUTOFF
, y
);
2149 dc
.DrawLine(x
+ CUTOFF
, y
, x2
- CUTOFF
+ 1, y
);
2151 dc
.SetPen(m_penBlack
);
2152 dc
.DrawLine(x2
, y2
, x2
, y
+ CUTOFF
);
2153 dc
.DrawLine(x2
, y
+ CUTOFF
, x2
- CUTOFF
, y
);
2155 dc
.SetPen(m_penDarkGrey
);
2156 dc
.DrawLine(x2
- 1, y2
, x2
- 1, y
+ CUTOFF
- 1);
2158 if ( flags
& wxCONTROL_SELECTED
)
2160 dc
.SetPen(m_penLightGrey
);
2162 // overwrite the part of the border below this tab
2163 dc
.DrawLine(x
+ 1, y2
+ 1, x2
- 1, y2
+ 1);
2165 // and the shadow of the tab to the left of us
2166 dc
.DrawLine(x
+ 1, y
+ CUTOFF
+ 1, x
+ 1, y2
+ 1);
2171 dc
.SetPen(m_penHighlight
);
2172 // we need to continue one pixel further to overwrite the corner of
2173 // the border for the selected tab
2174 dc
.DrawLine(x
, y
- (flags
& wxCONTROL_SELECTED
? 1 : 0),
2176 dc
.DrawLine(x
, y2
- CUTOFF
, x
+ CUTOFF
, y2
);
2178 dc
.SetPen(m_penBlack
);
2179 dc
.DrawLine(x
+ CUTOFF
, y2
, x2
- CUTOFF
+ 1, y2
);
2180 dc
.DrawLine(x2
, y
, x2
, y2
- CUTOFF
);
2181 dc
.DrawLine(x2
, y2
- CUTOFF
, x2
- CUTOFF
, y2
);
2183 dc
.SetPen(m_penDarkGrey
);
2184 dc
.DrawLine(x
+ CUTOFF
, y2
- 1, x2
- CUTOFF
+ 1, y2
- 1);
2185 dc
.DrawLine(x2
- 1, y
, x2
- 1, y2
- CUTOFF
+ 1);
2187 if ( flags
& wxCONTROL_SELECTED
)
2189 dc
.SetPen(m_penLightGrey
);
2191 // overwrite the part of the (double!) border above this tab
2192 dc
.DrawLine(x
+ 1, y
- 1, x2
- 1, y
- 1);
2193 dc
.DrawLine(x
+ 1, y
- 2, x2
- 1, y
- 2);
2195 // and the shadow of the tab to the left of us
2196 dc
.DrawLine(x
+ 1, y2
- CUTOFF
, x
+ 1, y
- 1);
2202 wxFAIL_MSG(_T("TODO"));
2206 // ----------------------------------------------------------------------------
2208 // ----------------------------------------------------------------------------
2210 wxSize
wxWin32Renderer::GetSliderThumbSize(const wxRect
& rect
,
2211 wxOrientation orient
) const
2215 wxRect rectShaft
= GetSliderShaftRect(rect
, orient
);
2216 if ( orient
== wxHORIZONTAL
)
2218 size
.y
= rect
.height
- 6;
2219 size
.x
= wxMin(size
.y
/ 2, rectShaft
.width
);
2223 size
.x
= rect
.width
- 6;
2224 size
.y
= wxMin(size
.x
/ 2, rectShaft
.height
);
2230 wxRect
wxWin32Renderer::GetSliderShaftRect(const wxRect
& rectOrig
,
2231 wxOrientation orient
) const
2233 static const wxCoord SLIDER_MARGIN
= 6;
2235 wxRect rect
= rectOrig
;
2237 if ( orient
== wxHORIZONTAL
)
2239 // make the rect of minimal width and centre it
2240 rect
.height
= 2*BORDER_THICKNESS
;
2241 rect
.y
= rectOrig
.y
+ (rectOrig
.height
- rect
.height
) / 2;
2245 // leave margins on the sides
2246 rect
.Deflate(SLIDER_MARGIN
, 0);
2250 // same as above but in other direction
2251 rect
.width
= 2*BORDER_THICKNESS
;
2252 rect
.x
= rectOrig
.x
+ (rectOrig
.width
- rect
.width
) / 2;
2256 rect
.Deflate(0, SLIDER_MARGIN
);
2262 void wxWin32Renderer::DrawSliderShaft(wxDC
& dc
,
2263 const wxRect
& rectOrig
,
2264 wxOrientation orient
,
2268 if ( flags
& wxCONTROL_FOCUSED
)
2270 DrawFocusRect(dc
, rectOrig
);
2273 wxRect rect
= GetSliderShaftRect(rectOrig
, orient
);
2278 DrawSunkenBorder(dc
, &rect
);
2281 void wxWin32Renderer::DrawSliderThumb(wxDC
& dc
,
2283 wxOrientation orient
,
2287 we are drawing a shape of this form
2292 H DB where H is hightlight colour
2305 The interior of this shape is filled with the hatched brush if the thumb
2309 DrawBackground(dc
, wxNullColour
, rect
, flags
);
2311 bool transpose
= orient
== wxVERTICAL
;
2313 wxCoord x
, y
, x2
, y2
;
2318 x2
= rect
.GetBottom();
2319 y2
= rect
.GetRight();
2325 x2
= rect
.GetRight();
2326 y2
= rect
.GetBottom();
2329 // the size of the pointed part of the thumb
2330 wxCoord sizeArrow
= (transpose
? rect
.height
: rect
.width
) / 2;
2332 wxCoord x3
= x
+ sizeArrow
,
2333 y3
= y2
- sizeArrow
;
2335 dc
.SetPen(m_penHighlight
);
2336 DrawLine(dc
, x
, y
, x2
, y
, transpose
);
2337 DrawLine(dc
, x
, y
+ 1, x
, y2
- sizeArrow
, transpose
);
2338 DrawLine(dc
, x
, y3
, x3
, y2
, transpose
);
2340 dc
.SetPen(m_penBlack
);
2341 DrawLine(dc
, x3
, y2
, x2
, y3
, transpose
);
2342 DrawLine(dc
, x2
, y3
, x2
, y
- 1, transpose
);
2344 dc
.SetPen(m_penDarkGrey
);
2345 DrawLine(dc
, x3
, y2
- 1, x2
- 1, y3
, transpose
);
2346 DrawLine(dc
, x2
- 1, y3
, x2
- 1, y
, transpose
);
2348 if ( flags
& wxCONTROL_PRESSED
)
2350 // TODO: MSW fills the entire area inside, not just the rect
2351 wxRect rectInt
= rect
;
2353 rectInt
.SetRight(y3
);
2355 rectInt
.SetBottom(y3
);
2358 static const char *stipple_xpm
[] = {
2359 /* columns rows colors chars-per-pixel */
2367 dc
.SetBrush(wxBrush(stipple_xpm
));
2369 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, SHADOW_HIGHLIGHT
));
2370 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, CONTROL
));
2371 dc
.SetPen(*wxTRANSPARENT_PEN
);
2372 dc
.DrawRectangle(rectInt
);
2376 void wxWin32Renderer::DrawSliderTicks(wxDC
& dc
,
2378 const wxSize
& sizeThumb
,
2379 wxOrientation orient
,
2391 // the variable names correspond to horizontal case, but they can be used
2392 // for both orientations
2393 wxCoord x1
, x2
, y1
, y2
, len
, widthThumb
;
2394 if ( orient
== wxHORIZONTAL
)
2396 x1
= rect
.GetLeft();
2397 x2
= rect
.GetRight();
2399 // draw from bottom to top to leave one pixel space between the ticks
2400 // and the slider as Windows do
2401 y1
= rect
.GetBottom();
2406 widthThumb
= sizeThumb
.x
;
2411 x2
= rect
.GetBottom();
2413 y1
= rect
.GetRight();
2414 y2
= rect
.GetLeft();
2418 widthThumb
= sizeThumb
.y
;
2421 // the first tick should be positioned in such way that a thumb drawn in
2422 // the first position points down directly to it
2423 x1
+= widthThumb
/ 2;
2424 x2
-= widthThumb
/ 2;
2426 // this also means that we have slightly less space for the ticks in
2427 // between the first and the last
2430 dc
.SetPen(m_penBlack
);
2432 int range
= end
- start
;
2433 for ( int n
= 0; n
< range
; n
+= step
)
2435 wxCoord x
= x1
+ (len
*n
) / range
;
2437 DrawLine(dc
, x
, y1
, x
, y2
, orient
== wxVERTICAL
);
2440 // always draw the line at the end position
2441 DrawLine(dc
, x2
, y1
, x2
, y2
, orient
== wxVERTICAL
);
2444 // ----------------------------------------------------------------------------
2446 // ----------------------------------------------------------------------------
2450 // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2451 class WXDLLEXPORT wxWin32MenuGeometryInfo
: public wxMenuGeometryInfo
2454 virtual wxSize
GetSize() const { return m_size
; }
2456 wxCoord
GetLabelOffset() const { return m_ofsLabel
; }
2457 wxCoord
GetAccelOffset() const { return m_ofsAccel
; }
2459 wxCoord
GetItemHeight() const { return m_heightItem
; }
2462 // the total size of the menu
2465 // the offset of the start of the menu item label
2468 // the offset of the start of the accel label
2471 // the height of a normal (not separator) item
2472 wxCoord m_heightItem
;
2474 friend wxMenuGeometryInfo
*wxWin32Renderer::
2475 GetMenuGeometry(wxWindow
*, const wxMenu
&) const;
2478 #endif // wxUSE_MENUS
2480 // FIXME: all constants are hardcoded but shouldn't be
2481 static const wxCoord MENU_LEFT_MARGIN
= 9;
2482 static const wxCoord MENU_RIGHT_MARGIN
= 18;
2483 static const wxCoord MENU_VERT_MARGIN
= 3;
2485 // the margin around bitmap/check marks (on each side)
2486 static const wxCoord MENU_BMP_MARGIN
= 2;
2488 // the margin between the labels and accel strings
2489 static const wxCoord MENU_ACCEL_MARGIN
= 8;
2491 // the separator height in pixels: in fact, strangely enough, the real height
2492 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2494 static const wxCoord MENU_SEPARATOR_HEIGHT
= 3;
2496 // the size of the standard checkmark bitmap
2497 static const wxCoord MENU_CHECK_SIZE
= 9;
2499 // we can't implement these methods without wxMenuGeometryInfo implementation
2500 // which we don't have if !wxUSE_MENUS
2503 void wxWin32Renderer::DrawMenuBarItem(wxDC
& dc
,
2504 const wxRect
& rectOrig
,
2505 const wxString
& label
,
2509 wxRect rect
= rectOrig
;
2512 wxDCTextColourChanger
colChanger(dc
);
2514 if ( flags
& wxCONTROL_SELECTED
)
2516 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2518 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2519 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2520 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2521 dc
.DrawRectangle(rect
);
2524 // don't draw the focus rect around menu bar items
2525 DrawLabel(dc
, label
, rect
, flags
& ~wxCONTROL_FOCUSED
,
2526 wxALIGN_CENTRE
, indexAccel
);
2529 void wxWin32Renderer::DrawMenuItem(wxDC
& dc
,
2531 const wxMenuGeometryInfo
& gi
,
2532 const wxString
& label
,
2533 const wxString
& accel
,
2534 const wxBitmap
& bitmap
,
2538 const wxWin32MenuGeometryInfo
& geometryInfo
=
2539 (const wxWin32MenuGeometryInfo
&)gi
;
2544 rect
.width
= geometryInfo
.GetSize().x
;
2545 rect
.height
= geometryInfo
.GetItemHeight();
2547 // draw the selected item specially
2548 wxDCTextColourChanger
colChanger(dc
);
2549 if ( flags
& wxCONTROL_SELECTED
)
2551 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2553 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2554 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2555 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2556 dc
.DrawRectangle(rect
);
2559 // draw the bitmap: use the bitmap provided or the standard checkmark for
2560 // the checkable items
2561 wxBitmap bmp
= bitmap
;
2562 if ( !bmp
.Ok() && (flags
& wxCONTROL_CHECKED
) )
2564 bmp
= GetIndicator(IndicatorType_Menu
, flags
);
2569 rect
.SetRight(geometryInfo
.GetLabelOffset());
2570 wxControlRenderer::DrawBitmap(dc
, bmp
, rect
);
2574 rect
.x
= geometryInfo
.GetLabelOffset();
2575 rect
.SetRight(geometryInfo
.GetAccelOffset());
2577 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
, indexAccel
);
2579 // draw the accel string
2580 rect
.x
= geometryInfo
.GetAccelOffset();
2581 rect
.SetRight(geometryInfo
.GetSize().x
);
2583 // NB: no accel index here
2584 DrawLabel(dc
, accel
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
);
2586 // draw the submenu indicator
2587 if ( flags
& wxCONTROL_ISSUBMENU
)
2589 rect
.x
= geometryInfo
.GetSize().x
- MENU_RIGHT_MARGIN
;
2590 rect
.width
= MENU_RIGHT_MARGIN
;
2592 wxArrowStyle arrowStyle
;
2593 if ( flags
& wxCONTROL_DISABLED
)
2594 arrowStyle
= flags
& wxCONTROL_SELECTED
? Arrow_InversedDisabled
2596 else if ( flags
& wxCONTROL_SELECTED
)
2597 arrowStyle
= Arrow_Inversed
;
2599 arrowStyle
= Arrow_Normal
;
2601 DrawArrow(dc
, rect
, Arrow_Right
, arrowStyle
);
2605 void wxWin32Renderer::DrawMenuSeparator(wxDC
& dc
,
2607 const wxMenuGeometryInfo
& geomInfo
)
2609 DrawHorizontalLine(dc
, y
+ MENU_VERT_MARGIN
, 0, geomInfo
.GetSize().x
);
2612 wxSize
wxWin32Renderer::GetMenuBarItemSize(const wxSize
& sizeText
) const
2614 wxSize size
= sizeText
;
2616 // FIXME: menubar height is configurable under Windows
2623 wxMenuGeometryInfo
*wxWin32Renderer::GetMenuGeometry(wxWindow
*win
,
2624 const wxMenu
& menu
) const
2626 // prepare the dc: for now we draw all the items with the system font
2628 dc
.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
));
2630 // the height of a normal item
2631 wxCoord heightText
= dc
.GetCharHeight();
2636 // the max length of label and accel strings: the menu width is the sum of
2637 // them, even if they're for different items (as the accels should be
2640 // the max length of the bitmap is never 0 as Windows always leaves enough
2641 // space for a check mark indicator
2642 wxCoord widthLabelMax
= 0,
2644 widthBmpMax
= MENU_LEFT_MARGIN
;
2646 for ( wxMenuItemList::Node
*node
= menu
.GetMenuItems().GetFirst();
2648 node
= node
->GetNext() )
2650 // height of this item
2653 wxMenuItem
*item
= node
->GetData();
2654 if ( item
->IsSeparator() )
2656 h
= MENU_SEPARATOR_HEIGHT
;
2658 else // not separator
2663 dc
.GetTextExtent(item
->GetLabel(), &widthLabel
, NULL
);
2664 if ( widthLabel
> widthLabelMax
)
2666 widthLabelMax
= widthLabel
;
2670 dc
.GetTextExtent(item
->GetAccelString(), &widthAccel
, NULL
);
2671 if ( widthAccel
> widthAccelMax
)
2673 widthAccelMax
= widthAccel
;
2676 const wxBitmap
& bmp
= item
->GetBitmap();
2679 wxCoord widthBmp
= bmp
.GetWidth();
2680 if ( widthBmp
> widthBmpMax
)
2681 widthBmpMax
= widthBmp
;
2683 //else if ( item->IsCheckable() ): no need to check for this as
2684 // MENU_LEFT_MARGIN is big enough to show the check mark
2687 h
+= 2*MENU_VERT_MARGIN
;
2689 // remember the item position and height
2690 item
->SetGeometry(height
, h
);
2695 // bundle the metrics into a struct and return it
2696 wxWin32MenuGeometryInfo
*gi
= new wxWin32MenuGeometryInfo
;
2698 gi
->m_ofsLabel
= widthBmpMax
+ 2*MENU_BMP_MARGIN
;
2699 gi
->m_ofsAccel
= gi
->m_ofsLabel
+ widthLabelMax
;
2700 if ( widthAccelMax
> 0 )
2702 // if we actually have any accesl, add a margin
2703 gi
->m_ofsAccel
+= MENU_ACCEL_MARGIN
;
2706 gi
->m_heightItem
= heightText
+ 2*MENU_VERT_MARGIN
;
2708 gi
->m_size
.x
= gi
->m_ofsAccel
+ widthAccelMax
+ MENU_RIGHT_MARGIN
;
2709 gi
->m_size
.y
= height
;
2714 #else // !wxUSE_MENUS
2717 void wxWin32Renderer::DrawMenuBarItem(wxDC& WXUNUSED(dc),
2718 const wxRect& WXUNUSED(rectOrig),
2719 const wxString& WXUNUSED(label),
2720 int WXUNUSED(flags),
2721 int WXUNUSED(indexAccel))
2725 void wxWin32Renderer::DrawMenuItem(wxDC& WXUNUSED(dc),
2726 wxCoord WXUNUSED(y),
2727 const wxMenuGeometryInfo& WXUNUSED(gi),
2728 const wxString& WXUNUSED(label),
2729 const wxString& WXUNUSED(accel),
2730 const wxBitmap& WXUNUSED(bitmap),
2731 int WXUNUSED(flags),
2732 int WXUNUSED(indexAccel))
2736 void wxWin32Renderer::DrawMenuSeparator(wxDC& WXUNUSED(dc),
2737 wxCoord WXUNUSED(y),
2738 const wxMenuGeometryInfo& WXUNUSED(gi))
2742 wxSize wxWin32Renderer::GetMenuBarItemSize(const wxSize& size) const
2747 wxMenuGeometryInfo *
2748 wxWin32Renderer::GetMenuGeometry(wxWindow *WXUNUSED(win),
2749 const wxMenu& WXUNUSED(menu)) const
2755 #endif // wxUSE_MENUS/!wxUSE_MENUS
2757 // ----------------------------------------------------------------------------
2759 // ----------------------------------------------------------------------------
2761 void wxWin32Renderer::GetComboBitmaps(wxBitmap
*bmpNormal
,
2763 wxBitmap
*bmpPressed
,
2764 wxBitmap
*bmpDisabled
)
2766 static const wxCoord widthCombo
= 16;
2767 static const wxCoord heightCombo
= 17;
2773 bmpNormal
->Create(widthCombo
, heightCombo
);
2774 dcMem
.SelectObject(*bmpNormal
);
2775 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2776 Arrow_Down
, Arrow_Normal
);
2781 bmpPressed
->Create(widthCombo
, heightCombo
);
2782 dcMem
.SelectObject(*bmpPressed
);
2783 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2784 Arrow_Down
, Arrow_Pressed
);
2789 bmpDisabled
->Create(widthCombo
, heightCombo
);
2790 dcMem
.SelectObject(*bmpDisabled
);
2791 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2792 Arrow_Down
, Arrow_Disabled
);
2796 // ----------------------------------------------------------------------------
2798 // ----------------------------------------------------------------------------
2800 void wxWin32Renderer::DoDrawBackground(wxDC
& dc
,
2801 const wxColour
& col
,
2804 wxBrush
brush(col
, wxSOLID
);
2806 dc
.SetPen(*wxTRANSPARENT_PEN
);
2807 dc
.DrawRectangle(rect
);
2810 void wxWin32Renderer::DrawBackground(wxDC
& dc
,
2811 const wxColour
& col
,
2815 // just fill it with the given or default bg colour
2816 wxColour colBg
= col
.Ok() ? col
: wxSCHEME_COLOUR(m_scheme
, CONTROL
);
2817 DoDrawBackground(dc
, colBg
, rect
);
2820 // ----------------------------------------------------------------------------
2822 // ----------------------------------------------------------------------------
2824 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2829 // get the bitmap for this arrow
2830 wxArrowDirection arrowDir
;
2833 case wxLEFT
: arrowDir
= Arrow_Left
; break;
2834 case wxRIGHT
: arrowDir
= Arrow_Right
; break;
2835 case wxUP
: arrowDir
= Arrow_Up
; break;
2836 case wxDOWN
: arrowDir
= Arrow_Down
; break;
2839 wxFAIL_MSG(_T("unknown arrow direction"));
2843 wxArrowStyle arrowStyle
;
2844 if ( flags
& wxCONTROL_PRESSED
)
2846 // can't be pressed and disabled
2847 arrowStyle
= Arrow_Pressed
;
2851 arrowStyle
= flags
& wxCONTROL_DISABLED
? Arrow_Disabled
: Arrow_Normal
;
2854 DrawArrowButton(dc
, rect
, arrowDir
, arrowStyle
);
2857 void wxWin32Renderer::DrawArrow(wxDC
& dc
,
2859 wxArrowDirection arrowDir
,
2860 wxArrowStyle arrowStyle
)
2862 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
2864 // under Windows the arrows always have the same size so just centre it in
2865 // the provided rectangle
2866 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
2867 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
2869 // Windows does it like this...
2870 if ( arrowDir
== Arrow_Left
)
2874 dc
.DrawBitmap(bmp
, x
, y
, TRUE
/* use mask */);
2877 void wxWin32Renderer::DrawArrowButton(wxDC
& dc
,
2878 const wxRect
& rectAll
,
2879 wxArrowDirection arrowDir
,
2880 wxArrowStyle arrowStyle
)
2882 wxRect rect
= rectAll
;
2883 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2884 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
2885 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
2888 void wxWin32Renderer::DrawScrollbarThumb(wxDC
& dc
,
2889 wxOrientation orient
,
2893 // we don't use the flags, the thumb never changes appearance
2894 wxRect rectThumb
= rect
;
2895 DrawArrowBorder(dc
, &rectThumb
);
2896 DrawBackground(dc
, wxNullColour
, rectThumb
);
2899 void wxWin32Renderer::DrawScrollbarShaft(wxDC
& dc
,
2900 wxOrientation orient
,
2901 const wxRect
& rectBar
,
2904 wxColourScheme::StdColour col
= flags
& wxCONTROL_PRESSED
2905 ? wxColourScheme::SCROLLBAR_PRESSED
2906 : wxColourScheme::SCROLLBAR
;
2907 DoDrawBackground(dc
, m_scheme
->Get(col
), rectBar
);
2910 void wxWin32Renderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
2912 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2915 wxRect
wxWin32Renderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
2916 wxScrollBar::Element elem
,
2919 return StandardGetScrollbarRect(scrollbar
, elem
,
2920 thumbPos
, m_sizeScrollbarArrow
);
2923 wxCoord
wxWin32Renderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
2925 return StandardScrollBarSize(scrollbar
, m_sizeScrollbarArrow
);
2928 wxHitTest
wxWin32Renderer::HitTestScrollbar(const wxScrollBar
*scrollbar
,
2929 const wxPoint
& pt
) const
2931 return StandardHitTestScrollbar(scrollbar
, pt
, m_sizeScrollbarArrow
);
2934 wxCoord
wxWin32Renderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
2937 return StandardScrollbarToPixel(scrollbar
, thumbPos
, m_sizeScrollbarArrow
);
2940 int wxWin32Renderer::PixelToScrollbar(const wxScrollBar
*scrollbar
,
2943 return StandardPixelToScrollbar(scrollbar
, coord
, m_sizeScrollbarArrow
);
2946 // ----------------------------------------------------------------------------
2947 // text control geometry
2948 // ----------------------------------------------------------------------------
2950 static inline int GetTextBorderWidth()
2955 wxRect
wxWin32Renderer::GetTextTotalArea(const wxTextCtrl
*text
,
2958 wxRect rectTotal
= rect
;
2960 wxCoord widthBorder
= GetTextBorderWidth();
2961 rectTotal
.Inflate(widthBorder
);
2963 // this is what Windows does
2969 wxRect
wxWin32Renderer::GetTextClientArea(const wxTextCtrl
*text
,
2971 wxCoord
*extraSpaceBeyond
)
2973 wxRect rectText
= rect
;
2975 // undo GetTextTotalArea()
2976 if ( rectText
.height
> 0 )
2979 wxCoord widthBorder
= GetTextBorderWidth();
2980 rectText
.Inflate(-widthBorder
);
2982 if ( extraSpaceBeyond
)
2983 *extraSpaceBeyond
= 0;
2988 // ----------------------------------------------------------------------------
2990 // ----------------------------------------------------------------------------
2992 void wxWin32Renderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
2995 if ( wxDynamicCast(window
, wxScrollBar
) )
2997 // we only set the width of vert scrollbars and height of the
2999 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
3000 size
->y
= m_sizeScrollbarArrow
.y
;
3002 size
->x
= m_sizeScrollbarArrow
.x
;
3004 // skip border width adjustments, they don't make sense for us
3007 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
3010 if ( wxDynamicCast(window
, wxButton
) )
3012 if ( !(window
->GetWindowStyle() & wxBU_EXACTFIT
) )
3014 // TODO: don't harcode all this
3015 size
->x
+= 3*window
->GetCharWidth();
3017 wxCoord heightBtn
= (11*(window
->GetCharHeight() + 8))/10;
3018 if ( size
->y
< heightBtn
- 8 )
3019 size
->y
= heightBtn
;
3024 // no border width adjustments for buttons
3027 #endif // wxUSE_BUTTON
3029 // take into account the border width
3030 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
3031 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
3032 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
3035 // ============================================================================
3037 // ============================================================================
3039 // ----------------------------------------------------------------------------
3040 // wxWin32InputHandler
3041 // ----------------------------------------------------------------------------
3043 wxWin32InputHandler::wxWin32InputHandler(wxWin32Renderer
*renderer
)
3045 m_renderer
= renderer
;
3048 bool wxWin32InputHandler::HandleKey(wxControl
*control
,
3049 const wxKeyEvent
& event
,
3055 bool wxWin32InputHandler::HandleMouse(wxControl
*control
,
3056 const wxMouseEvent
& event
)
3058 // clicking on the control gives it focus
3059 if ( event
.ButtonDown() && wxWindow::FindFocus() != control
)
3061 control
->SetFocus();
3069 // ----------------------------------------------------------------------------
3070 // wxWin32ScrollBarInputHandler
3071 // ----------------------------------------------------------------------------
3073 wxWin32ScrollBarInputHandler::
3074 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
3075 wxInputHandler
*handler
)
3076 : wxStdScrollBarInputHandler(renderer
, handler
)
3078 m_scrollPaused
= FALSE
;
3082 bool wxWin32ScrollBarInputHandler::OnScrollTimer(wxScrollBar
*scrollbar
,
3083 const wxControlAction
& action
)
3085 // stop if went beyond the position of the original click (this can only
3086 // happen when we scroll by pages)
3088 if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
3090 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3091 != wxHT_SCROLLBAR_BAR_2
;
3093 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
3095 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3096 != wxHT_SCROLLBAR_BAR_1
;
3101 StopScrolling(scrollbar
);
3103 scrollbar
->Refresh();
3108 return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar
, action
);
3111 bool wxWin32ScrollBarInputHandler::HandleMouse(wxControl
*control
,
3112 const wxMouseEvent
& event
)
3114 // remember the current state
3115 bool wasDraggingThumb
= m_htLast
== wxHT_SCROLLBAR_THUMB
;
3117 // do process the message
3118 bool rc
= wxStdScrollBarInputHandler::HandleMouse(control
, event
);
3120 // analyse the changes
3121 if ( !wasDraggingThumb
&& (m_htLast
== wxHT_SCROLLBAR_THUMB
) )
3123 // we just started dragging the thumb, remember its initial position to
3124 // be able to restore it if the drag is cancelled later
3125 m_eventStartDrag
= event
;
3131 bool wxWin32ScrollBarInputHandler::HandleMouseMove(wxControl
*control
,
3132 const wxMouseEvent
& event
)
3134 // we don't highlight scrollbar elements, so there is no need to process
3135 // mouse move events normally - only do it while mouse is captured (i.e.
3136 // when we're dragging the thumb or pressing on something)
3137 if ( !m_winCapture
)
3140 if ( event
.Entering() )
3142 // we're not interested in this at all
3146 wxScrollBar
*scrollbar
= wxStaticCast(control
, wxScrollBar
);
3148 if ( m_scrollPaused
)
3150 // check if the mouse returned to its original location
3152 if ( event
.Leaving() )
3158 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3159 if ( ht
== m_htLast
)
3161 // yes it did, resume scrolling
3162 m_scrollPaused
= FALSE
;
3163 if ( m_timerScroll
)
3165 // we were scrolling by line/page, restart timer
3166 m_timerScroll
->Start(m_interval
);
3168 Press(scrollbar
, TRUE
);
3170 else // we were dragging the thumb
3172 // restore its last location
3173 HandleThumbMove(scrollbar
, m_eventLastDrag
);
3179 else // normal case, scrolling hasn't been paused
3181 // if we're scrolling the scrollbar because the arrow or the shaft was
3182 // pressed, check that the mouse stays on the same scrollbar element
3184 if ( event
.Moving() )
3186 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3188 else // event.Leaving()
3193 // if we're dragging the thumb and the mouse stays in the scrollbar, it
3194 // is still ok - we only want to catch the case when the mouse leaves
3195 // the scrollbar here
3196 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
&& ht
!= wxHT_NOWHERE
)
3198 ht
= wxHT_SCROLLBAR_THUMB
;
3201 if ( ht
!= m_htLast
)
3203 // what were we doing? 2 possibilities: either an arrow/shaft was
3204 // pressed in which case we have a timer and so we just stop it or
3205 // we were dragging the thumb
3206 if ( m_timerScroll
)
3209 m_interval
= m_timerScroll
->GetInterval();
3210 m_timerScroll
->Stop();
3211 m_scrollPaused
= TRUE
;
3213 // unpress the arrow
3214 Press(scrollbar
, FALSE
);
3216 else // we were dragging the thumb
3218 // remember the current thumb position to be able to restore it
3219 // if the mouse returns to it later
3220 m_eventLastDrag
= event
;
3222 // and restore the original position (before dragging) of the
3224 HandleThumbMove(scrollbar
, m_eventStartDrag
);
3231 return wxStdScrollBarInputHandler::HandleMouseMove(control
, event
);
3234 // ----------------------------------------------------------------------------
3235 // wxWin32CheckboxInputHandler
3236 // ----------------------------------------------------------------------------
3238 bool wxWin32CheckboxInputHandler::HandleKey(wxControl
*control
,
3239 const wxKeyEvent
& event
,
3244 wxControlAction action
;
3245 int keycode
= event
.GetKeyCode();
3249 action
= wxACTION_CHECKBOX_TOGGLE
;
3253 case WXK_NUMPAD_SUBTRACT
:
3254 action
= wxACTION_CHECKBOX_CHECK
;
3258 case WXK_NUMPAD_ADD
:
3259 case WXK_NUMPAD_EQUAL
:
3260 action
= wxACTION_CHECKBOX_CLEAR
;
3266 control
->PerformAction(action
);
3275 // ----------------------------------------------------------------------------
3276 // wxWin32TextCtrlInputHandler
3277 // ----------------------------------------------------------------------------
3279 bool wxWin32TextCtrlInputHandler::HandleKey(wxControl
*control
,
3280 const wxKeyEvent
& event
,
3283 // handle only MSW-specific text bindings here, the others are handled in
3287 int keycode
= event
.GetKeyCode();
3289 wxControlAction action
;
3290 if ( keycode
== WXK_DELETE
&& event
.ShiftDown() )
3292 action
= wxACTION_TEXT_CUT
;
3294 else if ( keycode
== WXK_INSERT
)
3296 if ( event
.ControlDown() )
3297 action
= wxACTION_TEXT_COPY
;
3298 else if ( event
.ShiftDown() )
3299 action
= wxACTION_TEXT_PASTE
;
3302 if ( action
!= wxACTION_NONE
)
3304 control
->PerformAction(action
);
3310 return wxStdTextCtrlInputHandler::HandleKey(control
, event
, pressed
);