1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/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 licence
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/bmpbuttn.h"
37 #include "wx/listbox.h"
38 #include "wx/checklst.h"
39 #include "wx/combobox.h"
40 #include "wx/scrolbar.h"
41 #include "wx/slider.h"
42 #include "wx/textctrl.h"
43 #include "wx/toolbar.h"
44 #include "wx/statusbr.h"
47 // for COLOR_* constants
48 #include "wx/msw/private.h"
51 #include "wx/settings.h"
52 #include "wx/toplevel.h"
56 #include "wx/notebook.h"
57 #include "wx/spinbutt.h"
58 #include "wx/artprov.h"
59 #ifdef wxUSE_TOGGLEBTN
60 #include "wx/tglbtn.h"
61 #endif // wxUSE_TOGGLEBTN
63 #include "wx/univ/scrtimer.h"
64 #include "wx/univ/stdrend.h"
65 #include "wx/univ/inpcons.h"
66 #include "wx/univ/inphand.h"
67 #include "wx/univ/colschem.h"
68 #include "wx/univ/theme.h"
70 // ----------------------------------------------------------------------------
72 // ----------------------------------------------------------------------------
74 static const int BORDER_THICKNESS
= 2;
76 // the offset between the label and focus rect around it
77 static const int FOCUS_RECT_OFFSET_X
= 1;
78 static const int FOCUS_RECT_OFFSET_Y
= 1;
80 static const int FRAME_BORDER_THICKNESS
= 3;
81 static const int RESIZEABLE_FRAME_BORDER_THICKNESS
= 4;
82 static const int FRAME_TITLEBAR_HEIGHT
= 18;
83 static const int FRAME_BUTTON_WIDTH
= 16;
84 static const int FRAME_BUTTON_HEIGHT
= 14;
86 static const size_t NUM_STATUSBAR_GRIP_BANDS
= 3;
87 static const size_t WIDTH_STATUSBAR_GRIP_BAND
= 4;
88 static const size_t STATUSBAR_GRIP_SIZE
=
89 WIDTH_STATUSBAR_GRIP_BAND
*NUM_STATUSBAR_GRIP_BANDS
;
91 static const wxCoord SLIDER_MARGIN
= 6; // margin around slider
92 static const wxCoord SLIDER_THUMB_LENGTH
= 18;
93 static const wxCoord SLIDER_TICK_LENGTH
= 6;
95 // wxWin32Renderer: draw the GUI elements in Win32 style
96 // ----------------------------------------------------------------------------
98 class wxWin32Renderer
: public wxStdRenderer
101 enum wxFrameButtonType
104 FrameButton_Minimize
,
105 FrameButton_Maximize
,
112 wxWin32Renderer(const wxColourScheme
*scheme
);
114 // reimplement the renderer methods which are different for this theme
115 virtual void DrawLabel(wxDC
& dc
,
116 const wxString
& label
,
119 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
121 wxRect
*rectBounds
= NULL
);
122 virtual void DrawButtonLabel(wxDC
& dc
,
123 const wxString
& label
,
124 const wxBitmap
& image
,
127 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
129 wxRect
*rectBounds
= NULL
);
130 virtual void DrawButtonBorder(wxDC
& dc
,
133 wxRect
*rectIn
= NULL
);
135 virtual void DrawArrow(wxDC
& dc
,
139 virtual void DrawScrollbarThumb(wxDC
& dc
,
140 wxOrientation orient
,
143 virtual void DrawScrollbarShaft(wxDC
& dc
,
144 wxOrientation orient
,
149 virtual void DrawToolBarButton(wxDC
& dc
,
150 const wxString
& label
,
151 const wxBitmap
& bitmap
,
156 #endif // wxUSE_TOOLBAR
159 virtual void DrawTab(wxDC
& dc
,
162 const wxString
& label
,
163 const wxBitmap
& bitmap
= wxNullBitmap
,
165 int indexAccel
= -1);
166 #endif // wxUSE_NOTEBOOK
169 virtual void DrawSliderShaft(wxDC
& dc
,
172 wxOrientation orient
,
175 wxRect
*rectShaft
= NULL
);
176 virtual void DrawSliderThumb(wxDC
& dc
,
178 wxOrientation orient
,
181 virtual void DrawSliderTicks(wxDC
& dc
,
184 wxOrientation orient
,
190 #endif // wxUSE_SLIDER
193 virtual void DrawMenuBarItem(wxDC
& dc
,
195 const wxString
& label
,
197 int indexAccel
= -1);
198 virtual void DrawMenuItem(wxDC
& dc
,
200 const wxMenuGeometryInfo
& geometryInfo
,
201 const wxString
& label
,
202 const wxString
& accel
,
203 const wxBitmap
& bitmap
= wxNullBitmap
,
205 int indexAccel
= -1);
206 virtual void DrawMenuSeparator(wxDC
& dc
,
208 const wxMenuGeometryInfo
& geomInfo
);
209 #endif // wxUSE_MENUS
212 virtual void DrawStatusField(wxDC
& dc
,
214 const wxString
& label
,
215 int flags
= 0, int style
= 0);
216 #endif // wxUSE_STATUSBAR
219 virtual void DrawFrameTitleBar(wxDC
& dc
,
221 const wxString
& title
,
224 int specialButton
= 0,
225 int specialButtonFlags
= 0);
226 virtual void DrawFrameBorder(wxDC
& dc
,
229 virtual void DrawFrameBackground(wxDC
& dc
,
232 virtual void DrawFrameTitle(wxDC
& dc
,
234 const wxString
& title
,
236 virtual void DrawFrameIcon(wxDC
& dc
,
240 virtual void DrawFrameButton(wxDC
& dc
,
241 wxCoord x
, wxCoord y
,
244 virtual wxRect
GetFrameClientArea(const wxRect
& rect
, int flags
) const;
245 virtual wxSize
GetFrameTotalSize(const wxSize
& clientSize
, int flags
) const;
246 virtual wxSize
GetFrameMinSize(int flags
) const;
247 virtual wxSize
GetFrameIconSize() const;
248 virtual int HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const;
250 virtual void GetComboBitmaps(wxBitmap
*bmpNormal
,
252 wxBitmap
*bmpPressed
,
253 wxBitmap
*bmpDisabled
);
255 virtual void AdjustSize(wxSize
*size
, const wxWindow
*window
);
256 virtual bool AreScrollbarsInsideBorder() const;
258 virtual wxSize
GetScrollbarArrowSize() const
259 { return m_sizeScrollbarArrow
; }
261 virtual wxSize
GetCheckBitmapSize() const
262 { return wxSize(13, 13); }
263 virtual wxSize
GetRadioBitmapSize() const
264 { return wxSize(12, 12); }
265 virtual wxCoord
GetCheckItemMargin() const
268 virtual wxSize
GetToolBarButtonSize(wxCoord
*separator
) const
269 { if ( separator
) *separator
= 5; return wxSize(16, 15); }
270 virtual wxSize
GetToolBarMargin() const
271 { return wxSize(4, 4); }
274 virtual wxRect
GetTextTotalArea(const wxTextCtrl
*text
,
275 const wxRect
& rect
) const;
276 virtual wxRect
GetTextClientArea(const wxTextCtrl
*text
,
278 wxCoord
*extraSpaceBeyond
) const;
279 #endif // wxUSE_TEXTCTRL
282 virtual wxSize
GetTabIndent() const { return wxSize(2, 2); }
283 virtual wxSize
GetTabPadding() const { return wxSize(6, 5); }
284 #endif // wxUSE_NOTEBOOK
288 virtual wxCoord
GetSliderDim() const { return SLIDER_THUMB_LENGTH
+ 2*BORDER_THICKNESS
; }
289 virtual wxCoord
GetSliderTickLen() const { return SLIDER_TICK_LENGTH
; }
290 virtual wxRect
GetSliderShaftRect(const wxRect
& rect
,
292 wxOrientation orient
,
293 long style
= 0) const;
294 virtual wxSize
GetSliderThumbSize(const wxRect
& rect
,
296 wxOrientation orient
) const;
297 #endif // wxUSE_SLIDER
299 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;
305 #endif // wxUSE_MENUS
308 // overridden wxStdRenderer methods
309 virtual void DrawFrameWithLabel(wxDC
& dc
,
310 const wxString
& label
,
311 const wxRect
& rectFrame
,
312 const wxRect
& rectText
,
317 virtual void DrawCheckItemBitmap(wxDC
& dc
,
318 const wxBitmap
& bitmap
,
323 // draw the border used for scrollbar arrows
324 void DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
= false);
326 // public DrawArrow()s helper
327 void DrawArrow(wxDC
& dc
, const wxRect
& rect
,
328 ArrowDirection arrowDir
, ArrowStyle arrowStyle
);
330 // DrawArrowButton is used by DrawScrollbar and DrawComboButton
331 void DrawArrowButton(wxDC
& dc
, const wxRect
& rect
,
332 ArrowDirection arrowDir
,
333 ArrowStyle arrowStyle
);
335 // draw a normal or transposed line (useful for using the same code fo both
336 // horizontal and vertical widgets)
337 void DrawLine(wxDC
& dc
,
338 wxCoord x1
, wxCoord y1
,
339 wxCoord x2
, wxCoord y2
,
340 bool transpose
= false)
343 dc
.DrawLine(y1
, x1
, y2
, x2
);
345 dc
.DrawLine(x1
, y1
, x2
, y2
);
348 // get the standard check/radio button bitmap
349 wxBitmap
GetIndicator(IndicatorType indType
, int flags
);
350 virtual wxBitmap
GetCheckBitmap(int flags
)
351 { return GetIndicator(IndicatorType_Check
, flags
); }
352 virtual wxBitmap
GetRadioBitmap(int flags
)
353 { return GetIndicator(IndicatorType_Radio
, flags
); }
356 // the sizing parameters (TODO make them changeable)
357 wxSize m_sizeScrollbarArrow
;
359 wxFont m_titlebarFont
;
361 // the checked and unchecked bitmaps for DrawCheckItemBitmap()
362 wxBitmap m_bmpCheckBitmaps
[IndicatorStatus_Max
];
364 // the bitmaps returned by GetIndicator()
365 wxBitmap m_bmpIndicators
[IndicatorType_Max
]
366 [IndicatorState_MaxMenu
]
367 [IndicatorStatus_Max
];
369 // standard defaults for m_bmpCheckBitmaps and m_bmpIndicators
370 static const char **ms_xpmChecked
[IndicatorStatus_Max
];
371 static const char **ms_xpmIndicators
[IndicatorType_Max
]
372 [IndicatorState_MaxMenu
]
373 [IndicatorStatus_Max
];
376 wxBitmap m_bmpFrameButtons
[FrameButton_Max
];
378 // first row is for the normal state, second - for the disabled
379 wxBitmap m_bmpArrows
[Arrow_StateMax
][Arrow_Max
];
382 // ----------------------------------------------------------------------------
383 // wxWin32InputHandler and derived classes: process the keyboard and mouse
384 // messages according to Windows standards
385 // ----------------------------------------------------------------------------
387 class wxWin32InputHandler
: public wxInputHandler
390 wxWin32InputHandler() { }
392 virtual bool HandleKey(wxInputConsumer
*control
,
393 const wxKeyEvent
& event
,
395 virtual bool HandleMouse(wxInputConsumer
*control
,
396 const wxMouseEvent
& event
);
400 class wxWin32ScrollBarInputHandler
: public wxStdScrollBarInputHandler
403 wxWin32ScrollBarInputHandler(wxRenderer
*renderer
,
404 wxInputHandler
*handler
);
406 virtual bool HandleMouse(wxInputConsumer
*control
,
407 const wxMouseEvent
& event
);
408 virtual bool HandleMouseMove(wxInputConsumer
*control
,
409 const wxMouseEvent
& event
);
411 virtual bool OnScrollTimer(wxScrollBar
*scrollbar
,
412 const wxControlAction
& action
);
415 virtual void Highlight(wxScrollBar
* WXUNUSED(scrollbar
),
418 // we don't highlight anything
421 // the first and last event which caused the thumb to move
422 wxMouseEvent m_eventStartDrag
,
425 // have we paused the scrolling because the mouse moved?
428 // we remember the interval of the timer to be able to restart it
431 #endif // wxUSE_SCROLLBAR
434 class wxWin32CheckboxInputHandler
: public wxStdInputHandler
437 wxWin32CheckboxInputHandler(wxInputHandler
*handler
)
438 : wxStdInputHandler(handler
) { }
440 virtual bool HandleKey(wxInputConsumer
*control
,
441 const wxKeyEvent
& event
,
444 #endif // wxUSE_CHECKBOX
447 class wxWin32TextCtrlInputHandler
: public wxStdInputHandler
450 wxWin32TextCtrlInputHandler(wxInputHandler
*handler
)
451 : wxStdInputHandler(handler
) { }
453 virtual bool HandleKey(wxInputConsumer
*control
,
454 const wxKeyEvent
& event
,
457 #endif // wxUSE_TEXTCTRL
459 class wxWin32StatusBarInputHandler
: public wxStdInputHandler
462 wxWin32StatusBarInputHandler(wxInputHandler
*handler
);
464 virtual bool HandleMouse(wxInputConsumer
*consumer
,
465 const wxMouseEvent
& event
);
467 virtual bool HandleMouseMove(wxInputConsumer
*consumer
,
468 const wxMouseEvent
& event
);
471 // is the given point over the statusbar grip?
472 bool IsOnGrip(wxWindow
*statbar
, const wxPoint
& pt
) const;
475 // the cursor we had replaced with the resize one
476 wxCursor m_cursorOld
;
478 // was the mouse over the grip last time we checked?
482 class wxWin32SystemMenuEvtHandler
;
484 class wxWin32FrameInputHandler
: public wxStdInputHandler
487 wxWin32FrameInputHandler(wxInputHandler
*handler
);
488 virtual ~wxWin32FrameInputHandler();
490 virtual bool HandleMouse(wxInputConsumer
*control
,
491 const wxMouseEvent
& event
);
493 virtual bool HandleActivation(wxInputConsumer
*consumer
, bool activated
);
496 void PopupSystemMenu(wxTopLevelWindow
*window
, const wxPoint
& pos
) const;
497 #endif // wxUSE_MENUS
500 // was the mouse over the grip last time we checked?
501 wxWin32SystemMenuEvtHandler
*m_menuHandler
;
504 // ----------------------------------------------------------------------------
505 // wxWin32ColourScheme: uses (default) Win32 colours
506 // ----------------------------------------------------------------------------
508 class wxWin32ColourScheme
: public wxColourScheme
511 virtual wxColour
Get(StdColour col
) const;
512 virtual wxColour
GetBackground(wxWindow
*win
) const;
515 // ----------------------------------------------------------------------------
516 // wxWin32ArtProvider
517 // ----------------------------------------------------------------------------
519 class wxWin32ArtProvider
: public wxArtProvider
522 virtual wxBitmap
CreateBitmap(const wxArtID
& id
,
523 const wxArtClient
& client
,
527 // ----------------------------------------------------------------------------
529 // ----------------------------------------------------------------------------
531 WX_DEFINE_ARRAY_PTR(wxInputHandler
*, wxArrayHandlers
);
533 class wxWin32Theme
: public wxTheme
537 virtual ~wxWin32Theme();
539 virtual wxRenderer
*GetRenderer();
540 virtual wxArtProvider
*GetArtProvider();
541 virtual wxInputHandler
*GetInputHandler(const wxString
& control
,
542 wxInputConsumer
*consumer
);
543 virtual wxColourScheme
*GetColourScheme();
546 wxWin32Renderer
*m_renderer
;
548 wxWin32ArtProvider
*m_artProvider
;
550 // the names of the already created handlers and the handlers themselves
551 // (these arrays are synchronized)
552 wxSortedArrayString m_handlerNames
;
553 wxArrayHandlers m_handlers
;
555 wxWin32ColourScheme
*m_scheme
;
557 WX_DECLARE_THEME(win32
)
560 // ----------------------------------------------------------------------------
562 // ----------------------------------------------------------------------------
564 // frame buttons bitmaps
566 static const char *frame_button_close_xpm
[] = {
581 static const char *frame_button_help_xpm
[] = {
596 static const char *frame_button_maximize_xpm
[] = {
611 static const char *frame_button_minimize_xpm
[] = {
626 static const char *frame_button_restore_xpm
[] = {
643 static const char *checked_menu_xpm
[] = {
644 /* columns rows colors chars-per-pixel */
660 static const char *selected_checked_menu_xpm
[] = {
661 /* columns rows colors chars-per-pixel */
677 static const char *disabled_checked_menu_xpm
[] = {
678 /* columns rows colors chars-per-pixel */
695 static const char *selected_disabled_checked_menu_xpm
[] = {
696 /* columns rows colors chars-per-pixel */
712 // checkbox and radiobox bitmaps below
714 static const char *checked_xpm
[] = {
715 /* columns rows colors chars-per-pixel */
738 static const char *pressed_checked_xpm
[] = {
739 /* columns rows colors chars-per-pixel */
761 static const char *pressed_disabled_checked_xpm
[] = {
762 /* columns rows colors chars-per-pixel */
784 static const char *checked_item_xpm
[] = {
785 /* columns rows colors chars-per-pixel */
806 static const char *unchecked_xpm
[] = {
807 /* columns rows colors chars-per-pixel */
830 static const char *pressed_unchecked_xpm
[] = {
831 /* columns rows colors chars-per-pixel */
853 static const char *unchecked_item_xpm
[] = {
854 /* columns rows colors chars-per-pixel */
874 static const char *undetermined_xpm
[] = {
875 /* columns rows colors chars-per-pixel */
898 static const char *pressed_undetermined_xpm
[] = {
899 /* columns rows colors chars-per-pixel */
922 static const char *checked_radio_xpm
[] = {
923 /* columns rows colors chars-per-pixel */
946 static const char *pressed_checked_radio_xpm
[] = {
947 /* columns rows colors chars-per-pixel */
970 static const char *pressed_disabled_checked_radio_xpm
[] = {
971 /* columns rows colors chars-per-pixel */
994 static const char *unchecked_radio_xpm
[] = {
995 /* columns rows colors chars-per-pixel */
1018 static const char *pressed_unchecked_radio_xpm
[] = {
1019 /* columns rows colors chars-per-pixel */
1042 const char **wxWin32Renderer
::ms_xpmIndicators
[IndicatorType_Max
]
1043 [IndicatorState_MaxMenu
]
1044 [IndicatorStatus_Max
] =
1049 { checked_xpm
, unchecked_xpm
, undetermined_xpm
},
1052 { pressed_checked_xpm
, pressed_unchecked_xpm
, pressed_undetermined_xpm
},
1055 { pressed_disabled_checked_xpm
, pressed_unchecked_xpm
, pressed_disabled_checked_xpm
},
1061 { checked_radio_xpm
, unchecked_radio_xpm
, NULL
},
1064 { pressed_checked_radio_xpm
, pressed_unchecked_radio_xpm
, NULL
},
1067 { pressed_disabled_checked_radio_xpm
, pressed_unchecked_radio_xpm
, NULL
},
1073 { checked_menu_xpm
, NULL
, NULL
},
1076 { selected_checked_menu_xpm
, NULL
, NULL
},
1079 { disabled_checked_menu_xpm
, NULL
, NULL
},
1081 // disabled selected state
1082 { selected_disabled_checked_menu_xpm
, NULL
, NULL
},
1086 const char **wxWin32Renderer
::ms_xpmChecked
[IndicatorStatus_Max
] =
1092 // ============================================================================
1094 // ============================================================================
1096 WX_IMPLEMENT_THEME(wxWin32Theme
, win32
, wxTRANSLATE("Win32 theme"));
1098 // ----------------------------------------------------------------------------
1100 // ----------------------------------------------------------------------------
1102 wxWin32Theme
::wxWin32Theme()
1106 m_artProvider
= NULL
;
1109 wxWin32Theme
::~wxWin32Theme()
1113 wxArtProvider
::RemoveProvider(m_artProvider
);
1116 wxRenderer
*wxWin32Theme
::GetRenderer()
1120 m_renderer
= new wxWin32Renderer(GetColourScheme());
1126 wxArtProvider
*wxWin32Theme
::GetArtProvider()
1128 if ( !m_artProvider
)
1130 m_artProvider
= new wxWin32ArtProvider
;
1133 return m_artProvider
;
1137 wxWin32Theme
::GetInputHandler(const wxString
& control
,
1138 wxInputConsumer
*consumer
)
1140 wxInputHandler
*handler
= NULL
;
1141 int n
= m_handlerNames
.Index(control
);
1142 if ( n
== wxNOT_FOUND
)
1144 static wxWin32InputHandler s_handlerDef
;
1146 wxInputHandler
* const
1147 handlerStd
= consumer
->DoGetStdInputHandler(&s_handlerDef
);
1149 // create a new handler
1150 if ( control
== wxINP_HANDLER_TOPLEVEL
)
1152 static wxWin32FrameInputHandler
s_handler(handlerStd
);
1154 handler
= &s_handler
;
1157 else if ( control
== wxINP_HANDLER_CHECKBOX
)
1159 static wxWin32CheckboxInputHandler
s_handler(handlerStd
);
1161 handler
= &s_handler
;
1163 #endif // wxUSE_CHECKBOX
1165 else if ( control
== wxINP_HANDLER_SCROLLBAR
)
1167 static wxWin32ScrollBarInputHandler
1168 s_handler(GetRenderer(), handlerStd
);
1170 handler
= &s_handler
;
1172 #endif // wxUSE_SCROLLBAR
1174 else if ( control
== wxINP_HANDLER_STATUSBAR
)
1176 static wxWin32StatusBarInputHandler
s_handler(handlerStd
);
1178 handler
= &s_handler
;
1180 #endif // wxUSE_STATUSBAR
1182 else if ( control
== wxINP_HANDLER_TEXTCTRL
)
1184 static wxWin32TextCtrlInputHandler
s_handler(handlerStd
);
1186 handler
= &s_handler
;
1188 #endif // wxUSE_TEXTCTRL
1189 else // no special handler for this control
1191 handler
= handlerStd
;
1194 n
= m_handlerNames
.Add(control
);
1195 m_handlers
.Insert(handler
, n
);
1197 else // we already have it
1199 handler
= m_handlers
[n
];
1205 wxColourScheme
*wxWin32Theme
::GetColourScheme()
1209 m_scheme
= new wxWin32ColourScheme
;
1214 // ============================================================================
1215 // wxWin32ColourScheme
1216 // ============================================================================
1218 wxColour wxWin32ColourScheme
::GetBackground(wxWindow
*win
) const
1221 if ( win
->UseBgCol() )
1223 // use the user specified colour
1224 col
= win
->GetBackgroundColour();
1227 if ( !win
->ShouldInheritColours() )
1230 wxTextCtrl
*text
= wxDynamicCast(win
, wxTextCtrl
);
1231 #endif // wxUSE_TEXTCTRL
1233 wxListBox
* listBox
= wxDynamicCast(win
, wxListBox
);
1234 #endif // wxUSE_LISTBOX
1243 if ( !win
->IsEnabled() ) // not IsEditable()
1249 // doesn't depend on the state
1254 #endif // wxUSE_TEXTCTRL
1257 col
= Get(CONTROL
); // Most controls should be this colour, not WINDOW
1261 int flags
= win
->GetStateFlags();
1263 // the colour set by the user should be used for the normal state
1264 // and for the states for which we don't have any specific colours
1265 if ( !col
.Ok() || (flags
& wxCONTROL_PRESSED
) != 0 )
1268 if ( wxDynamicCast(win
, wxScrollBar
) )
1269 col
= Get(flags
& wxCONTROL_PRESSED ? SCROLLBAR_PRESSED
1272 #endif // wxUSE_SCROLLBAR
1280 wxColour wxWin32ColourScheme
::Get(wxWin32ColourScheme
::StdColour col
) const
1284 // use the system colours under Windows
1285 #if defined(__WXMSW__)
1286 case WINDOW
: return wxColour(GetSysColor(COLOR_WINDOW
));
1288 case CONTROL_PRESSED
:
1289 case CONTROL_CURRENT
:
1290 case CONTROL
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1292 case CONTROL_TEXT
: return wxColour(GetSysColor(COLOR_BTNTEXT
));
1294 #if defined(COLOR_3DLIGHT)
1295 case SCROLLBAR
: return wxColour(GetSysColor(COLOR_3DLIGHT
));
1297 case SCROLLBAR
: return wxColour(0xe0e0e0);
1299 case SCROLLBAR_PRESSED
: return wxColour(GetSysColor(COLOR_BTNTEXT
));
1301 case HIGHLIGHT
: return wxColour(GetSysColor(COLOR_HIGHLIGHT
));
1302 case HIGHLIGHT_TEXT
: return wxColour(GetSysColor(COLOR_HIGHLIGHTTEXT
));
1304 #if defined(COLOR_3DDKSHADOW)
1305 case SHADOW_DARK
: return wxColour(GetSysColor(COLOR_3DDKSHADOW
));
1307 case SHADOW_DARK
: return wxColour(GetSysColor(COLOR_3DHADOW
));
1310 case CONTROL_TEXT_DISABLED
:
1311 case SHADOW_HIGHLIGHT
: return wxColour(GetSysColor(COLOR_BTNHIGHLIGHT
));
1313 case SHADOW_IN
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1315 case CONTROL_TEXT_DISABLED_SHADOW
:
1316 case SHADOW_OUT
: return wxColour(GetSysColor(COLOR_BTNSHADOW
));
1318 case TITLEBAR
: return wxColour(GetSysColor(COLOR_INACTIVECAPTION
));
1319 case TITLEBAR_ACTIVE
: return wxColour(GetSysColor(COLOR_ACTIVECAPTION
));
1320 case TITLEBAR_TEXT
: return wxColour(GetSysColor(COLOR_INACTIVECAPTIONTEXT
));
1321 case TITLEBAR_ACTIVE_TEXT
: return wxColour(GetSysColor(COLOR_CAPTIONTEXT
));
1323 case DESKTOP
: return wxColour(0x808000);
1325 // use the standard Windows colours elsewhere
1326 case WINDOW
: return *wxWHITE
;
1328 case CONTROL_PRESSED
:
1329 case CONTROL_CURRENT
:
1330 case CONTROL
: return wxColour(0xc0c0c0);
1332 case CONTROL_TEXT
: return *wxBLACK
;
1334 case SCROLLBAR
: return wxColour(0xe0e0e0);
1335 case SCROLLBAR_PRESSED
: return *wxBLACK
;
1337 case HIGHLIGHT
: return wxColour(0x800000);
1338 case HIGHLIGHT_TEXT
: return wxColour(0xffffff);
1340 case SHADOW_DARK
: return *wxBLACK
;
1342 case CONTROL_TEXT_DISABLED
:return wxColour(0xe0e0e0);
1343 case SHADOW_HIGHLIGHT
: return wxColour(0xffffff);
1345 case SHADOW_IN
: return wxColour(0xc0c0c0);
1347 case CONTROL_TEXT_DISABLED_SHADOW
:
1348 case SHADOW_OUT
: return wxColour(0x7f7f7f);
1350 case TITLEBAR
: return wxColour(0xaeaaae);
1351 case TITLEBAR_ACTIVE
: return wxColour(0x820300);
1352 case TITLEBAR_TEXT
: return wxColour(0xc0c0c0);
1353 case TITLEBAR_ACTIVE_TEXT
:return *wxWHITE
;
1355 case DESKTOP
: return wxColour(0x808000);
1358 case GAUGE
: return Get(HIGHLIGHT
);
1362 wxFAIL_MSG(_T("invalid standard colour"));
1367 // ============================================================================
1369 // ============================================================================
1371 // ----------------------------------------------------------------------------
1373 // ----------------------------------------------------------------------------
1375 wxWin32Renderer
::wxWin32Renderer(const wxColourScheme
*scheme
)
1376 : wxStdRenderer(scheme
)
1379 m_sizeScrollbarArrow
= wxSize(16, 16);
1381 m_titlebarFont
= wxSystemSettings
::GetFont(wxSYS_DEFAULT_GUI_FONT
);
1382 m_titlebarFont
.SetWeight(wxFONTWEIGHT_BOLD
);
1384 // init the arrow bitmaps
1385 static const size_t ARROW_WIDTH
= 7;
1386 static const size_t ARROW_LENGTH
= 4;
1389 wxMemoryDC dcNormal
,
1392 for ( size_t n
= 0; n
< Arrow_Max
; n
++ )
1394 bool isVertical
= n
> Arrow_Right
;
1407 // disabled arrow is larger because of the shadow
1408 m_bmpArrows
[Arrow_Normal
][n
].Create(w
, h
);
1409 m_bmpArrows
[Arrow_Disabled
][n
].Create(w
+ 1, h
+ 1);
1411 dcNormal
.SelectObject(m_bmpArrows
[Arrow_Normal
][n
]);
1412 dcDisabled
.SelectObject(m_bmpArrows
[Arrow_Disabled
][n
]);
1414 dcNormal
.SetBackground(*wxWHITE_BRUSH
);
1415 dcDisabled
.SetBackground(*wxWHITE_BRUSH
);
1419 dcNormal
.SetPen(m_penBlack
);
1420 dcDisabled
.SetPen(m_penDarkGrey
);
1422 // calculate the position of the point of the arrow
1426 x1
= (ARROW_WIDTH
- 1)/2;
1427 y1
= n
== Arrow_Up ?
0 : ARROW_LENGTH
- 1;
1431 x1
= n
== Arrow_Left ?
0 : ARROW_LENGTH
- 1;
1432 y1
= (ARROW_WIDTH
- 1)/2;
1443 for ( size_t i
= 0; i
< ARROW_LENGTH
; i
++ )
1445 dcNormal
.DrawLine(x1
, y1
, x2
, y2
);
1446 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1453 if ( n
== Arrow_Up
)
1464 else // left or right arrow
1469 if ( n
== Arrow_Left
)
1482 // draw the shadow for the disabled one
1483 dcDisabled
.SetPen(m_penHighlight
);
1488 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1492 x1
= ARROW_LENGTH
- 1;
1493 y1
= (ARROW_WIDTH
- 1)/2 + 1;
1496 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1497 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1502 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1506 x1
= ARROW_WIDTH
- 1;
1508 x2
= (ARROW_WIDTH
- 1)/2;
1510 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1511 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1516 // create the inverted bitmap but only for the right arrow as we only
1517 // use it for the menus
1518 if ( n
== Arrow_Right
)
1520 m_bmpArrows
[Arrow_Inverted
][n
].Create(w
, h
);
1521 dcInverse
.SelectObject(m_bmpArrows
[Arrow_Inverted
][n
]);
1523 dcInverse
.Blit(0, 0, w
, h
,
1526 dcInverse
.SelectObject(wxNullBitmap
);
1528 mask
= new wxMask(m_bmpArrows
[Arrow_Inverted
][n
], *wxBLACK
);
1529 m_bmpArrows
[Arrow_Inverted
][n
].SetMask(mask
);
1531 m_bmpArrows
[Arrow_InvertedDisabled
][n
].Create(w
, h
);
1532 dcInverse
.SelectObject(m_bmpArrows
[Arrow_InvertedDisabled
][n
]);
1534 dcInverse
.Blit(0, 0, w
, h
,
1537 dcInverse
.SelectObject(wxNullBitmap
);
1539 mask
= new wxMask(m_bmpArrows
[Arrow_InvertedDisabled
][n
], *wxBLACK
);
1540 m_bmpArrows
[Arrow_InvertedDisabled
][n
].SetMask(mask
);
1543 dcNormal
.SelectObject(wxNullBitmap
);
1544 dcDisabled
.SelectObject(wxNullBitmap
);
1546 mask
= new wxMask(m_bmpArrows
[Arrow_Normal
][n
], *wxWHITE
);
1547 m_bmpArrows
[Arrow_Normal
][n
].SetMask(mask
);
1548 mask
= new wxMask(m_bmpArrows
[Arrow_Disabled
][n
], *wxWHITE
);
1549 m_bmpArrows
[Arrow_Disabled
][n
].SetMask(mask
);
1551 m_bmpArrows
[Arrow_Pressed
][n
] = m_bmpArrows
[Arrow_Normal
][n
];
1554 // init the frame buttons bitmaps
1555 m_bmpFrameButtons
[FrameButton_Close
] = wxBitmap(frame_button_close_xpm
);
1556 m_bmpFrameButtons
[FrameButton_Minimize
] = wxBitmap(frame_button_minimize_xpm
);
1557 m_bmpFrameButtons
[FrameButton_Maximize
] = wxBitmap(frame_button_maximize_xpm
);
1558 m_bmpFrameButtons
[FrameButton_Restore
] = wxBitmap(frame_button_restore_xpm
);
1559 m_bmpFrameButtons
[FrameButton_Help
] = wxBitmap(frame_button_help_xpm
);
1562 bool wxWin32Renderer
::AreScrollbarsInsideBorder() const
1567 // ----------------------------------------------------------------------------
1569 // ----------------------------------------------------------------------------
1571 void wxWin32Renderer
::DrawLabel(wxDC
& dc
,
1572 const wxString
& label
,
1579 // the underscores are not drawn for focused controls in wxMSW
1580 if ( flags
& wxCONTROL_FOCUSED
)
1585 if ( flags
& wxCONTROL_DISABLED
)
1587 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
1588 // currently only can happen for a menu item and it seems that Windows
1589 // doesn't draw the shadow in this case, so we don't do it neither
1590 if ( flags
& wxCONTROL_SELECTED
)
1592 // just make the label text greyed out
1593 dc
.SetTextForeground(m_penDarkGrey
.GetColour());
1595 flags
&= ~wxCONTROL_DISABLED
;
1599 wxStdRenderer
::DrawLabel(dc
, label
, rect
, flags
, alignment
,
1600 indexAccel
, rectBounds
);
1603 void wxWin32Renderer
::DrawFrameWithLabel(wxDC
& dc
,
1604 const wxString
& label
,
1605 const wxRect
& rectFrame
,
1606 const wxRect
& rectText
,
1612 label2
<< _T(' ') << label
<< _T(' ');
1613 if ( indexAccel
!= -1 )
1615 // adjust it as we prepended a space
1619 wxStdRenderer
::DrawFrameWithLabel(dc
, label2
, rectFrame
, rectText
,
1620 flags
, alignment
, indexAccel
);
1623 void wxWin32Renderer
::DrawButtonLabel(wxDC
& dc
,
1624 const wxString
& label
,
1625 const wxBitmap
& image
,
1632 // the underscores are not drawn for focused controls in wxMSW
1633 if ( flags
& wxCONTROL_PRESSED
)
1638 wxStdRenderer
::DrawButtonLabel(dc
, label
, image
, rect
, flags
, alignment
,
1639 indexAccel
, rectBounds
);
1642 void wxWin32Renderer
::DrawButtonBorder(wxDC
& dc
,
1643 const wxRect
& rectTotal
,
1647 wxRect rect
= rectTotal
;
1649 wxPen
penOut(*wxBLACK
);
1650 if ( flags
& wxCONTROL_PRESSED
)
1652 // button pressed: draw a double border around it
1653 DrawRect(dc
, &rect
, penOut
);
1654 DrawRect(dc
, &rect
, m_penDarkGrey
);
1656 else // button not pressed
1658 if ( flags
& (wxCONTROL_FOCUSED
| wxCONTROL_ISDEFAULT
) )
1660 // button either default or focused (or both): add an extra border
1662 DrawRect(dc
, &rect
, penOut
);
1665 // now draw a normal button border
1666 DrawRaisedBorder(dc
, &rect
);
1673 // ----------------------------------------------------------------------------
1674 // (check)listbox items
1675 // ----------------------------------------------------------------------------
1677 void wxWin32Renderer
::DrawCheckItemBitmap(wxDC
& dc
,
1678 const wxBitmap
& bitmap
,
1687 else // use default bitmap
1689 IndicatorStatus i
= flags
& wxCONTROL_CHECKED
1690 ? IndicatorStatus_Checked
1691 : IndicatorStatus_Unchecked
;
1693 if ( !m_bmpCheckBitmaps
[i
].Ok() )
1695 m_bmpCheckBitmaps
[i
] = wxBitmap(ms_xpmChecked
[i
]);
1698 bmp
= m_bmpCheckBitmaps
[i
];
1701 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2 - 1,
1702 true /* use mask */);
1705 // ----------------------------------------------------------------------------
1706 // check/radio buttons
1707 // ----------------------------------------------------------------------------
1709 wxBitmap wxWin32Renderer
::GetIndicator(IndicatorType indType
, int flags
)
1711 IndicatorState indState
;
1712 IndicatorStatus indStatus
;
1713 GetIndicatorsFromFlags(flags
, indState
, indStatus
);
1715 wxBitmap
& bmp
= m_bmpIndicators
[indType
][indState
][indStatus
];
1718 const char **xpm
= ms_xpmIndicators
[indType
][indState
][indStatus
];
1721 // create and cache it
1722 bmp
= wxBitmap(xpm
);
1729 // ----------------------------------------------------------------------------
1731 // ----------------------------------------------------------------------------
1734 void wxWin32Renderer
::DrawToolBarButton(wxDC
& dc
,
1735 const wxString
& label
,
1736 const wxBitmap
& bitmap
,
1737 const wxRect
& rectOrig
,
1742 if (style
== wxTOOL_STYLE_BUTTON
)
1744 wxRect rect
= rectOrig
;
1745 rect
.Deflate(BORDER_THICKNESS
);
1747 if ( flags
& wxCONTROL_PRESSED
)
1749 DrawBorder(dc
, wxBORDER_SUNKEN
, rect
, flags
);
1751 else if ( flags
& wxCONTROL_CURRENT
)
1753 DrawBorder(dc
, wxBORDER_RAISED
, rect
, flags
);
1756 if(tbarStyle
& wxTB_TEXT
)
1758 if(tbarStyle
& wxTB_HORIZONTAL
)
1760 dc
.DrawLabel(label
, bitmap
, rect
, wxALIGN_CENTRE
);
1764 dc
.DrawLabel(label
, bitmap
, rect
, wxALIGN_LEFT
|wxALIGN_CENTER_VERTICAL
);
1769 int xpoint
= (rect
.GetLeft() + rect
.GetRight() + 1 - bitmap
.GetWidth()) / 2;
1770 int ypoint
= (rect
.GetTop() + rect
.GetBottom() + 1 - bitmap
.GetHeight()) / 2;
1771 dc
.DrawBitmap(bitmap
, xpoint
, ypoint
);
1774 else if (style
== wxTOOL_STYLE_SEPARATOR
)
1776 // leave a small gap aroudn the line, also account for the toolbar
1778 if(rectOrig
.height
> rectOrig
.width
)
1781 DrawVerticalLine(dc
, rectOrig
.x
+ rectOrig
.width
/2,
1782 rectOrig
.y
+ 2*BORDER_THICKNESS
,
1783 rectOrig
.GetBottom() - BORDER_THICKNESS
);
1788 DrawHorizontalLine(dc
, rectOrig
.y
+ rectOrig
.height
/2,
1789 rectOrig
.x
+ 2*BORDER_THICKNESS
,
1790 rectOrig
.GetRight() - BORDER_THICKNESS
);
1793 // don't draw wxTOOL_STYLE_CONTROL
1795 #endif // wxUSE_TOOLBAR
1797 // ----------------------------------------------------------------------------
1799 // ----------------------------------------------------------------------------
1803 void wxWin32Renderer
::DrawTab(wxDC
& dc
,
1804 const wxRect
& rectOrig
,
1806 const wxString
& label
,
1807 const wxBitmap
& bitmap
,
1811 #define SELECT_FOR_VERTICAL(X,Y) ( isVertical ? Y : X )
1812 #define REVERSE_FOR_VERTICAL(X,Y) \
1813 SELECT_FOR_VERTICAL(X,Y) \
1815 SELECT_FOR_VERTICAL(Y,X)
1817 wxRect rect
= rectOrig
;
1819 bool isVertical
= ( dir
== wxLEFT
) || ( dir
== wxRIGHT
);
1821 // the current tab is drawn indented (to the top for default case) and
1822 // bigger than the other ones
1823 const wxSize indent
= GetTabIndent();
1824 if ( flags
& wxCONTROL_SELECTED
)
1826 rect
.Inflate( SELECT_FOR_VERTICAL( indent
.x
, 0),
1827 SELECT_FOR_VERTICAL( 0, indent
.y
));
1831 wxFAIL_MSG(_T("invaild notebook tab orientation"));
1838 rect
.height
+= indent
.y
;
1845 rect
.width
+= indent
.x
;
1850 // draw the text, image and the focus around them (if necessary)
1851 wxRect
rectLabel( REVERSE_FOR_VERTICAL(rect
.x
,rect
.y
),
1852 REVERSE_FOR_VERTICAL(rect
.width
,rect
.height
)
1854 rectLabel
.Deflate(1, 1);
1857 // draw it horizontally into memory and rotate for screen
1859 wxBitmap bitmapRotated
,
1860 bitmapMem( rectLabel
.x
+ rectLabel
.width
,
1861 rectLabel
.y
+ rectLabel
.height
);
1862 dcMem
.SelectObject(bitmapMem
);
1863 dcMem
.SetBackground(dc
.GetBackground());
1864 dcMem
.SetFont(dc
.GetFont());
1865 dcMem
.SetTextForeground(dc
.GetTextForeground());
1869 wxBitmap( wxImage( bitmap
.ConvertToImage() ).Rotate90(dir
==wxLEFT
) )
1872 #endif // wxUSE_IMAGE
1874 DrawButtonLabel(dcMem
, label
, bitmapRotated
, rectLabel
,
1875 flags
, wxALIGN_CENTRE
, indexAccel
);
1876 dcMem
.SelectObject(wxNullBitmap
);
1877 bitmapMem
= bitmapMem
.GetSubBitmap(rectLabel
);
1879 bitmapMem
= wxBitmap(wxImage(bitmapMem
.ConvertToImage()).Rotate90(dir
==wxRIGHT
));
1880 #endif // wxUSE_IMAGE
1881 dc
.DrawBitmap(bitmapMem
, rectLabel
.y
, rectLabel
.x
, false);
1885 DrawButtonLabel(dc
, label
, bitmap
, rectLabel
,
1886 flags
, wxALIGN_CENTRE
, indexAccel
);
1889 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
1890 static const wxCoord CUTOFF
= 2; // radius of the rounded corner
1891 wxCoord x
= SELECT_FOR_VERTICAL(rect
.x
,rect
.y
),
1892 y
= SELECT_FOR_VERTICAL(rect
.y
,rect
.x
),
1893 x2
= SELECT_FOR_VERTICAL(rect
.GetRight(),rect
.GetBottom()),
1894 y2
= SELECT_FOR_VERTICAL(rect
.GetBottom(),rect
.GetRight());
1896 // FIXME: all this code will break if the tab indent or the border width,
1897 // it is tied to the fact that both of them are equal to 2
1903 // left orientation looks like top but IsVertical makes x and y reversed
1905 // top is not vertical so use coordinates in written order
1906 dc
.SetPen(m_penHighlight
);
1907 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
, y2
),
1908 REVERSE_FOR_VERTICAL(x
, y
+ CUTOFF
));
1909 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
, y
+ CUTOFF
),
1910 REVERSE_FOR_VERTICAL(x
+ CUTOFF
, y
));
1911 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
+ CUTOFF
, y
),
1912 REVERSE_FOR_VERTICAL(x2
- CUTOFF
+ 1, y
));
1914 dc
.SetPen(m_penBlack
);
1915 dc
.DrawLine(REVERSE_FOR_VERTICAL(x2
, y2
),
1916 REVERSE_FOR_VERTICAL(x2
, y
+ CUTOFF
));
1917 dc
.DrawLine(REVERSE_FOR_VERTICAL(x2
, y
+ CUTOFF
),
1918 REVERSE_FOR_VERTICAL(x2
- CUTOFF
, y
));
1920 dc
.SetPen(m_penDarkGrey
);
1921 dc
.DrawLine(REVERSE_FOR_VERTICAL(x2
- 1, y2
),
1922 REVERSE_FOR_VERTICAL(x2
- 1, y
+ CUTOFF
- 1));
1924 if ( flags
& wxCONTROL_SELECTED
)
1926 dc
.SetPen(m_penLightGrey
);
1928 // overwrite the part of the border below this tab
1929 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
+ 1, y2
+ 1),
1930 REVERSE_FOR_VERTICAL(x2
- 1, y2
+ 1));
1932 // and the shadow of the tab to the left of us
1933 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
+ 1, y
+ CUTOFF
+ 1),
1934 REVERSE_FOR_VERTICAL(x
+ 1, y2
+ 1));
1939 // right orientation looks like bottom but IsVertical makes x and y reversed
1941 // bottom is not vertical so use coordinates in written order
1942 dc
.SetPen(m_penHighlight
);
1943 // we need to continue one pixel further to overwrite the corner of
1944 // the border for the selected tab
1945 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
, y
- (flags
& wxCONTROL_SELECTED ?
1 : 0)),
1946 REVERSE_FOR_VERTICAL(x
, y2
- CUTOFF
));
1947 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
, y2
- CUTOFF
),
1948 REVERSE_FOR_VERTICAL(x
+ CUTOFF
, y2
));
1950 dc
.SetPen(m_penBlack
);
1951 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
+ CUTOFF
, y2
),
1952 REVERSE_FOR_VERTICAL(x2
- CUTOFF
+ 1, y2
));
1953 dc
.DrawLine(REVERSE_FOR_VERTICAL(x2
, y
),
1954 REVERSE_FOR_VERTICAL(x2
, y2
- CUTOFF
));
1955 dc
.DrawLine(REVERSE_FOR_VERTICAL(x2
, y2
- CUTOFF
),
1956 REVERSE_FOR_VERTICAL(x2
- CUTOFF
, y2
));
1958 dc
.SetPen(m_penDarkGrey
);
1959 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
+ CUTOFF
, y2
- 1),
1960 REVERSE_FOR_VERTICAL(x2
- CUTOFF
+ 1, y2
- 1));
1961 dc
.DrawLine(REVERSE_FOR_VERTICAL(x2
- 1, y
),
1962 REVERSE_FOR_VERTICAL(x2
- 1, y2
- CUTOFF
+ 1));
1964 if ( flags
& wxCONTROL_SELECTED
)
1966 dc
.SetPen(m_penLightGrey
);
1968 // overwrite the part of the (double!) border above this tab
1969 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
+ 1, y
- 1),
1970 REVERSE_FOR_VERTICAL(x2
- 1, y
- 1));
1971 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
+ 1, y
- 2),
1972 REVERSE_FOR_VERTICAL(x2
- 1, y
- 2));
1974 // and the shadow of the tab to the left of us
1975 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
+ 1, y2
- CUTOFF
),
1976 REVERSE_FOR_VERTICAL(x
+ 1, y
- 1));
1981 #undef SELECT_FOR_VERTICAL
1982 #undef REVERSE_FOR_VERTICAL
1985 #endif // wxUSE_NOTEBOOK
1989 // ----------------------------------------------------------------------------
1991 // ----------------------------------------------------------------------------
1994 wxWin32Renderer
::GetSliderThumbSize(const wxRect
& WXUNUSED(rect
),
1996 wxOrientation orient
) const
1999 wxCoord width
= wxMax (lenThumb
, SLIDER_THUMB_LENGTH
) / 2;
2000 wxCoord height
= wxMax (lenThumb
, SLIDER_THUMB_LENGTH
);
2002 if (orient
== wxHORIZONTAL
)
2016 wxRect wxWin32Renderer
::GetSliderShaftRect(const wxRect
& rectOrig
,
2018 wxOrientation orient
,
2021 bool transpose
= (orient
== wxVERTICAL
);
2022 bool left
= ((style
& wxSL_AUTOTICKS
) != 0) &
2023 (((style
& wxSL_TOP
) != 0) & !transpose
|
2024 ((style
& wxSL_LEFT
) != 0) & transpose
|
2025 ((style
& wxSL_BOTH
) != 0));
2026 bool right
= ((style
& wxSL_AUTOTICKS
) != 0) &
2027 (((style
& wxSL_BOTTOM
) != 0) & !transpose
|
2028 ((style
& wxSL_RIGHT
) != 0) & transpose
|
2029 ((style
& wxSL_BOTH
) != 0));
2031 wxRect rect
= rectOrig
;
2033 wxSize sizeThumb
= GetSliderThumbSize (rect
, lenThumb
, orient
);
2035 if (orient
== wxHORIZONTAL
) {
2036 rect
.x
+= SLIDER_MARGIN
;
2039 rect
.y
+= wxMax ((rect
.height
- 2*BORDER_THICKNESS
) / 2, sizeThumb
.y
/2);
2043 rect
.y
+= wxMax ((rect
.height
- 2*BORDER_THICKNESS
- sizeThumb
.y
/2), sizeThumb
.y
/2);
2047 rect
.y
+= sizeThumb
.y
/2;
2049 rect
.width
-= 2*SLIDER_MARGIN
;
2050 rect
.height
= 2*BORDER_THICKNESS
;
2054 rect
.y
+= SLIDER_MARGIN
;
2057 rect
.x
+= wxMax ((rect
.width
- 2*BORDER_THICKNESS
) / 2, sizeThumb
.x
/2);
2061 rect
.x
+= wxMax ((rect
.width
- 2*BORDER_THICKNESS
- sizeThumb
.x
/2), sizeThumb
.x
/2);
2065 rect
.x
+= sizeThumb
.x
/2;
2067 rect
.width
= 2*BORDER_THICKNESS
;
2068 rect
.height
-= 2*SLIDER_MARGIN
;
2074 void wxWin32Renderer
::DrawSliderShaft(wxDC
& dc
,
2075 const wxRect
& rectOrig
,
2077 wxOrientation orient
,
2082 /* show shaft geometry
2100 if (flags
& wxCONTROL_FOCUSED
) {
2101 DrawFocusRect(dc
, rectOrig
);
2104 wxRect rect
= GetSliderShaftRect(rectOrig
, lenThumb
, orient
, style
);
2106 if (rectShaft
) *rectShaft
= rect
;
2108 DrawSunkenBorder(dc
, &rect
);
2111 void wxWin32Renderer
::DrawSliderThumb(wxDC
& dc
,
2113 wxOrientation orient
,
2117 /* show thumb geometry
2126 H D B where H is highlight colour
2140 The interior of this shape is filled with the hatched brush if the thumb
2144 DrawBackground(dc
, wxNullColour
, rect
, flags
);
2146 bool transpose
= (orient
== wxVERTICAL
);
2147 bool left
= ((style
& wxSL_AUTOTICKS
) != 0) &
2148 (((style
& wxSL_TOP
) != 0) & !transpose
|
2149 ((style
& wxSL_LEFT
) != 0) & transpose
) &
2150 ((style
& wxSL_BOTH
) == 0);
2151 bool right
= ((style
& wxSL_AUTOTICKS
) != 0) &
2152 (((style
& wxSL_BOTTOM
) != 0) & !transpose
|
2153 ((style
& wxSL_RIGHT
) != 0) & transpose
) &
2154 ((style
& wxSL_BOTH
) == 0);
2156 wxCoord sizeArrow
= (transpose ? rect
.height
: rect
.width
) / 2;
2157 wxCoord c
= ((transpose ? rect
.height
: rect
.width
) - 2*sizeArrow
);
2159 wxCoord x1
, x2
, x3
, y1
, y2
, y3
, y4
;
2160 x1
= (transpose ? rect
.y
: rect
.x
);
2161 x2
= (transpose ? rect
.GetBottom() : rect
.GetRight());
2162 x3
= (x1
-1+c
) + sizeArrow
;
2163 y1
= (transpose ? rect
.x
: rect
.y
);
2164 y2
= (transpose ? rect
.GetRight() : rect
.GetBottom());
2165 y3
= (left ?
(y1
-1+c
) + sizeArrow
: y1
);
2166 y4
= (right ?
(y2
+1-c
) - sizeArrow
: y2
);
2168 dc
.SetPen(m_penBlack
);
2170 DrawLine(dc
, x3
+1-c
, y1
, x2
, y3
, transpose
);
2172 DrawLine(dc
, x2
, y3
, x2
, y4
, transpose
);
2175 DrawLine(dc
, x3
+1-c
, y2
, x2
, y4
, transpose
);
2179 DrawLine(dc
, x1
, y2
, x2
, y2
, transpose
);
2182 dc
.SetPen(m_penDarkGrey
);
2183 DrawLine(dc
, x2
-1, y3
+1, x2
-1, y4
-1, transpose
);
2185 DrawLine(dc
, x3
+1-c
, y2
-1, x2
-1, y4
, transpose
);
2189 DrawLine(dc
, x1
+1, y2
-1, x2
-1, y2
-1, transpose
);
2192 dc
.SetPen(m_penHighlight
);
2195 DrawLine(dc
, x1
, y3
, x3
, y1
, transpose
);
2196 DrawLine(dc
, x3
+1-c
, y1
+1, x2
-1, y3
, transpose
);
2200 DrawLine(dc
, x1
, y1
, x2
, y1
, transpose
);
2202 DrawLine(dc
, x1
, y3
, x1
, y4
, transpose
);
2205 DrawLine(dc
, x1
, y4
, x3
+c
, y2
+c
, transpose
);
2208 if (flags
& wxCONTROL_PRESSED
) {
2209 // TODO: MSW fills the entire area inside, not just the rect
2210 wxRect rectInt
= rect
;
2213 rectInt
.SetLeft(y3
);
2214 rectInt
.SetRight(y4
);
2219 rectInt
.SetBottom(y4
);
2223 #if !defined(__WXMGL__)
2224 static const char *stipple_xpm
[] = {
2225 /* columns rows colors chars-per-pixel */
2234 // VS: MGL can only do 8x8 stipple brushes
2235 static const char *stipple_xpm
[] = {
2236 /* columns rows colors chars-per-pixel */
2251 dc
.SetBrush(wxBrush(stipple_xpm
));
2253 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, SHADOW_HIGHLIGHT
));
2254 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, CONTROL
));
2255 dc
.SetPen(*wxTRANSPARENT_PEN
);
2256 dc
.DrawRectangle(rectInt
);
2260 void wxWin32Renderer
::DrawSliderTicks(wxDC
& dc
,
2263 wxOrientation orient
,
2267 int WXUNUSED(flags
),
2270 /* show ticks geometry
2285 if (end
== start
) return;
2287 bool transpose
= (orient
== wxVERTICAL
);
2288 bool left
= ((style
& wxSL_AUTOTICKS
) != 0) &
2289 (((style
& wxSL_TOP
) != 0) & !transpose
|
2290 ((style
& wxSL_LEFT
) != 0) & transpose
|
2291 ((style
& wxSL_BOTH
) != 0));
2292 bool right
= ((style
& wxSL_AUTOTICKS
) != 0) &
2293 (((style
& wxSL_BOTTOM
) != 0) & !transpose
|
2294 ((style
& wxSL_RIGHT
) != 0) & transpose
|
2295 ((style
& wxSL_BOTH
) != 0));
2297 // default thumb size
2298 wxSize sizeThumb
= GetSliderThumbSize (rect
, 0, orient
);
2299 wxCoord defaultLen
= (transpose ? sizeThumb
.x
: sizeThumb
.y
);
2301 // normal thumb size
2302 sizeThumb
= GetSliderThumbSize (rect
, lenThumb
, orient
);
2303 wxCoord widthThumb
= (transpose ? sizeThumb
.y
: sizeThumb
.x
);
2305 wxRect rectShaft
= GetSliderShaftRect (rect
, lenThumb
, orient
, style
);
2307 wxCoord x1
, x2
, y1
, y2
, y3
, y4
, len
;
2308 x1
= (transpose ? rectShaft
.y
: rectShaft
.x
) + widthThumb
/2;
2309 x2
= (transpose ? rectShaft
.GetBottom() : rectShaft
.GetRight()) - widthThumb
/2;
2310 y1
= (transpose ? rectShaft
.x
: rectShaft
.y
) - defaultLen
/2;
2311 y2
= (transpose ? rectShaft
.GetRight() : rectShaft
.GetBottom()) + defaultLen
/2;
2312 y3
= (transpose ? rect
.x
: rect
.y
);
2313 y4
= (transpose ? rect
.GetRight() : rect
.GetBottom());
2316 dc
.SetPen(m_penBlack
);
2318 int range
= end
- start
;
2319 for ( int n
= 0; n
< range
; n
+= step
) {
2320 wxCoord x
= x1
+ (len
*n
) / range
;
2322 if (left
& (y1
> y3
)) {
2323 DrawLine(dc
, x
, y1
, x
, y3
, orient
== wxVERTICAL
);
2325 if (right
& (y4
> y2
)) {
2326 DrawLine(dc
, x
, y2
, x
, y4
, orient
== wxVERTICAL
);
2329 // always draw the line at the end position
2330 if (left
& (y1
> y3
)) {
2331 DrawLine(dc
, x2
, y1
, x2
, y3
, orient
== wxVERTICAL
);
2333 if (right
& (y4
> y2
)) {
2334 DrawLine(dc
, x2
, y2
, x2
, y4
, orient
== wxVERTICAL
);
2338 #endif // wxUSE_SLIDER
2342 // ----------------------------------------------------------------------------
2344 // ----------------------------------------------------------------------------
2346 // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2347 class WXDLLEXPORT wxWin32MenuGeometryInfo
: public wxMenuGeometryInfo
2350 virtual wxSize
GetSize() const { return m_size
; }
2352 wxCoord
GetLabelOffset() const { return m_ofsLabel
; }
2353 wxCoord
GetAccelOffset() const { return m_ofsAccel
; }
2355 wxCoord
GetItemHeight() const { return m_heightItem
; }
2358 // the total size of the menu
2361 // the offset of the start of the menu item label
2364 // the offset of the start of the accel label
2367 // the height of a normal (not separator) item
2368 wxCoord m_heightItem
;
2370 friend wxMenuGeometryInfo
*
2371 wxWin32Renderer
::GetMenuGeometry(wxWindow
*, const wxMenu
&) const;
2374 // FIXME: all constants are hardcoded but shouldn't be
2375 static const wxCoord MENU_LEFT_MARGIN
= 9;
2376 static const wxCoord MENU_RIGHT_MARGIN
= 18;
2377 static const wxCoord MENU_VERT_MARGIN
= 3;
2379 // the margin around bitmap/check marks (on each side)
2380 static const wxCoord MENU_BMP_MARGIN
= 2;
2382 // the margin between the labels and accel strings
2383 static const wxCoord MENU_ACCEL_MARGIN
= 8;
2385 // the separator height in pixels: in fact, strangely enough, the real height
2386 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2388 static const wxCoord MENU_SEPARATOR_HEIGHT
= 3;
2390 // the size of the standard checkmark bitmap
2391 static const wxCoord MENU_CHECK_SIZE
= 9;
2393 void wxWin32Renderer
::DrawMenuBarItem(wxDC
& dc
,
2394 const wxRect
& rectOrig
,
2395 const wxString
& label
,
2399 wxRect rect
= rectOrig
;
2402 wxDCTextColourChanger
colChanger(dc
);
2404 if ( flags
& wxCONTROL_SELECTED
)
2406 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2408 const wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2411 dc
.DrawRectangle(rect
);
2414 // don't draw the focus rect around menu bar items
2415 DrawLabel(dc
, label
, rect
, flags
& ~wxCONTROL_FOCUSED
,
2416 wxALIGN_CENTRE
, indexAccel
);
2419 void wxWin32Renderer
::DrawMenuItem(wxDC
& dc
,
2421 const wxMenuGeometryInfo
& gi
,
2422 const wxString
& label
,
2423 const wxString
& accel
,
2424 const wxBitmap
& bitmap
,
2428 const wxWin32MenuGeometryInfo
& geometryInfo
=
2429 (const wxWin32MenuGeometryInfo
&)gi
;
2434 rect
.width
= geometryInfo
.GetSize().x
;
2435 rect
.height
= geometryInfo
.GetItemHeight();
2437 // draw the selected item specially
2438 wxDCTextColourChanger
colChanger(dc
);
2439 if ( flags
& wxCONTROL_SELECTED
)
2441 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2443 const wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2446 dc
.DrawRectangle(rect
);
2449 // draw the bitmap: use the bitmap provided or the standard checkmark for
2450 // the checkable items
2451 wxBitmap bmp
= bitmap
;
2452 if ( !bmp
.Ok() && (flags
& wxCONTROL_CHECKED
) )
2454 bmp
= GetIndicator(IndicatorType_Menu
, flags
);
2459 rect
.SetRight(geometryInfo
.GetLabelOffset());
2460 wxControlRenderer
::DrawBitmap(dc
, bmp
, rect
);
2464 rect
.x
= geometryInfo
.GetLabelOffset();
2465 rect
.SetRight(geometryInfo
.GetAccelOffset());
2467 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
, indexAccel
);
2469 // draw the accel string
2470 rect
.x
= geometryInfo
.GetAccelOffset();
2471 rect
.SetRight(geometryInfo
.GetSize().x
);
2473 // NB: no accel index here
2474 DrawLabel(dc
, accel
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
);
2476 // draw the submenu indicator
2477 if ( flags
& wxCONTROL_ISSUBMENU
)
2479 rect
.x
= geometryInfo
.GetSize().x
- MENU_RIGHT_MARGIN
;
2480 rect
.width
= MENU_RIGHT_MARGIN
;
2482 ArrowStyle arrowStyle
;
2483 if ( flags
& wxCONTROL_DISABLED
)
2484 arrowStyle
= flags
& wxCONTROL_SELECTED ? Arrow_InvertedDisabled
2486 else if ( flags
& wxCONTROL_SELECTED
)
2487 arrowStyle
= Arrow_Inverted
;
2489 arrowStyle
= Arrow_Normal
;
2491 DrawArrow(dc
, rect
, Arrow_Right
, arrowStyle
);
2495 void wxWin32Renderer
::DrawMenuSeparator(wxDC
& dc
,
2497 const wxMenuGeometryInfo
& geomInfo
)
2499 DrawHorizontalLine(dc
, y
+ MENU_VERT_MARGIN
, 0, geomInfo
.GetSize().x
);
2502 wxSize wxWin32Renderer
::GetMenuBarItemSize(const wxSize
& sizeText
) const
2504 wxSize size
= sizeText
;
2506 // FIXME: menubar height is configurable under Windows
2513 wxMenuGeometryInfo
*wxWin32Renderer
::GetMenuGeometry(wxWindow
*win
,
2514 const wxMenu
& menu
) const
2516 // prepare the dc: for now we draw all the items with the system font
2518 dc
.SetFont(wxSystemSettings
::GetFont(wxSYS_DEFAULT_GUI_FONT
));
2520 // the height of a normal item
2521 wxCoord heightText
= dc
.GetCharHeight();
2526 // the max length of label and accel strings: the menu width is the sum of
2527 // them, even if they're for different items (as the accels should be
2530 // the max length of the bitmap is never 0 as Windows always leaves enough
2531 // space for a check mark indicator
2532 wxCoord widthLabelMax
= 0,
2534 widthBmpMax
= MENU_LEFT_MARGIN
;
2536 for ( wxMenuItemList
::compatibility_iterator node
= menu
.GetMenuItems().GetFirst();
2538 node
= node
->GetNext() )
2540 // height of this item
2543 wxMenuItem
*item
= node
->GetData();
2544 if ( item
->IsSeparator() )
2546 h
= MENU_SEPARATOR_HEIGHT
;
2548 else // not separator
2553 dc
.GetTextExtent(item
->GetLabel(), &widthLabel
, NULL
);
2554 if ( widthLabel
> widthLabelMax
)
2556 widthLabelMax
= widthLabel
;
2560 dc
.GetTextExtent(item
->GetAccelString(), &widthAccel
, NULL
);
2561 if ( widthAccel
> widthAccelMax
)
2563 widthAccelMax
= widthAccel
;
2566 const wxBitmap
& bmp
= item
->GetBitmap();
2569 wxCoord widthBmp
= bmp
.GetWidth();
2570 if ( widthBmp
> widthBmpMax
)
2571 widthBmpMax
= widthBmp
;
2573 //else if ( item->IsCheckable() ): no need to check for this as
2574 // MENU_LEFT_MARGIN is big enough to show the check mark
2577 h
+= 2*MENU_VERT_MARGIN
;
2579 // remember the item position and height
2580 item
->SetGeometry(height
, h
);
2585 // bundle the metrics into a struct and return it
2586 wxWin32MenuGeometryInfo
*gi
= new wxWin32MenuGeometryInfo
;
2588 gi
->m_ofsLabel
= widthBmpMax
+ 2*MENU_BMP_MARGIN
;
2589 gi
->m_ofsAccel
= gi
->m_ofsLabel
+ widthLabelMax
;
2590 if ( widthAccelMax
> 0 )
2592 // if we actually have any accesl, add a margin
2593 gi
->m_ofsAccel
+= MENU_ACCEL_MARGIN
;
2596 gi
->m_heightItem
= heightText
+ 2*MENU_VERT_MARGIN
;
2598 gi
->m_size
.x
= gi
->m_ofsAccel
+ widthAccelMax
+ MENU_RIGHT_MARGIN
;
2599 gi
->m_size
.y
= height
;
2604 #endif // wxUSE_MENUS
2608 // ----------------------------------------------------------------------------
2610 // ----------------------------------------------------------------------------
2612 void wxWin32Renderer
::DrawStatusField(wxDC
& dc
,
2614 const wxString
& label
,
2620 if ( flags
& wxCONTROL_SIZEGRIP
)
2622 // draw the size grip: it is a normal rect except that in the lower
2623 // right corner we have several bands which may be used for dragging
2624 // the status bar corner
2626 // each band consists of 4 stripes: m_penHighlight, double
2627 // m_penDarkGrey and transparent one
2628 wxCoord x2
= rect
.GetRight(),
2629 y2
= rect
.GetBottom();
2631 // draw the upper left part of the rect normally
2632 if (style
!= wxSB_FLAT
)
2634 if (style
== wxSB_RAISED
)
2635 dc
.SetPen(m_penHighlight
);
2637 dc
.SetPen(m_penDarkGrey
);
2638 dc
.DrawLine(rect
.GetLeft(), rect
.GetTop(), rect
.GetLeft(), y2
);
2639 dc
.DrawLine(rect
.GetLeft() + 1, rect
.GetTop(), x2
, rect
.GetTop());
2642 // draw the grey stripes of the grip
2644 wxCoord ofs
= WIDTH_STATUSBAR_GRIP_BAND
- 1;
2645 for ( n
= 0; n
< NUM_STATUSBAR_GRIP_BANDS
; n
++, ofs
+= WIDTH_STATUSBAR_GRIP_BAND
)
2647 dc
.DrawLine(x2
- ofs
+ 1, y2
- 1, x2
, y2
- ofs
);
2648 dc
.DrawLine(x2
- ofs
, y2
- 1, x2
, y2
- ofs
- 1);
2651 // draw the white stripes
2652 dc
.SetPen(m_penHighlight
);
2653 ofs
= WIDTH_STATUSBAR_GRIP_BAND
+ 1;
2654 for ( n
= 0; n
< NUM_STATUSBAR_GRIP_BANDS
; n
++, ofs
+= WIDTH_STATUSBAR_GRIP_BAND
)
2656 dc
.DrawLine(x2
- ofs
+ 1, y2
- 1, x2
, y2
- ofs
);
2659 // draw the remaining rect boundaries
2660 if (style
!= wxSB_FLAT
)
2662 if (style
== wxSB_RAISED
)
2663 dc
.SetPen(m_penDarkGrey
);
2665 dc
.SetPen(m_penHighlight
);
2666 ofs
-= WIDTH_STATUSBAR_GRIP_BAND
;
2667 dc
.DrawLine(x2
, rect
.GetTop(), x2
, y2
- ofs
+ 1);
2668 dc
.DrawLine(rect
.GetLeft(), y2
, x2
- ofs
+ 1, y2
);
2674 rectIn
.width
-= STATUSBAR_GRIP_SIZE
;
2676 // this will prevent the standard version from drawing any borders
2680 DrawStatusField(dc
, rect
, label
, flags
, style
);
2683 #endif // wxUSE_STATUSBAR
2685 // ----------------------------------------------------------------------------
2687 // ----------------------------------------------------------------------------
2689 void wxWin32Renderer
::GetComboBitmaps(wxBitmap
*bmpNormal
,
2690 wxBitmap
* WXUNUSED(bmpFocus
),
2691 wxBitmap
*bmpPressed
,
2692 wxBitmap
*bmpDisabled
)
2694 static const wxCoord widthCombo
= 16;
2695 static const wxCoord heightCombo
= 17;
2701 bmpNormal
->Create(widthCombo
, heightCombo
);
2702 dcMem
.SelectObject(*bmpNormal
);
2703 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2704 Arrow_Down
, Arrow_Normal
);
2709 bmpPressed
->Create(widthCombo
, heightCombo
);
2710 dcMem
.SelectObject(*bmpPressed
);
2711 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2712 Arrow_Down
, Arrow_Pressed
);
2717 bmpDisabled
->Create(widthCombo
, heightCombo
);
2718 dcMem
.SelectObject(*bmpDisabled
);
2719 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
2720 Arrow_Down
, Arrow_Disabled
);
2724 // ----------------------------------------------------------------------------
2726 // ----------------------------------------------------------------------------
2728 void wxWin32Renderer
::DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
)
2732 DrawRect(dc
, rect
, m_penDarkGrey
);
2734 // the arrow is usually drawn inside border of width 2 and is offset by
2735 // another pixel in both directions when it's pressed - as the border
2736 // in this case is more narrow as well, we have to adjust rect like
2744 DrawAntiSunkenBorder(dc
, rect
);
2748 void wxWin32Renderer
::DrawArrow(wxDC
& dc
,
2753 ArrowStyle arrowStyle
;
2754 if ( flags
& wxCONTROL_PRESSED
)
2756 // can't be pressed and disabled
2757 arrowStyle
= Arrow_Pressed
;
2761 arrowStyle
= flags
& wxCONTROL_DISABLED ? Arrow_Disabled
: Arrow_Normal
;
2764 DrawArrowButton(dc
, rect
, GetArrowDirection(dir
), arrowStyle
);
2767 void wxWin32Renderer
::DrawArrow(wxDC
& dc
,
2769 ArrowDirection arrowDir
,
2770 ArrowStyle arrowStyle
)
2772 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
2774 // under Windows the arrows always have the same size so just centre it in
2775 // the provided rectangle
2776 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
2777 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
2779 // Windows does it like this...
2780 if ( arrowDir
== Arrow_Left
)
2784 dc
.DrawBitmap(bmp
, x
, y
, true /* use mask */);
2787 void wxWin32Renderer
::DrawArrowButton(wxDC
& dc
,
2788 const wxRect
& rectAll
,
2789 ArrowDirection arrowDir
,
2790 ArrowStyle arrowStyle
)
2792 wxRect rect
= rectAll
;
2793 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
2794 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
2795 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
2798 void wxWin32Renderer
::DrawScrollbarThumb(wxDC
& dc
,
2799 wxOrientation
WXUNUSED(orient
),
2801 int WXUNUSED(flags
))
2803 // we don't use the flags, the thumb never changes appearance
2804 wxRect rectThumb
= rect
;
2805 DrawArrowBorder(dc
, &rectThumb
);
2806 DrawBackground(dc
, wxNullColour
, rectThumb
);
2809 void wxWin32Renderer
::DrawScrollbarShaft(wxDC
& dc
,
2810 wxOrientation
WXUNUSED(orient
),
2811 const wxRect
& rectBar
,
2814 wxColourScheme
::StdColour col
= flags
& wxCONTROL_PRESSED
2815 ? wxColourScheme
::SCROLLBAR_PRESSED
2816 : wxColourScheme
::SCROLLBAR
;
2817 DrawBackground(dc
, m_scheme
->Get(col
), rectBar
);
2820 // ----------------------------------------------------------------------------
2821 // top level windows
2822 // ----------------------------------------------------------------------------
2824 int wxWin32Renderer
::HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const
2826 wxRect client
= GetFrameClientArea(rect
, flags
);
2828 if ( client
.Contains(pt
) )
2829 return wxHT_TOPLEVEL_CLIENT_AREA
;
2831 if ( flags
& wxTOPLEVEL_TITLEBAR
)
2833 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
2835 if ( flags
& wxTOPLEVEL_ICON
)
2837 if ( wxRect(client
.GetPosition(), GetFrameIconSize()).Contains(pt
) )
2838 return wxHT_TOPLEVEL_ICON
;
2841 wxRect
btnRect(client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
,
2842 client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2,
2843 FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
2845 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
2847 if ( btnRect
.Contains(pt
) )
2848 return wxHT_TOPLEVEL_BUTTON_CLOSE
;
2849 btnRect
.x
-= FRAME_BUTTON_WIDTH
+ 2;
2851 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
2853 if ( btnRect
.Contains(pt
) )
2854 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE
;
2855 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
2857 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
2859 if ( btnRect
.Contains(pt
) )
2860 return wxHT_TOPLEVEL_BUTTON_RESTORE
;
2861 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
2863 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
2865 if ( btnRect
.Contains(pt
) )
2866 return wxHT_TOPLEVEL_BUTTON_ICONIZE
;
2867 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
2869 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
2871 if ( btnRect
.Contains(pt
) )
2872 return wxHT_TOPLEVEL_BUTTON_HELP
;
2873 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
2876 if ( pt
.y
>= client
.y
&& pt
.y
< client
.y
+ FRAME_TITLEBAR_HEIGHT
)
2877 return wxHT_TOPLEVEL_TITLEBAR
;
2880 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
2882 // we are certainly at one of borders, lets decide which one:
2885 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
2886 if ( pt
.x
< client
.x
)
2887 border
|= wxHT_TOPLEVEL_BORDER_W
;
2888 else if ( pt
.x
>= client
.width
+ client
.x
)
2889 border
|= wxHT_TOPLEVEL_BORDER_E
;
2890 if ( pt
.y
< client
.y
)
2891 border
|= wxHT_TOPLEVEL_BORDER_N
;
2892 else if ( pt
.y
>= client
.height
+ client
.y
)
2893 border
|= wxHT_TOPLEVEL_BORDER_S
;
2897 return wxHT_NOWHERE
;
2900 void wxWin32Renderer
::DrawFrameTitleBar(wxDC
& dc
,
2902 const wxString
& title
,
2906 int specialButtonFlags
)
2908 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
2910 DrawFrameBorder(dc
, rect
, flags
);
2912 if ( flags
& wxTOPLEVEL_TITLEBAR
)
2914 DrawFrameBackground(dc
, rect
, flags
);
2915 if ( flags
& wxTOPLEVEL_ICON
)
2916 DrawFrameIcon(dc
, rect
, icon
, flags
);
2917 DrawFrameTitle(dc
, rect
, title
, flags
);
2919 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
2921 x
= client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
;
2922 y
= client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2;
2924 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
2926 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_CLOSE
,
2927 (specialButton
== wxTOPLEVEL_BUTTON_CLOSE
) ?
2928 specialButtonFlags
: 0);
2929 x
-= FRAME_BUTTON_WIDTH
+ 2;
2931 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
2933 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_MAXIMIZE
,
2934 (specialButton
== wxTOPLEVEL_BUTTON_MAXIMIZE
) ?
2935 specialButtonFlags
: 0);
2936 x
-= FRAME_BUTTON_WIDTH
;
2938 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
2940 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_RESTORE
,
2941 (specialButton
== wxTOPLEVEL_BUTTON_RESTORE
) ?
2942 specialButtonFlags
: 0);
2943 x
-= FRAME_BUTTON_WIDTH
;
2945 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
2947 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_ICONIZE
,
2948 (specialButton
== wxTOPLEVEL_BUTTON_ICONIZE
) ?
2949 specialButtonFlags
: 0);
2950 x
-= FRAME_BUTTON_WIDTH
;
2952 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
2954 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_HELP
,
2955 (specialButton
== wxTOPLEVEL_BUTTON_HELP
) ?
2956 specialButtonFlags
: 0);
2961 void wxWin32Renderer
::DrawFrameBorder(wxDC
& dc
,
2965 if ( !(flags
& wxTOPLEVEL_BORDER
) ) return;
2969 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penBlack
);
2970 DrawShadedRect(dc
, &r
, m_penHighlight
, m_penDarkGrey
);
2971 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penLightGrey
);
2972 if ( flags
& wxTOPLEVEL_RESIZEABLE
)
2973 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penLightGrey
);
2976 void wxWin32Renderer
::DrawFrameBackground(wxDC
& dc
,
2980 if ( !(flags
& wxTOPLEVEL_TITLEBAR
) ) return;
2982 wxColour col
= (flags
& wxTOPLEVEL_ACTIVE
) ?
2983 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_ACTIVE
) :
2984 wxSCHEME_COLOUR(m_scheme
, TITLEBAR
);
2986 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
2987 r
.height
= FRAME_TITLEBAR_HEIGHT
;
2989 DrawBackground(dc
, col
, r
);
2992 void wxWin32Renderer
::DrawFrameTitle(wxDC
& dc
,
2994 const wxString
& title
,
2997 wxColour col
= (flags
& wxTOPLEVEL_ACTIVE
) ?
2998 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_ACTIVE_TEXT
) :
2999 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_TEXT
);
3001 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3002 r
.height
= FRAME_TITLEBAR_HEIGHT
;
3003 if ( flags
& wxTOPLEVEL_ICON
)
3005 r
.x
+= FRAME_TITLEBAR_HEIGHT
;
3006 r
.width
-= FRAME_TITLEBAR_HEIGHT
+ 2;
3014 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3015 r
.width
-= FRAME_BUTTON_WIDTH
+ 2;
3016 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3017 r
.width
-= FRAME_BUTTON_WIDTH
;
3018 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3019 r
.width
-= FRAME_BUTTON_WIDTH
;
3020 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3021 r
.width
-= FRAME_BUTTON_WIDTH
;
3022 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3023 r
.width
-= FRAME_BUTTON_WIDTH
;
3025 dc
.SetFont(m_titlebarFont
);
3026 dc
.SetTextForeground(col
);
3029 dc
.GetTextExtent(title
, &textW
, NULL
);
3030 if ( textW
> r
.width
)
3032 // text is too big, let's shorten it and add "..." after it:
3033 size_t len
= title
.length();
3034 wxCoord WSoFar
, letterW
;
3036 dc
.GetTextExtent(wxT("..."), &WSoFar
, NULL
);
3037 if ( WSoFar
> r
.width
)
3039 // not enough space to draw anything
3045 for (size_t i
= 0; i
< len
; i
++)
3047 dc
.GetTextExtent(title
[i
], &letterW
, NULL
);
3048 if ( letterW
+ WSoFar
> r
.width
)
3054 dc
.DrawLabel(s
, wxNullBitmap
, r
,
3055 wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
3058 dc
.DrawLabel(title
, wxNullBitmap
, r
,
3059 wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
3062 void wxWin32Renderer
::DrawFrameIcon(wxDC
& dc
,
3069 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3070 dc
.DrawIcon(icon
, r
.x
, r
.y
);
3074 void wxWin32Renderer
::DrawFrameButton(wxDC
& dc
,
3075 wxCoord x
, wxCoord y
,
3079 wxRect
r(x
, y
, FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
3084 case wxTOPLEVEL_BUTTON_CLOSE
: idx
= FrameButton_Close
; break;
3085 case wxTOPLEVEL_BUTTON_MAXIMIZE
: idx
= FrameButton_Maximize
; break;
3086 case wxTOPLEVEL_BUTTON_ICONIZE
: idx
= FrameButton_Minimize
; break;
3087 case wxTOPLEVEL_BUTTON_RESTORE
: idx
= FrameButton_Restore
; break;
3088 case wxTOPLEVEL_BUTTON_HELP
: idx
= FrameButton_Help
; break;
3090 wxFAIL_MSG(wxT("incorrect button specification"));
3093 if ( flags
& wxCONTROL_PRESSED
)
3095 DrawShadedRect(dc
, &r
, m_penBlack
, m_penHighlight
);
3096 DrawShadedRect(dc
, &r
, m_penDarkGrey
, m_penLightGrey
);
3097 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), r
);
3098 dc
.DrawBitmap(m_bmpFrameButtons
[idx
], r
.x
+1, r
.y
+1, true);
3102 DrawShadedRect(dc
, &r
, m_penHighlight
, m_penBlack
);
3103 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penDarkGrey
);
3104 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), r
);
3105 dc
.DrawBitmap(m_bmpFrameButtons
[idx
], r
.x
, r
.y
, true);
3110 wxRect wxWin32Renderer
::GetFrameClientArea(const wxRect
& rect
,
3115 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3117 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3118 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3119 FRAME_BORDER_THICKNESS
;
3122 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3124 r
.y
+= FRAME_TITLEBAR_HEIGHT
;
3125 r
.height
-= FRAME_TITLEBAR_HEIGHT
;
3131 wxSize wxWin32Renderer
::GetFrameTotalSize(const wxSize
& clientSize
,
3134 wxSize
s(clientSize
);
3136 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3138 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3139 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3140 FRAME_BORDER_THICKNESS
;
3144 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3145 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
3150 wxSize wxWin32Renderer
::GetFrameMinSize(int flags
) const
3154 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3156 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3157 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3158 FRAME_BORDER_THICKNESS
;
3163 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3165 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
3167 if ( flags
& wxTOPLEVEL_ICON
)
3168 s
.x
+= FRAME_TITLEBAR_HEIGHT
+ 2;
3169 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3170 s
.x
+= FRAME_BUTTON_WIDTH
+ 2;
3171 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3172 s
.x
+= FRAME_BUTTON_WIDTH
;
3173 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3174 s
.x
+= FRAME_BUTTON_WIDTH
;
3175 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3176 s
.x
+= FRAME_BUTTON_WIDTH
;
3177 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3178 s
.x
+= FRAME_BUTTON_WIDTH
;
3184 wxSize wxWin32Renderer
::GetFrameIconSize() const
3186 return wxSize(16, 16);
3190 // ----------------------------------------------------------------------------
3192 // ----------------------------------------------------------------------------
3194 /* Copyright (c) Julian Smart */
3195 static char *error_xpm
[]={
3196 /* columns rows colors chars-per-pixel */
3273 " $oooooooooooo%& ",
3274 " *=-ooooooooooooo;: ",
3275 " *oooooooooooooooooo> ",
3276 " =ooooooooooooooooooo, ",
3277 " $-ooooooooooooooooooo<1 ",
3278 " .oooooo2334ooo533oooooo6 ",
3279 " +ooooooo789oo2883oooooo0q ",
3280 " oooooooo2w83o78eoooooooor ",
3281 " toooooooooy88u884oooooooori ",
3282 " Xooooooooooe888poooooooooas ",
3283 " ooooooooooo4889doooooooooof ",
3284 " ooooooooooo588w2oooooooooofi ",
3285 " oooooooooodw8887oooooooooofi ",
3286 " goooooooooh8w588jooooooookli ",
3287 " tooooooooz885op8wdooooooorix ",
3288 " oooooood98cood98cooooooori ",
3289 " @oooooop8w2ooo5885ooooovbi ",
3290 " n%ooooooooooooooooooooomiM ",
3291 " &;oooooooooooooooooooNBiV ",
3292 " :ooooooooooooooooooCZiA ",
3293 " nSooooooooooooooooCDiF ",
3294 " nG<oooooooooooooNZiiH ",
3295 " 160ooooooooovmBiFH ",
3296 " nqrraoookrrbiiA ",
3303 /* Copyright (c) Julian Smart */
3304 static char *info_xpm
[]={
3305 /* columns rows colors chars-per-pixel */
3327 " ..XXXXXXXXXXXXX.. ",
3328 " .XXXXXXXXXXXXXXXXX. ",
3329 " .XXXXXXXXoO+XXXXXXXX. ",
3330 " .XXXXXXXXX@#OXXXXXXXXX. ",
3331 " .XXXXXXXXXX$@oXXXXXXXXXX. ",
3332 " .XXXXXXXXXXXXXXXXXXXXXXX.% ",
3333 " .XXXXXXXXX&*=-XXXXXXXXXX.%% ",
3334 ".XXXXXXXXXX;:#>XXXXXXXXXXX.% ",
3335 ".XXXXXXXXXXX;#+XXXXXXXXXXX.% ",
3336 ".XXXXXXXXXXX;#+XXXXXXXXXXX.%% ",
3337 " .XXXXXXXXXX;#+XXXXXXXXXX.%%% ",
3338 " .XXXXXXXXXX;#+XXXXXXXXXX.%%% ",
3339 " .XXXXXXXXXX;#+XXXXXXXXXX.%% ",
3340 " .XXXXXXXX*-##+XXXXXXXX.%%% ",
3341 " .XXXXXXXXXXXXXXXXXXX.%%%% ",
3342 " .XXXXXXXXXXXXXXXXX.%%%% ",
3343 " ..XXXXXXXXXXXXX..%%%% ",
3344 " %...XXXXXXXX..%%%%% ",
3345 " %%%..XXXXXX.%%%%% ",
3359 /* Copyright (c) Julian Smart */
3360 static char *question_xpm
[]={
3361 /* columns rows colors chars-per-pixel */
3382 " ..XXXXXXXXXXXXX.. ",
3383 " .XXXXXXoO++@XXXXXX. ",
3384 " .XXXXXXO#$$$$#%XXXXX. ",
3385 " .XXXXXX@$$#&&#$#oXXXXX. ",
3386 " .XXXXXXX*$$%XX%$$=XXXXXX. ",
3387 " .XXXXXXX+-;XXXX$$-XXXXXX.: ",
3388 " .XXXXXXXXXXXXX+$$&XXXXXX.:: ",
3389 ".XXXXXXXXXXXXo;$$*oXXXXXXX.: ",
3390 ".XXXXXXXXXXXo*$$*oXXXXXXXX.: ",
3391 ".XXXXXXXXXXX+$$*oXXXXXXXXX.:: ",
3392 " .XXXXXXXXXX-$$oXXXXXXXXX.::: ",
3393 " .XXXXXXXXXXX--XXXXXXXXXX.::: ",
3394 " .XXXXXXXXXXXXXXXXXXXXXXX.:: ",
3395 " .XXXXXXXXX-$$XXXXXXXXX.::: ",
3396 " .XXXXXXXX-$$XXXXXXXX.:::: ",
3397 " .XXXXXXXO++XXXXXXX.:::: ",
3398 " ..XXXXXXXXXXXXX..:::: ",
3399 " :...XXXXXXXX..::::: ",
3400 " :::..XXXXXX.::::: ",
3414 /* Copyright (c) Julian Smart */
3415 static char *warning_xpm
[]={
3416 /* columns rows colors chars-per-pixel */
3442 " ..XXXXO@#XXX... ",
3443 " ...XXXXO@#XXXX.. ",
3444 " ..XXXXXO@#XXXX... ",
3445 " ...XXXXXo@OXXXXX.. ",
3446 " ...XXXXXXo@OXXXXXX.. ",
3447 " ..XXXXXXX$@OXXXXXX... ",
3448 " ...XXXXXXXX@XXXXXXXX.. ",
3449 " ...XXXXXXXXXXXXXXXXXX... ",
3450 " ..XXXXXXXXXXOXXXXXXXXX.. ",
3451 " ...XXXXXXXXXO@#XXXXXXXXX.. ",
3452 " ..XXXXXXXXXXX#XXXXXXXXXX... ",
3453 " ...XXXXXXXXXXXXXXXXXXXXXXX.. ",
3454 " ...XXXXXXXXXXXXXXXXXXXXXXXX... ",
3455 " .............................. ",
3456 " .............................. ",
3463 wxBitmap wxWin32ArtProvider
::CreateBitmap(const wxArtID
& id
,
3464 const wxArtClient
& WXUNUSED(client
),
3465 const wxSize
& WXUNUSED(size
))
3467 if ( id
== wxART_INFORMATION
)
3468 return wxBitmap(info_xpm
);
3469 if ( id
== wxART_ERROR
)
3470 return wxBitmap(error_xpm
);
3471 if ( id
== wxART_WARNING
)
3472 return wxBitmap(warning_xpm
);
3473 if ( id
== wxART_QUESTION
)
3474 return wxBitmap(question_xpm
);
3475 return wxNullBitmap
;
3481 // ----------------------------------------------------------------------------
3482 // text control geometry
3483 // ----------------------------------------------------------------------------
3486 wxWin32Renderer
::GetTextTotalArea(const wxTextCtrl
*text
,
3487 const wxRect
& rect
) const
3489 wxRect rectTotal
= wxStdRenderer
::GetTextTotalArea(text
, rect
);
3491 // this is strange but it's what Windows does
3498 wxWin32Renderer
::GetTextClientArea(const wxTextCtrl
*text
,
3500 wxCoord
*extraSpaceBeyond
) const
3502 wxRect rectText
= rect
;
3504 // undo GetTextTotalArea()
3505 if ( rectText
.height
> 0 )
3508 return wxStdRenderer
::GetTextClientArea(text
, rect
, extraSpaceBeyond
);
3511 #endif // wxUSE_TEXTCTRL
3513 // ----------------------------------------------------------------------------
3515 // ----------------------------------------------------------------------------
3517 void wxWin32Renderer
::AdjustSize(wxSize
*size
, const wxWindow
*window
)
3520 if ( wxDynamicCast(window
, wxScrollBar
) )
3522 // we only set the width of vert scrollbars and height of the
3524 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
3525 size
->y
= m_sizeScrollbarArrow
.y
;
3527 size
->x
= m_sizeScrollbarArrow
.x
;
3529 // skip border width adjustments, they don't make sense for us
3532 #endif // wxUSE_SCROLLBAR
3535 if ( wxDynamicCast(window
, wxBitmapButton
) )
3539 #endif // wxUSE_BMPBUTTON
3540 #if wxUSE_BUTTON || wxUSE_TOGGLEBTN
3543 || wxDynamicCast(window
, wxButton
)
3544 # endif // wxUSE_BUTTON
3545 # if wxUSE_TOGGLEBTN
3546 || wxDynamicCast(window
, wxToggleButton
)
3547 # endif // wxUSE_TOGGLEBTN
3550 if ( !(window
->GetWindowStyle() & wxBU_EXACTFIT
) )
3552 // TODO: don't harcode all this
3553 size
->x
+= 3*window
->GetCharWidth();
3555 wxCoord heightBtn
= (11*(window
->GetCharHeight() + 8))/10;
3556 if ( size
->y
< heightBtn
- 8 )
3557 size
->y
= heightBtn
;
3562 // for compatibility with other ports, the buttons default size is never
3563 // less than the standard one, but not when display not PDAs.
3564 if (wxSystemSettings
::GetScreenType() > wxSYS_SCREEN_PDA
)
3566 if ( !(window
->GetWindowStyle() & wxBU_EXACTFIT
) )
3568 wxSize szDef
= wxButton
::GetDefaultSize();
3569 if ( size
->x
< szDef
.x
)
3574 // no border width adjustments for buttons
3577 #endif // wxUSE_BUTTON || wxUSE_TOGGLEBTN
3579 wxStdRenderer
::AdjustSize(size
, window
);
3582 // ============================================================================
3584 // ============================================================================
3586 // ----------------------------------------------------------------------------
3587 // wxWin32InputHandler
3588 // ----------------------------------------------------------------------------
3590 bool wxWin32InputHandler
::HandleKey(wxInputConsumer
* WXUNUSED(control
),
3591 const wxKeyEvent
& WXUNUSED(event
),
3592 bool WXUNUSED(pressed
))
3597 bool wxWin32InputHandler
::HandleMouse(wxInputConsumer
*control
,
3598 const wxMouseEvent
& event
)
3600 // clicking on the control gives it focus
3601 if ( event
.ButtonDown() )
3603 wxWindow
*win
= control
->GetInputWindow();
3605 if ( (wxWindow
::FindFocus() != control
->GetInputWindow()) &&
3606 win
->AcceptsFocus() )
3619 // ----------------------------------------------------------------------------
3620 // wxWin32ScrollBarInputHandler
3621 // ----------------------------------------------------------------------------
3623 wxWin32ScrollBarInputHandler
::
3624 wxWin32ScrollBarInputHandler(wxRenderer
*renderer
, wxInputHandler
*handler
)
3625 : wxStdScrollBarInputHandler(renderer
, handler
)
3627 m_scrollPaused
= false;
3631 bool wxWin32ScrollBarInputHandler
::OnScrollTimer(wxScrollBar
*scrollbar
,
3632 const wxControlAction
& action
)
3634 // stop if went beyond the position of the original click (this can only
3635 // happen when we scroll by pages)
3637 if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
3639 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3640 != wxHT_SCROLLBAR_BAR_2
;
3642 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
3644 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
3645 != wxHT_SCROLLBAR_BAR_1
;
3650 StopScrolling(scrollbar
);
3652 scrollbar
->Refresh();
3657 return wxStdScrollBarInputHandler
::OnScrollTimer(scrollbar
, action
);
3660 bool wxWin32ScrollBarInputHandler
::HandleMouse(wxInputConsumer
*control
,
3661 const wxMouseEvent
& event
)
3663 // remember the current state
3664 bool wasDraggingThumb
= m_htLast
== wxHT_SCROLLBAR_THUMB
;
3666 // do process the message
3667 bool rc
= wxStdScrollBarInputHandler
::HandleMouse(control
, event
);
3669 // analyse the changes
3670 if ( !wasDraggingThumb
&& (m_htLast
== wxHT_SCROLLBAR_THUMB
) )
3672 // we just started dragging the thumb, remember its initial position to
3673 // be able to restore it if the drag is cancelled later
3674 m_eventStartDrag
= event
;
3680 bool wxWin32ScrollBarInputHandler
::HandleMouseMove(wxInputConsumer
*control
,
3681 const wxMouseEvent
& event
)
3683 // we don't highlight scrollbar elements, so there is no need to process
3684 // mouse move events normally - only do it while mouse is captured (i.e.
3685 // when we're dragging the thumb or pressing on something)
3686 if ( !m_winCapture
)
3689 if ( event
.Entering() )
3691 // we're not interested in this at all
3695 wxScrollBar
*scrollbar
= wxStaticCast(control
->GetInputWindow(), wxScrollBar
);
3697 if ( m_scrollPaused
)
3699 // check if the mouse returned to its original location
3701 if ( event
.Leaving() )
3707 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3708 if ( ht
== m_htLast
)
3710 // yes it did, resume scrolling
3711 m_scrollPaused
= false;
3712 if ( m_timerScroll
)
3714 // we were scrolling by line/page, restart timer
3715 m_timerScroll
->Start(m_interval
);
3717 Press(scrollbar
, true);
3719 else // we were dragging the thumb
3721 // restore its last location
3722 HandleThumbMove(scrollbar
, m_eventLastDrag
);
3728 else // normal case, scrolling hasn't been paused
3730 // if we're scrolling the scrollbar because the arrow or the shaft was
3731 // pressed, check that the mouse stays on the same scrollbar element
3734 // Always let thumb jump back if we leave the scrollbar
3735 if ( event
.Moving() )
3737 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
3739 else // event.Leaving()
3744 // Jump back only if we get far away from it
3745 wxPoint pos
= event
.GetPosition();
3746 if (scrollbar
->HasFlag( wxVERTICAL
))
3748 if (pos
.x
> -40 && pos
.x
< scrollbar
->GetSize().x
+40)
3753 if (pos
.y
> -40 && pos
.y
< scrollbar
->GetSize().y
+40)
3756 ht
= m_renderer
->HitTestScrollbar(scrollbar
, pos
);
3759 // if we're dragging the thumb and the mouse stays in the scrollbar, it
3760 // is still ok - we only want to catch the case when the mouse leaves
3761 // the scrollbar here
3762 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
&& ht
!= wxHT_NOWHERE
)
3764 ht
= wxHT_SCROLLBAR_THUMB
;
3767 if ( ht
!= m_htLast
)
3769 // what were we doing? 2 possibilities: either an arrow/shaft was
3770 // pressed in which case we have a timer and so we just stop it or
3771 // we were dragging the thumb
3772 if ( m_timerScroll
)
3775 m_interval
= m_timerScroll
->GetInterval();
3776 m_timerScroll
->Stop();
3777 m_scrollPaused
= true;
3779 // unpress the arrow
3780 Press(scrollbar
, false);
3782 else // we were dragging the thumb
3784 // remember the current thumb position to be able to restore it
3785 // if the mouse returns to it later
3786 m_eventLastDrag
= event
;
3788 // and restore the original position (before dragging) of the
3790 HandleThumbMove(scrollbar
, m_eventStartDrag
);
3797 return wxStdInputHandler
::HandleMouseMove(control
, event
);
3800 #endif // wxUSE_SCROLLBAR
3804 // ----------------------------------------------------------------------------
3805 // wxWin32CheckboxInputHandler
3806 // ----------------------------------------------------------------------------
3808 bool wxWin32CheckboxInputHandler
::HandleKey(wxInputConsumer
*control
,
3809 const wxKeyEvent
& event
,
3814 wxControlAction action
;
3815 int keycode
= event
.GetKeyCode();
3819 action
= wxACTION_CHECKBOX_TOGGLE
;
3823 case WXK_NUMPAD_SUBTRACT
:
3824 action
= wxACTION_CHECKBOX_CHECK
;
3828 case WXK_NUMPAD_ADD
:
3829 case WXK_NUMPAD_EQUAL
:
3830 action
= wxACTION_CHECKBOX_CLEAR
;
3834 if ( !action
.IsEmpty() )
3836 control
->PerformAction(action
);
3845 #endif // wxUSE_CHECKBOX
3849 // ----------------------------------------------------------------------------
3850 // wxWin32TextCtrlInputHandler
3851 // ----------------------------------------------------------------------------
3853 bool wxWin32TextCtrlInputHandler
::HandleKey(wxInputConsumer
*control
,
3854 const wxKeyEvent
& event
,
3857 // handle only MSW-specific text bindings here, the others are handled in
3861 int keycode
= event
.GetKeyCode();
3863 wxControlAction action
;
3864 if ( keycode
== WXK_DELETE
&& event
.ShiftDown() )
3866 action
= wxACTION_TEXT_CUT
;
3868 else if ( keycode
== WXK_INSERT
)
3870 if ( event
.ControlDown() )
3871 action
= wxACTION_TEXT_COPY
;
3872 else if ( event
.ShiftDown() )
3873 action
= wxACTION_TEXT_PASTE
;
3876 if ( action
!= wxACTION_NONE
)
3878 control
->PerformAction(action
);
3884 return wxStdInputHandler
::HandleKey(control
, event
, pressed
);
3887 #endif // wxUSE_TEXTCTRL
3891 // ----------------------------------------------------------------------------
3892 // wxWin32StatusBarInputHandler
3893 // ----------------------------------------------------------------------------
3895 wxWin32StatusBarInputHandler
::
3896 wxWin32StatusBarInputHandler(wxInputHandler
*handler
)
3897 : wxStdInputHandler(handler
)
3902 bool wxWin32StatusBarInputHandler
::IsOnGrip(wxWindow
*statbar
,
3903 const wxPoint
& pt
) const
3905 if ( statbar
->HasFlag(wxST_SIZEGRIP
) &&
3906 statbar
->GetParent()->HasFlag(wxRESIZE_BORDER
) )
3909 parentTLW
= wxDynamicCast(statbar
->GetParent(), wxTopLevelWindow
);
3911 wxCHECK_MSG( parentTLW
, false,
3912 _T("the status bar should be a child of a TLW") );
3914 // a maximized window can't be resized anyhow
3915 if ( !parentTLW
->IsMaximized() )
3917 // VZ: I think that the standard Windows behaviour is to only
3918 // show the resizing cursor when the mouse is on top of the
3919 // grip itself but apparently different Windows versions behave
3920 // differently (?) and it seems a better UI to allow resizing
3921 // the status bar even when the mouse is above the grip
3922 wxSize sizeSbar
= statbar
->GetSize();
3924 int diff
= sizeSbar
.x
- pt
.x
;
3925 return diff
>= 0 && diff
< (wxCoord
)STATUSBAR_GRIP_SIZE
;
3932 bool wxWin32StatusBarInputHandler
::HandleMouse(wxInputConsumer
*consumer
,
3933 const wxMouseEvent
& event
)
3935 if ( event
.Button(1) )
3937 if ( event
.ButtonDown(1) )
3939 wxWindow
*statbar
= consumer
->GetInputWindow();
3941 if ( IsOnGrip(statbar
, event
.GetPosition()) )
3943 wxTopLevelWindow
*tlw
= wxDynamicCast(statbar
->GetParent(),
3947 tlw
->PerformAction(wxACTION_TOPLEVEL_RESIZE
,
3948 wxHT_TOPLEVEL_BORDER_SE
);
3950 statbar
->SetCursor(m_cursorOld
);
3958 return wxStdInputHandler
::HandleMouse(consumer
, event
);
3961 bool wxWin32StatusBarInputHandler
::HandleMouseMove(wxInputConsumer
*consumer
,
3962 const wxMouseEvent
& event
)
3964 wxWindow
*statbar
= consumer
->GetInputWindow();
3966 bool isOnGrip
= IsOnGrip(statbar
, event
.GetPosition());
3967 if ( isOnGrip
!= m_isOnGrip
)
3969 m_isOnGrip
= isOnGrip
;
3972 m_cursorOld
= statbar
->GetCursor();
3973 statbar
->SetCursor(wxCURSOR_SIZENWSE
);
3977 statbar
->SetCursor(m_cursorOld
);
3981 return wxStdInputHandler
::HandleMouseMove(consumer
, event
);
3984 #endif // wxUSE_STATUSBAR
3986 // ----------------------------------------------------------------------------
3987 // wxWin32FrameInputHandler
3988 // ----------------------------------------------------------------------------
3990 class wxWin32SystemMenuEvtHandler
: public wxEvtHandler
3993 wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler
*handler
);
3995 void Attach(wxInputConsumer
*consumer
);
3999 DECLARE_EVENT_TABLE()
4000 void OnSystemMenu(wxCommandEvent
&event
);
4001 void OnCloseFrame(wxCommandEvent
&event
);
4002 void OnClose(wxCloseEvent
&event
);
4004 wxWin32FrameInputHandler
*m_inputHnd
;
4005 wxTopLevelWindow
*m_wnd
;
4007 wxAcceleratorTable m_oldAccelTable
;
4011 wxWin32SystemMenuEvtHandler
::
4012 wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler
*handler
)
4014 m_inputHnd
= handler
;
4018 void wxWin32SystemMenuEvtHandler
::Attach(wxInputConsumer
*consumer
)
4020 wxASSERT_MSG( m_wnd
== NULL
, _T("can't attach the handler twice!") );
4022 m_wnd
= wxStaticCast(consumer
->GetInputWindow(), wxTopLevelWindow
);
4023 m_wnd
->PushEventHandler(this);
4026 // VS: This code relies on using generic implementation of
4027 // wxAcceleratorTable in wxUniv!
4028 wxAcceleratorTable table
= *m_wnd
->GetAcceleratorTable();
4029 m_oldAccelTable
= table
;
4030 table
.Add(wxAcceleratorEntry(wxACCEL_ALT
, WXK_SPACE
, wxID_SYSTEM_MENU
));
4031 table
.Add(wxAcceleratorEntry(wxACCEL_ALT
, WXK_F4
, wxID_CLOSE_FRAME
));
4032 m_wnd
->SetAcceleratorTable(table
);
4036 void wxWin32SystemMenuEvtHandler
::Detach()
4041 m_wnd
->SetAcceleratorTable(m_oldAccelTable
);
4043 m_wnd
->RemoveEventHandler(this);
4048 BEGIN_EVENT_TABLE(wxWin32SystemMenuEvtHandler
, wxEvtHandler
)
4049 EVT_MENU(wxID_SYSTEM_MENU
, wxWin32SystemMenuEvtHandler
::OnSystemMenu
)
4050 EVT_MENU(wxID_CLOSE_FRAME
, wxWin32SystemMenuEvtHandler
::OnCloseFrame
)
4051 EVT_CLOSE(wxWin32SystemMenuEvtHandler
::OnClose
)
4054 void wxWin32SystemMenuEvtHandler
::OnSystemMenu(wxCommandEvent
&WXUNUSED(event
))
4056 int border
= ((m_wnd
->GetWindowStyle() & wxRESIZE_BORDER
) &&
4057 !m_wnd
->IsMaximized()) ?
4058 RESIZEABLE_FRAME_BORDER_THICKNESS
:
4059 FRAME_BORDER_THICKNESS
;
4060 wxPoint pt
= m_wnd
->GetClientAreaOrigin();
4061 pt
.x
= -pt
.x
+ border
;
4062 pt
.y
= -pt
.y
+ border
+ FRAME_TITLEBAR_HEIGHT
;
4065 wxAcceleratorTable table
= *m_wnd
->GetAcceleratorTable();
4066 m_wnd
->SetAcceleratorTable(wxNullAcceleratorTable
);
4070 m_inputHnd
->PopupSystemMenu(m_wnd
, pt
);
4071 #endif // wxUSE_MENUS
4074 m_wnd
->SetAcceleratorTable(table
);
4078 void wxWin32SystemMenuEvtHandler
::OnCloseFrame(wxCommandEvent
&WXUNUSED(event
))
4080 m_wnd
->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK
,
4081 wxTOPLEVEL_BUTTON_CLOSE
);
4084 void wxWin32SystemMenuEvtHandler
::OnClose(wxCloseEvent
&event
)
4091 wxWin32FrameInputHandler
::wxWin32FrameInputHandler(wxInputHandler
*handler
)
4092 : wxStdInputHandler(handler
)
4094 m_menuHandler
= new wxWin32SystemMenuEvtHandler(this);
4097 wxWin32FrameInputHandler
::~wxWin32FrameInputHandler()
4099 if ( m_menuHandler
)
4101 m_menuHandler
->Detach();
4102 delete m_menuHandler
;
4106 bool wxWin32FrameInputHandler
::HandleMouse(wxInputConsumer
*consumer
,
4107 const wxMouseEvent
& event
)
4109 if ( event
.LeftDClick() || event
.LeftDown() || event
.RightDown() )
4111 wxTopLevelWindow
*tlw
=
4112 wxStaticCast(consumer
->GetInputWindow(), wxTopLevelWindow
);
4114 long hit
= tlw
->HitTest(event
.GetPosition());
4116 if ( event
.LeftDClick() && hit
== wxHT_TOPLEVEL_TITLEBAR
)
4118 tlw
->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK
,
4119 tlw
->IsMaximized() ? wxTOPLEVEL_BUTTON_RESTORE
4120 : wxTOPLEVEL_BUTTON_MAXIMIZE
);
4123 else if ( tlw
->GetWindowStyle() & wxSYSTEM_MENU
)
4125 if ( (event
.LeftDown() && hit
== wxHT_TOPLEVEL_ICON
) ||
4126 (event
.RightDown() &&
4127 (hit
== wxHT_TOPLEVEL_TITLEBAR
||
4128 hit
== wxHT_TOPLEVEL_ICON
)) )
4131 PopupSystemMenu(tlw
, event
.GetPosition());
4132 #endif // wxUSE_MENUS
4138 return wxStdInputHandler
::HandleMouse(consumer
, event
);
4143 void wxWin32FrameInputHandler
::PopupSystemMenu(wxTopLevelWindow
*window
,
4144 const wxPoint
& pos
) const
4146 wxMenu
*menu
= new wxMenu
;
4148 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4149 menu
->Append(wxID_RESTORE_FRAME
, _("&Restore"));
4150 menu
->Append(wxID_MOVE_FRAME
, _("&Move"));
4151 if ( window
->GetWindowStyle() & wxRESIZE_BORDER
)
4152 menu
->Append(wxID_RESIZE_FRAME
, _("&Size"));
4153 if ( wxSystemSettings
::HasFeature(wxSYS_CAN_ICONIZE_FRAME
) )
4154 menu
->Append(wxID_ICONIZE_FRAME
, _("Mi&nimize"));
4155 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4156 menu
->Append(wxID_MAXIMIZE_FRAME
, _("Ma&ximize"));
4157 menu
->AppendSeparator();
4158 menu
->Append(wxID_CLOSE_FRAME
, _("Close\tAlt-F4"));
4160 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4162 if ( window
->IsMaximized() )
4164 menu
->Enable(wxID_MAXIMIZE_FRAME
, false);
4165 menu
->Enable(wxID_MOVE_FRAME
, false);
4166 if ( window
->GetWindowStyle() & wxRESIZE_BORDER
)
4167 menu
->Enable(wxID_RESIZE_FRAME
, false);
4170 menu
->Enable(wxID_RESTORE_FRAME
, false);
4173 window
->PopupMenu(menu
, pos
);
4177 #endif // wxUSE_MENUS
4179 bool wxWin32FrameInputHandler
::HandleActivation(wxInputConsumer
*consumer
,
4182 if ( consumer
->GetInputWindow()->GetWindowStyle() & wxSYSTEM_MENU
)
4184 // always detach if active frame changed:
4185 m_menuHandler
->Detach();
4189 m_menuHandler
->Attach(consumer
);
4193 return wxStdInputHandler
::HandleActivation(consumer
, activated
);