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"
41 #include "wx/toolbar.h"
44 // for COLOR_* constants
45 #include "wx/msw/private.h"
49 #include "wx/notebook.h"
50 #include "wx/spinbutt.h"
51 #include "wx/settings.h"
53 #include "wx/artprov.h"
54 #include "wx/toplevel.h"
56 #include "wx/univ/scrtimer.h"
57 #include "wx/univ/renderer.h"
58 #include "wx/univ/inphand.h"
59 #include "wx/univ/colschem.h"
60 #include "wx/univ/theme.h"
62 // ----------------------------------------------------------------------------
64 // ----------------------------------------------------------------------------
66 static const int BORDER_THICKNESS
= 2;
68 // the offset between the label and focus rect around it
69 static const int FOCUS_RECT_OFFSET_X
= 1;
70 static const int FOCUS_RECT_OFFSET_Y
= 1;
72 static const int FRAME_BORDER_THICKNESS
= 3;
73 static const int RESIZEABLE_FRAME_BORDER_THICKNESS
= 4;
74 static const int FRAME_TITLEBAR_HEIGHT
= 18;
75 static const int FRAME_BUTTON_WIDTH
= 16;
76 static const int FRAME_BUTTON_HEIGHT
= 14;
78 static const size_t NUM_STATUSBAR_GRIP_BANDS
= 3;
79 static const size_t WIDTH_STATUSBAR_GRIP_BAND
= 4;
80 static const size_t STATUSBAR_GRIP_SIZE
=
81 WIDTH_STATUSBAR_GRIP_BAND
*NUM_STATUSBAR_GRIP_BANDS
;
93 IndicatorState_Normal
,
94 IndicatorState_Pressed
, // this one is for check/radioboxes
95 IndicatorState_Selected
= IndicatorState_Pressed
, // for menus
96 IndicatorState_Disabled
,
97 IndicatorState_SelectedDisabled
, // only for the menus
103 IndicatorStatus_Checked
,
104 IndicatorStatus_Unchecked
,
108 // wxWin32Renderer: draw the GUI elements in Win32 style
109 // ----------------------------------------------------------------------------
111 class wxWin32Renderer
: public wxRenderer
115 enum wxArrowDirection
130 Arrow_InversedDisabled
,
134 enum wxFrameButtonType
137 FrameButton_Minimize
,
138 FrameButton_Maximize
,
145 wxWin32Renderer(const wxColourScheme
*scheme
);
147 // implement the base class pure virtuals
148 virtual void DrawBackground(wxDC
& dc
,
152 wxWindow
*window
= NULL
);
153 virtual void DrawLabel(wxDC
& dc
,
154 const wxString
& label
,
157 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
159 wxRect
*rectBounds
= NULL
);
160 virtual void DrawButtonLabel(wxDC
& dc
,
161 const wxString
& label
,
162 const wxBitmap
& image
,
165 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
167 wxRect
*rectBounds
= NULL
);
168 virtual void DrawBorder(wxDC
& dc
,
172 wxRect
*rectIn
= (wxRect
*)NULL
);
173 virtual void DrawHorizontalLine(wxDC
& dc
,
174 wxCoord y
, wxCoord x1
, wxCoord x2
);
175 virtual void DrawVerticalLine(wxDC
& dc
,
176 wxCoord x
, wxCoord y1
, wxCoord y2
);
177 virtual void DrawFrame(wxDC
& dc
,
178 const wxString
& label
,
181 int alignment
= wxALIGN_LEFT
,
182 int indexAccel
= -1);
183 virtual void DrawTextBorder(wxDC
& dc
,
187 wxRect
*rectIn
= (wxRect
*)NULL
);
188 virtual void DrawButtonBorder(wxDC
& dc
,
191 wxRect
*rectIn
= (wxRect
*)NULL
);
192 virtual void DrawArrow(wxDC
& dc
,
196 virtual void DrawScrollbarArrow(wxDC
& dc
,
200 { DrawArrow(dc
, dir
, rect
, flags
); }
201 virtual void DrawScrollbarThumb(wxDC
& dc
,
202 wxOrientation orient
,
205 virtual void DrawScrollbarShaft(wxDC
& dc
,
206 wxOrientation orient
,
209 virtual void DrawScrollCorner(wxDC
& dc
,
211 virtual void DrawItem(wxDC
& dc
,
212 const wxString
& label
,
215 virtual void DrawCheckItem(wxDC
& dc
,
216 const wxString
& label
,
217 const wxBitmap
& bitmap
,
220 virtual void DrawCheckButton(wxDC
& dc
,
221 const wxString
& label
,
222 const wxBitmap
& bitmap
,
225 wxAlignment align
= wxALIGN_LEFT
,
226 int indexAccel
= -1);
227 virtual void DrawRadioButton(wxDC
& dc
,
228 const wxString
& label
,
229 const wxBitmap
& bitmap
,
232 wxAlignment align
= wxALIGN_LEFT
,
233 int indexAccel
= -1);
234 virtual void DrawToolBarButton(wxDC
& dc
,
235 const wxString
& label
,
236 const wxBitmap
& bitmap
,
239 virtual void DrawTextLine(wxDC
& dc
,
240 const wxString
& text
,
245 virtual void DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
);
246 virtual void DrawTab(wxDC
& dc
,
249 const wxString
& label
,
250 const wxBitmap
& bitmap
= wxNullBitmap
,
252 int indexAccel
= -1);
254 virtual void DrawSliderShaft(wxDC
& dc
,
256 wxOrientation orient
,
258 wxRect
*rectShaft
= NULL
);
259 virtual void DrawSliderThumb(wxDC
& dc
,
261 wxOrientation orient
,
263 virtual void DrawSliderTicks(wxDC
& dc
,
265 const wxSize
& sizeThumb
,
266 wxOrientation orient
,
272 virtual void DrawMenuBarItem(wxDC
& dc
,
274 const wxString
& label
,
276 int indexAccel
= -1);
277 virtual void DrawMenuItem(wxDC
& dc
,
279 const wxMenuGeometryInfo
& geometryInfo
,
280 const wxString
& label
,
281 const wxString
& accel
,
282 const wxBitmap
& bitmap
= wxNullBitmap
,
284 int indexAccel
= -1);
285 virtual void DrawMenuSeparator(wxDC
& dc
,
287 const wxMenuGeometryInfo
& geomInfo
);
289 virtual void DrawStatusField(wxDC
& dc
,
291 const wxString
& label
,
295 virtual void DrawFrameTitleBar(wxDC
& dc
,
297 const wxString
& title
,
300 int specialButton
= 0,
301 int specialButtonFlags
= 0);
302 virtual void DrawFrameBorder(wxDC
& dc
,
305 virtual void DrawFrameBackground(wxDC
& dc
,
308 virtual void DrawFrameTitle(wxDC
& dc
,
310 const wxString
& title
,
312 virtual void DrawFrameIcon(wxDC
& dc
,
316 virtual void DrawFrameButton(wxDC
& dc
,
317 wxCoord x
, wxCoord y
,
320 virtual wxRect
GetFrameClientArea(const wxRect
& rect
, int flags
) const;
321 virtual wxSize
GetFrameTotalSize(const wxSize
& clientSize
, int flags
) const;
322 virtual wxSize
GetFrameMinSize(int flags
) const;
323 virtual wxSize
GetFrameIconSize() const;
324 virtual int HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const;
326 virtual void GetComboBitmaps(wxBitmap
*bmpNormal
,
328 wxBitmap
*bmpPressed
,
329 wxBitmap
*bmpDisabled
);
331 virtual void AdjustSize(wxSize
*size
, const wxWindow
*window
);
332 virtual wxRect
GetBorderDimensions(wxBorder border
) const;
333 virtual bool AreScrollbarsInsideBorder() const;
335 virtual wxSize
GetScrollbarArrowSize() const
336 { return m_sizeScrollbarArrow
; }
337 virtual wxRect
GetScrollbarRect(const wxScrollBar
*scrollbar
,
338 wxScrollBar
::Element elem
,
339 int thumbPos
= -1) const;
340 virtual wxCoord
GetScrollbarSize(const wxScrollBar
*scrollbar
);
341 virtual wxHitTest
HitTestScrollbar(const wxScrollBar
*scrollbar
,
342 const wxPoint
& pt
) const;
343 virtual wxCoord
ScrollbarToPixel(const wxScrollBar
*scrollbar
,
345 virtual int PixelToScrollbar(const wxScrollBar
*scrollbar
, wxCoord coord
);
346 virtual wxCoord
GetListboxItemHeight(wxCoord fontHeight
)
347 { return fontHeight
+ 2; }
348 virtual wxSize
GetCheckBitmapSize() const
349 { return wxSize(13, 13); }
350 virtual wxSize
GetRadioBitmapSize() const
351 { return wxSize(12, 12); }
352 virtual wxCoord
GetCheckItemMargin() const
355 virtual wxSize
GetToolBarButtonSize(wxCoord
*separator
) const
356 { if ( separator
) *separator
= 5; return wxSize(16, 15); }
357 virtual wxSize
GetToolBarMargin() const
358 { return wxSize(4, 4); }
360 virtual wxRect
GetTextTotalArea(const wxTextCtrl
*text
,
361 const wxRect
& rect
) const;
362 virtual wxRect
GetTextClientArea(const wxTextCtrl
*text
,
364 wxCoord
*extraSpaceBeyond
) const;
366 virtual wxSize
GetTabIndent() const { return wxSize(2, 2); }
367 virtual wxSize
GetTabPadding() const { return wxSize(6, 5); }
369 virtual wxCoord
GetSliderDim() const { return 20; }
370 virtual wxCoord
GetSliderTickLen() const { return 4; }
371 virtual wxRect
GetSliderShaftRect(const wxRect
& rect
,
372 wxOrientation orient
) const;
373 virtual wxSize
GetSliderThumbSize(const wxRect
& rect
,
374 wxOrientation orient
) const;
375 virtual wxSize
GetProgressBarStep() const { return wxSize(16, 32); }
377 virtual wxSize
GetMenuBarItemSize(const wxSize
& sizeText
) const;
378 virtual wxMenuGeometryInfo
*GetMenuGeometry(wxWindow
*win
,
379 const wxMenu
& menu
) const;
381 virtual wxSize
GetStatusBarBorders(wxCoord
*borderBetweenFields
) const;
384 // helper of DrawLabel() and DrawCheckOrRadioButton()
385 void DoDrawLabel(wxDC
& dc
,
386 const wxString
& label
,
389 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
391 wxRect
*rectBounds
= NULL
,
392 const wxPoint
& focusOffset
393 = wxPoint(FOCUS_RECT_OFFSET_X
, FOCUS_RECT_OFFSET_Y
));
395 // common part of DrawLabel() and DrawItem()
396 void DrawFocusRect(wxDC
& dc
, const wxRect
& rect
);
398 // DrawLabel() and DrawButtonLabel() helper
399 void DrawLabelShadow(wxDC
& dc
,
400 const wxString
& label
,
405 // DrawButtonBorder() helper
406 void DoDrawBackground(wxDC
& dc
,
409 wxWindow
*window
= NULL
);
411 // DrawBorder() helpers: all of them shift and clip the DC after drawing
414 // just draw a rectangle with the given pen
415 void DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
417 // draw the lower left part of rectangle
418 void DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
420 // draw the rectange using the first brush for the left and top sides and
421 // the second one for the bottom and right ones
422 void DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
423 const wxPen
& pen1
, const wxPen
& pen2
);
425 // draw the normal 3D border
426 void DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
);
428 // draw the sunken 3D border
429 void DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
);
431 // draw the border used for scrollbar arrows
432 void DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
= FALSE
);
434 // public DrawArrow()s helper
435 void DrawArrow(wxDC
& dc
, const wxRect
& rect
,
436 wxArrowDirection arrowDir
, wxArrowStyle arrowStyle
);
438 // DrawArrowButton is used by DrawScrollbar and DrawComboButton
439 void DrawArrowButton(wxDC
& dc
, const wxRect
& rect
,
440 wxArrowDirection arrowDir
,
441 wxArrowStyle arrowStyle
);
443 // DrawCheckButton/DrawRadioButton helper
444 void DrawCheckOrRadioButton(wxDC
& dc
,
445 const wxString
& label
,
446 const wxBitmap
& bitmap
,
451 wxCoord focusOffsetY
);
453 // draw a normal or transposed line (useful for using the same code fo both
454 // horizontal and vertical widgets)
455 void DrawLine(wxDC
& dc
,
456 wxCoord x1
, wxCoord y1
,
457 wxCoord x2
, wxCoord y2
,
458 bool transpose
= FALSE
)
461 dc
.DrawLine(y1
, x1
, y2
, x2
);
463 dc
.DrawLine(x1
, y1
, x2
, y2
);
466 // get the standard check/radio button bitmap
467 wxBitmap
GetIndicator(IndicatorType indType
, int flags
);
468 wxBitmap
GetCheckBitmap(int flags
)
469 { return GetIndicator(IndicatorType_Check
, flags
); }
470 wxBitmap
GetRadioBitmap(int flags
)
471 { return GetIndicator(IndicatorType_Radio
, flags
); }
474 const wxColourScheme
*m_scheme
;
476 // the sizing parameters (TODO make them changeable)
477 wxSize m_sizeScrollbarArrow
;
479 // GDI objects we use for drawing
480 wxColour m_colDarkGrey
,
488 wxFont m_titlebarFont
;
490 // the checked and unchecked bitmaps for DrawCheckItem()
491 wxBitmap m_bmpCheckBitmaps
[IndicatorStatus_Max
];
493 // the bitmaps returned by GetIndicator()
494 wxBitmap m_bmpIndicators
[IndicatorType_Max
]
496 [IndicatorStatus_Max
];
499 wxBitmap m_bmpFrameButtons
[FrameButton_Max
];
501 // first row is for the normal state, second - for the disabled
502 wxBitmap m_bmpArrows
[Arrow_StateMax
][Arrow_Max
];
505 // ----------------------------------------------------------------------------
506 // wxWin32InputHandler and derived classes: process the keyboard and mouse
507 // messages according to Windows standards
508 // ----------------------------------------------------------------------------
510 class wxWin32InputHandler
: public wxInputHandler
513 wxWin32InputHandler(wxWin32Renderer
*renderer
);
515 virtual bool HandleKey(wxInputConsumer
*control
,
516 const wxKeyEvent
& event
,
518 virtual bool HandleMouse(wxInputConsumer
*control
,
519 const wxMouseEvent
& event
);
522 wxWin32Renderer
*m_renderer
;
525 class wxWin32ScrollBarInputHandler
: public wxStdScrollBarInputHandler
528 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
529 wxInputHandler
*handler
);
531 virtual bool HandleMouse(wxInputConsumer
*control
, const wxMouseEvent
& event
);
532 virtual bool HandleMouseMove(wxInputConsumer
*control
, const wxMouseEvent
& event
);
534 virtual bool OnScrollTimer(wxScrollBar
*scrollbar
,
535 const wxControlAction
& action
);
538 virtual bool IsAllowedButton(int button
) { return button
== 1; }
540 virtual void Highlight(wxScrollBar
*scrollbar
, bool doIt
)
542 // we don't highlight anything
545 // the first and last event which caused the thumb to move
546 wxMouseEvent m_eventStartDrag
,
549 // have we paused the scrolling because the mouse moved?
552 // we remember the interval of the timer to be able to restart it
556 class wxWin32CheckboxInputHandler
: public wxStdCheckboxInputHandler
559 wxWin32CheckboxInputHandler(wxInputHandler
*handler
)
560 : wxStdCheckboxInputHandler(handler
) { }
562 virtual bool HandleKey(wxInputConsumer
*control
,
563 const wxKeyEvent
& event
,
567 class wxWin32TextCtrlInputHandler
: public wxStdTextCtrlInputHandler
570 wxWin32TextCtrlInputHandler(wxInputHandler
*handler
)
571 : wxStdTextCtrlInputHandler(handler
) { }
573 virtual bool HandleKey(wxInputConsumer
*control
,
574 const wxKeyEvent
& event
,
578 class wxWin32StatusBarInputHandler
: public wxStdInputHandler
581 wxWin32StatusBarInputHandler(wxInputHandler
*handler
);
583 virtual bool HandleMouse(wxInputConsumer
*consumer
,
584 const wxMouseEvent
& event
);
586 virtual bool HandleMouseMove(wxInputConsumer
*consumer
,
587 const wxMouseEvent
& event
);
590 // is the given point over the statusbar grip?
591 bool IsOnGrip(wxWindow
*statbar
, const wxPoint
& pt
) const;
594 // the cursor we had replaced with the resize one
595 wxCursor m_cursorOld
;
597 // was the mouse over the grip last time we checked?
601 class wxWin32SystemMenuEvtHandler
;
603 class wxWin32FrameInputHandler
: public wxStdFrameInputHandler
606 wxWin32FrameInputHandler(wxInputHandler
*handler
);
607 ~wxWin32FrameInputHandler();
609 virtual bool HandleMouse(wxInputConsumer
*control
,
610 const wxMouseEvent
& event
);
612 virtual bool HandleActivation(wxInputConsumer
*consumer
, bool activated
);
614 void PopupSystemMenu(wxTopLevelWindow
*window
, const wxPoint
& pos
) const;
617 // was the mouse over the grip last time we checked?
618 wxWin32SystemMenuEvtHandler
*m_menuHandler
;
621 // ----------------------------------------------------------------------------
622 // wxWin32ColourScheme: uses (default) Win32 colours
623 // ----------------------------------------------------------------------------
625 class wxWin32ColourScheme
: public wxColourScheme
628 virtual wxColour
Get(StdColour col
) const;
629 virtual wxColour
GetBackground(wxWindow
*win
) const;
632 // ----------------------------------------------------------------------------
633 // wxWin32ArtProvider
634 // ----------------------------------------------------------------------------
636 class wxWin32ArtProvider
: public wxArtProvider
639 virtual wxBitmap
CreateBitmap(const wxArtID
& id
,
640 const wxArtClient
& client
,
644 // ----------------------------------------------------------------------------
646 // ----------------------------------------------------------------------------
648 WX_DEFINE_ARRAY(wxInputHandler
*, wxArrayHandlers
);
650 class wxWin32Theme
: public wxTheme
654 virtual ~wxWin32Theme();
656 virtual wxRenderer
*GetRenderer();
657 virtual wxArtProvider
*GetArtProvider();
658 virtual wxInputHandler
*GetInputHandler(const wxString
& control
);
659 virtual wxColourScheme
*GetColourScheme();
662 // get the default input handler
663 wxInputHandler
*GetDefaultInputHandler();
665 wxWin32Renderer
*m_renderer
;
667 wxWin32ArtProvider
*m_artProvider
;
669 // the names of the already created handlers and the handlers themselves
670 // (these arrays are synchronized)
671 wxSortedArrayString m_handlerNames
;
672 wxArrayHandlers m_handlers
;
674 wxWin32InputHandler
*m_handlerDefault
;
676 wxWin32ColourScheme
*m_scheme
;
678 WX_DECLARE_THEME(win32
)
681 // ----------------------------------------------------------------------------
683 // ----------------------------------------------------------------------------
685 // frame buttons bitmaps
687 static const char *frame_button_close_xpm
[] = {
702 static const char *frame_button_help_xpm
[] = {
717 static const char *frame_button_maximize_xpm
[] = {
732 static const char *frame_button_minimize_xpm
[] = {
747 static const char *frame_button_restore_xpm
[] = {
764 static const char *checked_menu_xpm
[] = {
765 /* columns rows colors chars-per-pixel */
781 static const char *selected_checked_menu_xpm
[] = {
782 /* columns rows colors chars-per-pixel */
798 static const char *disabled_checked_menu_xpm
[] = {
799 /* columns rows colors chars-per-pixel */
816 static const char *selected_disabled_checked_menu_xpm
[] = {
817 /* columns rows colors chars-per-pixel */
833 // checkbox and radiobox bitmaps below
835 static const char *checked_xpm
[] = {
836 /* columns rows colors chars-per-pixel */
859 static const char *pressed_checked_xpm
[] = {
860 /* columns rows colors chars-per-pixel */
882 static const char *pressed_disabled_checked_xpm
[] = {
883 /* columns rows colors chars-per-pixel */
905 static const char *checked_item_xpm
[] = {
906 /* columns rows colors chars-per-pixel */
927 static const char *unchecked_xpm
[] = {
928 /* columns rows colors chars-per-pixel */
951 static const char *pressed_unchecked_xpm
[] = {
952 /* columns rows colors chars-per-pixel */
974 static const char *unchecked_item_xpm
[] = {
975 /* columns rows colors chars-per-pixel */
995 static const char *checked_radio_xpm
[] = {
996 /* columns rows colors chars-per-pixel */
1019 static const char *pressed_checked_radio_xpm
[] = {
1020 /* columns rows colors chars-per-pixel */
1043 static const char *pressed_disabled_checked_radio_xpm
[] = {
1044 /* columns rows colors chars-per-pixel */
1067 static const char *unchecked_radio_xpm
[] = {
1068 /* columns rows colors chars-per-pixel */
1091 static const char *pressed_unchecked_radio_xpm
[] = {
1092 /* columns rows colors chars-per-pixel */
1115 static const char **
1116 xpmIndicators
[IndicatorType_Max
][IndicatorState_Max
][IndicatorStatus_Max
] =
1121 { checked_xpm
, unchecked_xpm
},
1124 { pressed_checked_xpm
, pressed_unchecked_xpm
},
1127 { pressed_disabled_checked_xpm
, pressed_unchecked_xpm
},
1133 { checked_radio_xpm
, unchecked_radio_xpm
},
1136 { pressed_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
1139 { pressed_disabled_checked_radio_xpm
, pressed_unchecked_radio_xpm
},
1145 { checked_menu_xpm
, NULL
},
1148 { selected_checked_menu_xpm
, NULL
},
1151 { disabled_checked_menu_xpm
, NULL
},
1153 // disabled selected state
1154 { selected_disabled_checked_menu_xpm
, NULL
},
1158 static const char **xpmChecked
[IndicatorStatus_Max
] =
1164 // ============================================================================
1166 // ============================================================================
1168 WX_IMPLEMENT_THEME(wxWin32Theme
, win32
, wxTRANSLATE("Win32 theme"));
1170 // ----------------------------------------------------------------------------
1172 // ----------------------------------------------------------------------------
1174 wxWin32Theme
::wxWin32Theme()
1178 m_handlerDefault
= NULL
;
1179 m_artProvider
= NULL
;
1182 wxWin32Theme
::~wxWin32Theme()
1184 size_t count
= m_handlers
.GetCount();
1185 for ( size_t n
= 0; n
< count
; n
++ )
1187 if ( m_handlers
[n
] != m_handlerDefault
)
1188 delete m_handlers
[n
];
1191 delete m_handlerDefault
;
1195 wxArtProvider
::RemoveProvider(m_artProvider
);
1198 wxRenderer
*wxWin32Theme
::GetRenderer()
1202 m_renderer
= new wxWin32Renderer(GetColourScheme());
1208 wxArtProvider
*wxWin32Theme
::GetArtProvider()
1210 if ( !m_artProvider
)
1212 m_artProvider
= new wxWin32ArtProvider
;
1215 return m_artProvider
;
1218 wxInputHandler
*wxWin32Theme
::GetDefaultInputHandler()
1220 if ( !m_handlerDefault
)
1222 m_handlerDefault
= new wxWin32InputHandler(m_renderer
);
1225 return m_handlerDefault
;
1228 wxInputHandler
*wxWin32Theme
::GetInputHandler(const wxString
& control
)
1230 wxInputHandler
*handler
;
1231 int n
= m_handlerNames
.Index(control
);
1232 if ( n
== wxNOT_FOUND
)
1234 // create a new handler
1235 if ( control
== wxINP_HANDLER_SCROLLBAR
)
1236 handler
= new wxWin32ScrollBarInputHandler(m_renderer
,
1237 GetDefaultInputHandler());
1239 else if ( control
== wxINP_HANDLER_BUTTON
)
1240 handler
= new wxStdButtonInputHandler(GetDefaultInputHandler());
1241 #endif // wxUSE_BUTTON
1243 else if ( control
== wxINP_HANDLER_CHECKBOX
)
1244 handler
= new wxWin32CheckboxInputHandler(GetDefaultInputHandler());
1245 #endif // wxUSE_CHECKBOX
1247 else if ( control
== wxINP_HANDLER_COMBOBOX
)
1248 handler
= new wxStdComboBoxInputHandler(GetDefaultInputHandler());
1249 #endif // wxUSE_COMBOBOX
1251 else if ( control
== wxINP_HANDLER_LISTBOX
)
1252 handler
= new wxStdListboxInputHandler(GetDefaultInputHandler());
1253 #endif // wxUSE_LISTBOX
1254 #if wxUSE_CHECKLISTBOX
1255 else if ( control
== wxINP_HANDLER_CHECKLISTBOX
)
1256 handler
= new wxStdCheckListboxInputHandler(GetDefaultInputHandler());
1257 #endif // wxUSE_CHECKLISTBOX
1259 else if ( control
== wxINP_HANDLER_TEXTCTRL
)
1260 handler
= new wxWin32TextCtrlInputHandler(GetDefaultInputHandler());
1261 #endif // wxUSE_TEXTCTRL
1263 else if ( control
== wxINP_HANDLER_SLIDER
)
1264 handler
= new wxStdSliderButtonInputHandler(GetDefaultInputHandler());
1265 #endif // wxUSE_SLIDER
1267 else if ( control
== wxINP_HANDLER_SPINBTN
)
1268 handler
= new wxStdSpinButtonInputHandler(GetDefaultInputHandler());
1269 #endif // wxUSE_SPINBTN
1271 else if ( control
== wxINP_HANDLER_NOTEBOOK
)
1272 handler
= new wxStdNotebookInputHandler(GetDefaultInputHandler());
1273 #endif // wxUSE_NOTEBOOK
1275 else if ( control
== wxINP_HANDLER_STATUSBAR
)
1276 handler
= new wxWin32StatusBarInputHandler(GetDefaultInputHandler());
1277 #endif // wxUSE_STATUSBAR
1279 else if ( control
== wxINP_HANDLER_TOOLBAR
)
1280 handler
= new wxStdToolbarInputHandler(GetDefaultInputHandler());
1281 #endif // wxUSE_TOOLBAR
1282 else if ( control
== wxINP_HANDLER_TOPLEVEL
)
1283 handler
= new wxWin32FrameInputHandler(GetDefaultInputHandler());
1285 handler
= GetDefaultInputHandler();
1287 n
= m_handlerNames
.Add(control
);
1288 m_handlers
.Insert(handler
, n
);
1290 else // we already have it
1292 handler
= m_handlers
[n
];
1298 wxColourScheme
*wxWin32Theme
::GetColourScheme()
1302 m_scheme
= new wxWin32ColourScheme
;
1307 // ============================================================================
1308 // wxWin32ColourScheme
1309 // ============================================================================
1311 wxColour wxWin32ColourScheme
::GetBackground(wxWindow
*win
) const
1314 if ( win
->UseBgCol() )
1316 // use the user specified colour
1317 col
= win
->GetBackgroundColour();
1320 if ( win
->IsContainerWindow() )
1322 wxTextCtrl
*text
= wxDynamicCast(win
, wxTextCtrl
);
1325 if ( !text
->IsEnabled() ) // not IsEditable()
1327 //else: execute code below
1332 // doesn't depend on the state
1338 int flags
= win
->GetStateFlags();
1340 // the colour set by the user should be used for the normal state
1341 // and for the states for which we don't have any specific colours
1342 if ( !col
.Ok() || (flags
& wxCONTROL_PRESSED
) != 0 )
1344 if ( wxDynamicCast(win
, wxScrollBar
) )
1345 col
= Get(flags
& wxCONTROL_PRESSED ? SCROLLBAR_PRESSED
1355 wxColour wxWin32ColourScheme
::Get(wxWin32ColourScheme
::StdColour col
) const
1359 // use the system colours under Windows
1360 #if defined(__WXMSW__)
1361 case WINDOW
: return wxColour(GetSysColor(COLOR_WINDOW
));
1363 case CONTROL_PRESSED
:
1364 case CONTROL_CURRENT
:
1365 case CONTROL
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1367 case CONTROL_TEXT
: return wxColour(GetSysColor(COLOR_BTNTEXT
));
1369 #if defined(COLOR_3DLIGHT)
1370 case SCROLLBAR
: return wxColour(GetSysColor(COLOR_3DLIGHT
));
1372 case SCROLLBAR
: return wxColour(0xe0e0e0);
1374 case SCROLLBAR_PRESSED
: return wxColour(GetSysColor(COLOR_BTNTEXT
));
1376 case HIGHLIGHT
: return wxColour(GetSysColor(COLOR_HIGHLIGHT
));
1377 case HIGHLIGHT_TEXT
: return wxColour(GetSysColor(COLOR_HIGHLIGHTTEXT
));
1379 #if defined(COLOR_3DDKSHADOW)
1380 case SHADOW_DARK
: return wxColour(GetSysColor(COLOR_3DDKSHADOW
));
1382 case SHADOW_DARK
: return wxColour(GetSysColor(COLOR_3DHADOW
));
1385 case CONTROL_TEXT_DISABLED
:
1386 case SHADOW_HIGHLIGHT
: return wxColour(GetSysColor(COLOR_BTNHIGHLIGHT
));
1388 case SHADOW_IN
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1390 case CONTROL_TEXT_DISABLED_SHADOW
:
1391 case SHADOW_OUT
: return wxColour(GetSysColor(COLOR_BTNSHADOW
));
1393 case TITLEBAR
: return wxColour(GetSysColor(COLOR_INACTIVECAPTION
));
1394 case TITLEBAR_ACTIVE
: return wxColour(GetSysColor(COLOR_ACTIVECAPTION
));
1395 case TITLEBAR_TEXT
: return wxColour(GetSysColor(COLOR_INACTIVECAPTIONTEXT
));
1396 case TITLEBAR_ACTIVE_TEXT
: return wxColour(GetSysColor(COLOR_CAPTIONTEXT
));
1398 case DESKTOP
: return wxColour(0x808000);
1400 // use the standard Windows colours elsewhere
1401 case WINDOW
: return *wxWHITE
;
1403 case CONTROL_PRESSED
:
1404 case CONTROL_CURRENT
:
1405 case CONTROL
: return wxColour(0xc0c0c0);
1407 case CONTROL_TEXT
: return *wxBLACK
;
1409 case SCROLLBAR
: return wxColour(0xe0e0e0);
1410 case SCROLLBAR_PRESSED
: return *wxBLACK
;
1412 case HIGHLIGHT
: return wxColour(0x800000);
1413 case HIGHLIGHT_TEXT
: return wxColour(0xffffff);
1415 case SHADOW_DARK
: return *wxBLACK
;
1417 case CONTROL_TEXT_DISABLED
:return wxColour(0xe0e0e0);
1418 case SHADOW_HIGHLIGHT
: return wxColour(0xffffff);
1420 case SHADOW_IN
: return wxColour(0xc0c0c0);
1422 case CONTROL_TEXT_DISABLED_SHADOW
:
1423 case SHADOW_OUT
: return wxColour(0x7f7f7f);
1425 case TITLEBAR
: return wxColour(0xaeaaae);
1426 case TITLEBAR_ACTIVE
: return wxColour(0x820300);
1427 case TITLEBAR_TEXT
: return wxColour(0xc0c0c0);
1428 case TITLEBAR_ACTIVE_TEXT
:return *wxWHITE
;
1430 case DESKTOP
: return wxColour(0x808000);
1433 case GAUGE
: return Get(HIGHLIGHT
);
1437 wxFAIL_MSG(_T("invalid standard colour"));
1442 // ============================================================================
1444 // ============================================================================
1446 // ----------------------------------------------------------------------------
1448 // ----------------------------------------------------------------------------
1450 wxWin32Renderer
::wxWin32Renderer(const wxColourScheme
*scheme
)
1454 m_sizeScrollbarArrow
= wxSize(16, 16);
1456 // init colours and pens
1457 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
), 0, wxSOLID
);
1459 m_colDarkGrey
= wxSCHEME_COLOUR(scheme
, SHADOW_OUT
);
1460 m_penDarkGrey
= wxPen(m_colDarkGrey
, 0, wxSOLID
);
1462 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
), 0, wxSOLID
);
1464 m_colHighlight
= wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
);
1465 m_penHighlight
= wxPen(m_colHighlight
, 0, wxSOLID
);
1467 m_titlebarFont
= wxSystemSettings
::GetFont(wxSYS_DEFAULT_GUI_FONT
);
1468 m_titlebarFont
.SetWeight(wxFONTWEIGHT_BOLD
);
1470 // init the arrow bitmaps
1471 static const size_t ARROW_WIDTH
= 7;
1472 static const size_t ARROW_LENGTH
= 4;
1475 wxMemoryDC dcNormal
,
1478 for ( size_t n
= 0; n
< Arrow_Max
; n
++ )
1480 bool isVertical
= n
> Arrow_Right
;
1493 // disabled arrow is larger because of the shadow
1494 m_bmpArrows
[Arrow_Normal
][n
].Create(w
, h
);
1495 m_bmpArrows
[Arrow_Disabled
][n
].Create(w
+ 1, h
+ 1);
1497 dcNormal
.SelectObject(m_bmpArrows
[Arrow_Normal
][n
]);
1498 dcDisabled
.SelectObject(m_bmpArrows
[Arrow_Disabled
][n
]);
1500 dcNormal
.SetBackground(*wxWHITE_BRUSH
);
1501 dcDisabled
.SetBackground(*wxWHITE_BRUSH
);
1505 dcNormal
.SetPen(m_penBlack
);
1506 dcDisabled
.SetPen(m_penDarkGrey
);
1508 // calculate the position of the point of the arrow
1512 x1
= (ARROW_WIDTH
- 1)/2;
1513 y1
= n
== Arrow_Up ?
0 : ARROW_LENGTH
- 1;
1517 x1
= n
== Arrow_Left ?
0 : ARROW_LENGTH
- 1;
1518 y1
= (ARROW_WIDTH
- 1)/2;
1529 for ( size_t i
= 0; i
< ARROW_LENGTH
; i
++ )
1531 dcNormal
.DrawLine(x1
, y1
, x2
, y2
);
1532 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1539 if ( n
== Arrow_Up
)
1550 else // left or right arrow
1555 if ( n
== Arrow_Left
)
1568 // draw the shadow for the disabled one
1569 dcDisabled
.SetPen(m_penHighlight
);
1574 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1578 x1
= ARROW_LENGTH
- 1;
1579 y1
= (ARROW_WIDTH
- 1)/2 + 1;
1582 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1583 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1588 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1592 x1
= ARROW_WIDTH
- 1;
1594 x2
= (ARROW_WIDTH
- 1)/2;
1596 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1597 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1602 // create the inversed bitmap but only for the right arrow as we only
1603 // use it for the menus
1604 if ( n
== Arrow_Right
)
1606 m_bmpArrows
[Arrow_Inversed
][n
].Create(w
, h
);
1607 dcInverse
.SelectObject(m_bmpArrows
[Arrow_Inversed
][n
]);
1609 dcInverse
.Blit(0, 0, w
, h
,
1612 dcInverse
.SelectObject(wxNullBitmap
);
1614 mask
= new wxMask(m_bmpArrows
[Arrow_Inversed
][n
], *wxBLACK
);
1615 m_bmpArrows
[Arrow_Inversed
][n
].SetMask(mask
);
1617 m_bmpArrows
[Arrow_InversedDisabled
][n
].Create(w
, h
);
1618 dcInverse
.SelectObject(m_bmpArrows
[Arrow_InversedDisabled
][n
]);
1620 dcInverse
.Blit(0, 0, w
, h
,
1623 dcInverse
.SelectObject(wxNullBitmap
);
1625 mask
= new wxMask(m_bmpArrows
[Arrow_InversedDisabled
][n
], *wxBLACK
);
1626 m_bmpArrows
[Arrow_InversedDisabled
][n
].SetMask(mask
);
1629 dcNormal
.SelectObject(wxNullBitmap
);
1630 dcDisabled
.SelectObject(wxNullBitmap
);
1632 mask
= new wxMask(m_bmpArrows
[Arrow_Normal
][n
], *wxWHITE
);
1633 m_bmpArrows
[Arrow_Normal
][n
].SetMask(mask
);
1634 mask
= new wxMask(m_bmpArrows
[Arrow_Disabled
][n
], *wxWHITE
);
1635 m_bmpArrows
[Arrow_Disabled
][n
].SetMask(mask
);
1637 m_bmpArrows
[Arrow_Pressed
][n
] = m_bmpArrows
[Arrow_Normal
][n
];
1640 // init the frame buttons bitmaps
1641 m_bmpFrameButtons
[FrameButton_Close
] = wxBitmap(frame_button_close_xpm
);
1642 m_bmpFrameButtons
[FrameButton_Minimize
] = wxBitmap(frame_button_minimize_xpm
);
1643 m_bmpFrameButtons
[FrameButton_Maximize
] = wxBitmap(frame_button_maximize_xpm
);
1644 m_bmpFrameButtons
[FrameButton_Restore
] = wxBitmap(frame_button_restore_xpm
);
1645 m_bmpFrameButtons
[FrameButton_Help
] = wxBitmap(frame_button_help_xpm
);
1648 // ----------------------------------------------------------------------------
1650 // ----------------------------------------------------------------------------
1653 The raised border in Win32 looks like this:
1655 IIIIIIIIIIIIIIIIIIIIIIB
1657 I GB I = white (HILIGHT)
1658 I GB H = light grey (LIGHT)
1659 I GB G = dark grey (SHADOI)
1660 I GB B = black (DKSHADOI)
1661 I GB I = hIghlight (COLOR_3DHILIGHT)
1663 IGGGGGGGGGGGGGGGGGGGGGB
1664 BBBBBBBBBBBBBBBBBBBBBBB
1666 The sunken border looks like this:
1668 GGGGGGGGGGGGGGGGGGGGGGI
1669 GBBBBBBBBBBBBBBBBBBBBHI
1676 GHHHHHHHHHHHHHHHHHHHHHI
1677 IIIIIIIIIIIIIIIIIIIIIII
1679 The static border (used for the controls which don't get focus) is like
1682 GGGGGGGGGGGGGGGGGGGGGGW
1690 WWWWWWWWWWWWWWWWWWWWWWW
1692 The most complicated is the double border:
1694 HHHHHHHHHHHHHHHHHHHHHHB
1695 HWWWWWWWWWWWWWWWWWWWWGB
1696 HWHHHHHHHHHHHHHHHHHHHGB
1701 HWHHHHHHHHHHHHHHHHHHHGB
1702 HGGGGGGGGGGGGGGGGGGGGGB
1703 BBBBBBBBBBBBBBBBBBBBBBB
1705 And the simple border is, well, simple:
1707 BBBBBBBBBBBBBBBBBBBBBBB
1716 BBBBBBBBBBBBBBBBBBBBBBB
1719 void wxWin32Renderer
::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1723 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1724 dc
.DrawRectangle(*rect
);
1730 void wxWin32Renderer
::DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1732 // draw the bottom and right sides
1734 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1735 rect
->GetRight() + 1, rect
->GetBottom());
1736 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1737 rect
->GetRight(), rect
->GetBottom());
1744 void wxWin32Renderer
::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
1745 const wxPen
& pen1
, const wxPen
& pen2
)
1747 // draw the rectangle
1749 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
1750 rect
->GetLeft(), rect
->GetBottom());
1751 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
1752 rect
->GetRight(), rect
->GetTop());
1754 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1755 rect
->GetRight(), rect
->GetBottom());
1756 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1757 rect
->GetRight() + 1, rect
->GetBottom());
1763 void wxWin32Renderer
::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
1765 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
1766 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
1769 void wxWin32Renderer
::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
1771 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
1772 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
1775 void wxWin32Renderer
::DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
)
1779 DrawRect(dc
, rect
, m_penDarkGrey
);
1781 // the arrow is usually drawn inside border of width 2 and is offset by
1782 // another pixel in both directions when it's pressed - as the border
1783 // in this case is more narrow as well, we have to adjust rect like
1791 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
1792 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
1796 void wxWin32Renderer
::DrawBorder(wxDC
& dc
,
1798 const wxRect
& rectTotal
,
1799 int WXUNUSED(flags
),
1804 wxRect rect
= rectTotal
;
1808 case wxBORDER_SUNKEN
:
1809 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1811 DrawSunkenBorder(dc
, &rect
);
1815 case wxBORDER_STATIC
:
1816 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1819 case wxBORDER_RAISED
:
1820 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1822 DrawRaisedBorder(dc
, &rect
);
1826 case wxBORDER_DOUBLE
:
1827 DrawArrowBorder(dc
, &rect
);
1828 DrawRect(dc
, &rect
, m_penLightGrey
);
1831 case wxBORDER_SIMPLE
:
1832 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1834 DrawRect(dc
, &rect
, m_penBlack
);
1839 wxFAIL_MSG(_T("unknown border type"));
1842 case wxBORDER_DEFAULT
:
1851 wxRect wxWin32Renderer
::GetBorderDimensions(wxBorder border
) const
1856 case wxBORDER_RAISED
:
1857 case wxBORDER_SUNKEN
:
1858 width
= BORDER_THICKNESS
;
1861 case wxBORDER_SIMPLE
:
1862 case wxBORDER_STATIC
:
1866 case wxBORDER_DOUBLE
:
1872 // char *crash = NULL;
1874 wxFAIL_MSG(_T("unknown border type"));
1878 case wxBORDER_DEFAULT
:
1888 rect
.height
= width
;
1893 bool wxWin32Renderer
::AreScrollbarsInsideBorder() const
1898 // ----------------------------------------------------------------------------
1900 // ----------------------------------------------------------------------------
1902 void wxWin32Renderer
::DrawTextBorder(wxDC
& dc
,
1908 // text controls are not special under windows
1909 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
1912 void wxWin32Renderer
::DrawButtonBorder(wxDC
& dc
,
1913 const wxRect
& rectTotal
,
1917 wxRect rect
= rectTotal
;
1919 if ( flags
& wxCONTROL_PRESSED
)
1921 // button pressed: draw a double border around it
1922 DrawRect(dc
, &rect
, m_penBlack
);
1923 DrawRect(dc
, &rect
, m_penDarkGrey
);
1927 // button not pressed
1929 if ( flags
& (wxCONTROL_FOCUSED
| wxCONTROL_ISDEFAULT
) )
1931 // button either default or focused (or both): add an extra border around it
1932 DrawRect(dc
, &rect
, m_penBlack
);
1935 // now draw a normal button
1936 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penBlack
);
1937 DrawHalfRect(dc
, &rect
, m_penDarkGrey
);
1946 // ----------------------------------------------------------------------------
1948 // ----------------------------------------------------------------------------
1950 void wxWin32Renderer
::DrawHorizontalLine(wxDC
& dc
,
1951 wxCoord y
, wxCoord x1
, wxCoord x2
)
1953 dc
.SetPen(m_penDarkGrey
);
1954 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1955 dc
.SetPen(m_penHighlight
);
1957 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
1960 void wxWin32Renderer
::DrawVerticalLine(wxDC
& dc
,
1961 wxCoord x
, wxCoord y1
, wxCoord y2
)
1963 dc
.SetPen(m_penDarkGrey
);
1964 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1965 dc
.SetPen(m_penHighlight
);
1967 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
1970 void wxWin32Renderer
::DrawFrame(wxDC
& dc
,
1971 const wxString
& label
,
1977 wxCoord height
= 0; // of the label
1978 wxRect rectFrame
= rect
;
1979 if ( !label
.empty() )
1981 // the text should touch the top border of the rect, so the frame
1982 // itself should be lower
1983 dc
.GetTextExtent(label
, NULL
, &height
);
1984 rectFrame
.y
+= height
/ 2;
1985 rectFrame
.height
-= height
/ 2;
1987 // we have to draw each part of the frame individually as we can't
1988 // erase the background beyond the label as it might contain some
1989 // pixmap already, so drawing everything and then overwriting part of
1990 // the frame with label doesn't work
1992 // TODO: the +5 and space insertion should be customizable
1995 rectText
.x
= rectFrame
.x
+ 5;
1996 rectText
.y
= rect
.y
;
1997 rectText
.width
= rectFrame
.width
- 7; // +2 border width
1998 rectText
.height
= height
;
2001 label2
<< _T(' ') << label
<< _T(' ');
2002 if ( indexAccel
!= -1 )
2004 // adjust it as we prepended a space
2009 DrawLabel(dc
, label2
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
2011 StandardDrawFrame(dc
, rectFrame
, rectLabel
);
2015 // just draw the complete frame
2016 DrawShadedRect(dc
, &rectFrame
, m_penDarkGrey
, m_penHighlight
);
2017 DrawShadedRect(dc
, &rectFrame
, m_penHighlight
, m_penDarkGrey
);
2021 // ----------------------------------------------------------------------------
2023 // ----------------------------------------------------------------------------
2025 void wxWin32Renderer
::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
2027 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
2028 // pixels each while we really need dots here... PS_ALTERNATE might
2029 // work, but it is for NT 5 only
2031 DrawRect(dc
, &rect
, wxPen(*wxBLACK
, 0, wxDOT
));
2033 // draw the pixels manually: note that to behave in the same manner as
2034 // DrawRect(), we must exclude the bottom and right borders from the
2036 wxCoord x1
= rect
.GetLeft(),
2038 x2
= rect
.GetRight(),
2039 y2
= rect
.GetBottom();
2041 dc
.SetPen(wxPen(*wxBLACK
, 0, wxSOLID
));
2043 // this seems to be closer than what Windows does than wxINVERT although
2044 // I'm still not sure if it's correct
2045 dc
.SetLogicalFunction(wxAND_REVERSE
);
2048 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
2049 dc
.DrawPoint(z
, rect
.GetTop());
2051 wxCoord shift
= z
== x2 ?
0 : 1;
2052 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
2053 dc
.DrawPoint(x2
, z
);
2055 shift
= z
== y2 ?
0 : 1;
2056 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
2057 dc
.DrawPoint(z
, y2
);
2059 shift
= z
== x1 ?
0 : 1;
2060 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
2061 dc
.DrawPoint(x1
, z
);
2063 dc
.SetLogicalFunction(wxCOPY
);
2067 void wxWin32Renderer
::DrawLabelShadow(wxDC
& dc
,
2068 const wxString
& label
,
2073 // draw shadow of the text
2074 dc
.SetTextForeground(m_colHighlight
);
2075 wxRect rectShadow
= rect
;
2078 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
2080 // make the text grey
2081 dc
.SetTextForeground(m_colDarkGrey
);
2084 void wxWin32Renderer
::DrawLabel(wxDC
& dc
,
2085 const wxString
& label
,
2092 DoDrawLabel(dc
, label
, rect
, flags
, alignment
, indexAccel
, rectBounds
);
2095 void wxWin32Renderer
::DoDrawLabel(wxDC
& dc
,
2096 const wxString
& label
,
2102 const wxPoint
& focusOffset
)
2104 // the underscores are not drawn for focused controls in wxMSW
2105 if ( flags
& wxCONTROL_FOCUSED
)
2110 if ( flags
& wxCONTROL_DISABLED
)
2112 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
2113 // currently only can happen for a menu item and it seems that Windows
2114 // doesn't draw the shadow in this case, so we don't do it neither
2115 if ( flags
& wxCONTROL_SELECTED
)
2117 // just make the label text greyed out
2118 dc
.SetTextForeground(m_colDarkGrey
);
2120 else // draw normal disabled label
2122 DrawLabelShadow(dc
, label
, rect
, alignment
, indexAccel
);
2127 dc
.DrawLabel(label
, wxNullBitmap
, rect
, alignment
, indexAccel
, &rectLabel
);
2129 if ( flags
& wxCONTROL_DISABLED
)
2131 // restore the fg colour
2132 dc
.SetTextForeground(*wxBLACK
);
2135 if ( flags
& wxCONTROL_FOCUSED
)
2137 if ( focusOffset
.x
|| focusOffset
.y
)
2139 rectLabel
.Inflate(focusOffset
.x
, focusOffset
.y
);
2142 DrawFocusRect(dc
, rectLabel
);
2146 *rectBounds
= rectLabel
;
2149 void wxWin32Renderer
::DrawButtonLabel(wxDC
& dc
,
2150 const wxString
& label
,
2151 const wxBitmap
& image
,
2158 // the underscores are not drawn for focused controls in wxMSW
2159 if ( flags
& wxCONTROL_PRESSED
)
2164 wxRect rectLabel
= rect
;
2165 if ( !label
.empty() )
2167 // shift the label if a button is pressed
2168 if ( flags
& wxCONTROL_PRESSED
)
2174 if ( flags
& wxCONTROL_DISABLED
)
2176 DrawLabelShadow(dc
, label
, rectLabel
, alignment
, indexAccel
);
2179 // leave enough space for the focus rectangle
2180 if ( flags
& wxCONTROL_FOCUSED
)
2182 rectLabel
.Inflate(-2);
2186 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
2188 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
2190 if ( flags
& wxCONTROL_PRESSED
)
2192 // the focus rectangle is never pressed, so undo the shift done
2200 DrawFocusRect(dc
, rectLabel
);
2204 // ----------------------------------------------------------------------------
2205 // (check)listbox items
2206 // ----------------------------------------------------------------------------
2208 void wxWin32Renderer
::DrawItem(wxDC
& dc
,
2209 const wxString
& label
,
2213 wxDCTextColourChanger
colChanger(dc
);
2215 if ( flags
& wxCONTROL_SELECTED
)
2217 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2219 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2220 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2221 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2222 dc
.DrawRectangle(rect
);
2225 wxRect rectText
= rect
;
2227 rectText
.width
-= 2;
2228 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
2230 if ( flags
& wxCONTROL_FOCUSED
)
2232 DrawFocusRect(dc
, rect
);
2236 void wxWin32Renderer
::DrawCheckItem(wxDC
& dc
,
2237 const wxString
& label
,
2238 const wxBitmap
& bitmap
,
2247 else // use default bitmap
2249 IndicatorStatus i
= flags
& wxCONTROL_CHECKED
2250 ? IndicatorStatus_Checked
2251 : IndicatorStatus_Unchecked
;
2253 if ( !m_bmpCheckBitmaps
[i
].Ok() )
2255 m_bmpCheckBitmaps
[i
] = wxBitmap(xpmChecked
[i
]);
2258 bmp
= m_bmpCheckBitmaps
[i
];
2261 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2 - 1,
2262 TRUE
/* use mask */);
2264 wxRect rectLabel
= rect
;
2265 int bmpWidth
= bmp
.GetWidth();
2266 rectLabel
.x
+= bmpWidth
;
2267 rectLabel
.width
-= bmpWidth
;
2269 DrawItem(dc
, label
, rectLabel
, flags
);
2272 // ----------------------------------------------------------------------------
2273 // check/radio buttons
2274 // ----------------------------------------------------------------------------
2276 wxBitmap wxWin32Renderer
::GetIndicator(IndicatorType indType
, int flags
)
2278 IndicatorState indState
;
2279 if ( flags
& wxCONTROL_SELECTED
)
2280 indState
= flags
& wxCONTROL_DISABLED ? IndicatorState_SelectedDisabled
2281 : IndicatorState_Selected
;
2282 else if ( flags
& wxCONTROL_DISABLED
)
2283 indState
= IndicatorState_Disabled
;
2284 else if ( flags
& wxCONTROL_PRESSED
)
2285 indState
= IndicatorState_Pressed
;
2287 indState
= IndicatorState_Normal
;
2289 IndicatorStatus indStatus
= flags
& wxCONTROL_CHECKED
2290 ? IndicatorStatus_Checked
2291 : IndicatorStatus_Unchecked
;
2293 wxBitmap bmp
= m_bmpIndicators
[indType
][indState
][indStatus
];
2296 const char **xpm
= xpmIndicators
[indType
][indState
][indStatus
];
2299 // create and cache it
2300 bmp
= wxBitmap(xpm
);
2301 m_bmpIndicators
[indType
][indState
][indStatus
] = bmp
;
2308 void wxWin32Renderer
::DrawCheckOrRadioButton(wxDC
& dc
,
2309 const wxString
& label
,
2310 const wxBitmap
& bitmap
,
2315 wxCoord focusOffsetY
)
2317 // calculate the position of the bitmap and of the label
2318 wxCoord heightBmp
= bitmap
.GetHeight();
2320 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
2323 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
2324 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
2326 // align label vertically with the bitmap - looks nicer like this
2327 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
2329 // calc horz position
2330 if ( align
== wxALIGN_RIGHT
)
2332 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
2333 rectLabel
.x
= rect
.x
+ 3;
2334 rectLabel
.SetRight(xBmp
);
2336 else // normal (checkbox to the left of the text) case
2339 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
2340 rectLabel
.SetRight(rect
.GetRight());
2343 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, TRUE
/* use mask */);
2346 dc
, label
, rectLabel
,
2348 wxALIGN_LEFT
| wxALIGN_TOP
,
2350 NULL
, // we don't need bounding rect
2351 // use custom vert focus rect offset
2352 wxPoint(FOCUS_RECT_OFFSET_X
, focusOffsetY
)
2356 void wxWin32Renderer
::DrawRadioButton(wxDC
& dc
,
2357 const wxString
& label
,
2358 const wxBitmap
& bitmap
,
2368 bmp
= GetRadioBitmap(flags
);
2370 DrawCheckOrRadioButton(dc
, label
,
2372 rect
, flags
, align
, indexAccel
,
2373 FOCUS_RECT_OFFSET_Y
); // default focus rect offset
2376 void wxWin32Renderer
::DrawCheckButton(wxDC
& dc
,
2377 const wxString
& label
,
2378 const wxBitmap
& bitmap
,
2388 bmp
= GetCheckBitmap(flags
);
2390 DrawCheckOrRadioButton(dc
, label
,
2392 rect
, flags
, align
, indexAccel
,
2393 0); // no focus rect offset for checkboxes
2396 void wxWin32Renderer
::DrawToolBarButton(wxDC
& dc
,
2397 const wxString
& label
,
2398 const wxBitmap
& bitmap
,
2399 const wxRect
& rectOrig
,
2402 if ( !label
.empty() || bitmap
.Ok() )
2404 wxRect rect
= rectOrig
;
2405 rect
.Deflate(BORDER_THICKNESS
);
2407 if ( flags
& wxCONTROL_PRESSED
)
2409 DrawBorder(dc
, wxBORDER_SUNKEN
, rect
, flags
);
2411 else if ( flags
& wxCONTROL_CURRENT
)
2413 DrawBorder(dc
, wxBORDER_RAISED
, rect
, flags
);
2416 dc
.DrawLabel(label
, bitmap
, rect
, wxALIGN_CENTRE
);
2420 // leave a small gap aroudn the line, also account for the toolbar
2422 DrawVerticalLine(dc
, rectOrig
.x
+ rectOrig
.width
/2,
2423 rectOrig
.y
+ 2*BORDER_THICKNESS
,
2424 rectOrig
.GetBottom() - BORDER_THICKNESS
);
2428 // ----------------------------------------------------------------------------
2430 // ----------------------------------------------------------------------------
2432 void wxWin32Renderer
::DrawTextLine(wxDC
& dc
,
2433 const wxString
& text
,
2439 // nothing special to do here
2440 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
2443 void wxWin32Renderer
::DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
)
2445 // we don't draw them
2448 // ----------------------------------------------------------------------------
2450 // ----------------------------------------------------------------------------
2452 void wxWin32Renderer
::DrawTab(wxDC
& dc
,
2453 const wxRect
& rectOrig
,
2455 const wxString
& label
,
2456 const wxBitmap
& bitmap
,
2460 wxRect rect
= rectOrig
;
2462 // the current tab is drawn indented (to the top for default case) and
2463 // bigger than the other ones
2464 const wxSize indent
= GetTabIndent();
2465 if ( flags
& wxCONTROL_SELECTED
)
2470 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2474 rect
.Inflate(indent
.x
, 0);
2476 rect
.height
+= indent
.y
;
2480 rect
.Inflate(indent
.x
, 0);
2481 rect
.height
+= indent
.y
;
2486 wxFAIL_MSG(_T("TODO"));
2491 // draw the text, image and the focus around them (if necessary)
2492 wxRect rectLabel
= rect
;
2493 rectLabel
.Deflate(1, 1);
2494 DrawButtonLabel(dc
, label
, bitmap
, rectLabel
,
2495 flags
, wxALIGN_CENTRE
, indexAccel
);
2497 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2498 static const wxCoord CUTOFF
= 2; // radius of the rounded corner
2501 x2
= rect
.GetRight(),
2502 y2
= rect
.GetBottom();
2504 // FIXME: all this code will break if the tab indent or the border width,
2505 // it is tied to the fact that both of them are equal to 2
2510 dc
.SetPen(m_penHighlight
);
2511 dc
.DrawLine(x
, y2
, x
, y
+ CUTOFF
);
2512 dc
.DrawLine(x
, y
+ CUTOFF
, x
+ CUTOFF
, y
);
2513 dc
.DrawLine(x
+ CUTOFF
, y
, x2
- CUTOFF
+ 1, y
);
2515 dc
.SetPen(m_penBlack
);
2516 dc
.DrawLine(x2
, y2
, x2
, y
+ CUTOFF
);
2517 dc
.DrawLine(x2
, y
+ CUTOFF
, x2
- CUTOFF
, y
);
2519 dc
.SetPen(m_penDarkGrey
);
2520 dc
.DrawLine(x2
- 1, y2
, x2
- 1, y
+ CUTOFF
- 1);
2522 if ( flags
& wxCONTROL_SELECTED
)
2524 dc
.SetPen(m_penLightGrey
);
2526 // overwrite the part of the border below this tab
2527 dc
.DrawLine(x
+ 1, y2
+ 1, x2
- 1, y2
+ 1);
2529 // and the shadow of the tab to the left of us
2530 dc
.DrawLine(x
+ 1, y
+ CUTOFF
+ 1, x
+ 1, y2
+ 1);
2535 dc
.SetPen(m_penHighlight
);
2536 // we need to continue one pixel further to overwrite the corner of
2537 // the border for the selected tab
2538 dc
.DrawLine(x
, y
- (flags
& wxCONTROL_SELECTED ?
1 : 0),
2540 dc
.DrawLine(x
, y2
- CUTOFF
, x
+ CUTOFF
, y2
);
2542 dc
.SetPen(m_penBlack
);
2543 dc
.DrawLine(x
+ CUTOFF
, y2
, x2
- CUTOFF
+ 1, y2
);
2544 dc
.DrawLine(x2
, y
, x2
, y2
- CUTOFF
);
2545 dc
.DrawLine(x2
, y2
- CUTOFF
, x2
- CUTOFF
, y2
);
2547 dc
.SetPen(m_penDarkGrey
);
2548 dc
.DrawLine(x
+ CUTOFF
, y2
- 1, x2
- CUTOFF
+ 1, y2
- 1);
2549 dc
.DrawLine(x2
- 1, y
, x2
- 1, y2
- CUTOFF
+ 1);
2551 if ( flags
& wxCONTROL_SELECTED
)
2553 dc
.SetPen(m_penLightGrey
);
2555 // overwrite the part of the (double!) border above this tab
2556 dc
.DrawLine(x
+ 1, y
- 1, x2
- 1, y
- 1);
2557 dc
.DrawLine(x
+ 1, y
- 2, x2
- 1, y
- 2);
2559 // and the shadow of the tab to the left of us
2560 dc
.DrawLine(x
+ 1, y2
- CUTOFF
, x
+ 1, y
- 1);
2566 wxFAIL_MSG(_T("TODO"));
2570 // ----------------------------------------------------------------------------
2572 // ----------------------------------------------------------------------------
2574 wxSize wxWin32Renderer
::GetSliderThumbSize(const wxRect
& rect
,
2575 wxOrientation orient
) const
2579 wxRect rectShaft
= GetSliderShaftRect(rect
, orient
);
2580 if ( orient
== wxHORIZONTAL
)
2582 size
.y
= rect
.height
- 6;
2583 size
.x
= wxMin(size
.y
/ 2, rectShaft
.width
);
2587 size
.x
= rect
.width
- 6;
2588 size
.y
= wxMin(size
.x
/ 2, rectShaft
.height
);
2594 wxRect wxWin32Renderer
::GetSliderShaftRect(const wxRect
& rectOrig
,
2595 wxOrientation orient
) const
2597 static const wxCoord SLIDER_MARGIN
= 6;
2599 wxRect rect
= rectOrig
;
2601 if ( orient
== wxHORIZONTAL
)
2603 // make the rect of minimal width and centre it
2604 rect
.height
= 2*BORDER_THICKNESS
;
2605 rect
.y
= rectOrig
.y
+ (rectOrig
.height
- rect
.height
) / 2;
2609 // leave margins on the sides
2610 rect
.Deflate(SLIDER_MARGIN
, 0);
2614 // same as above but in other direction
2615 rect
.width
= 2*BORDER_THICKNESS
;
2616 rect
.x
= rectOrig
.x
+ (rectOrig
.width
- rect
.width
) / 2;
2620 rect
.Deflate(0, SLIDER_MARGIN
);
2626 void wxWin32Renderer
::DrawSliderShaft(wxDC
& dc
,
2627 const wxRect
& rectOrig
,
2628 wxOrientation orient
,
2632 if ( flags
& wxCONTROL_FOCUSED
)
2634 DrawFocusRect(dc
, rectOrig
);
2637 wxRect rect
= GetSliderShaftRect(rectOrig
, orient
);
2642 DrawSunkenBorder(dc
, &rect
);
2645 void wxWin32Renderer
::DrawSliderThumb(wxDC
& dc
,
2647 wxOrientation orient
,
2651 we are drawing a shape of this form
2656 H DB where H is hightlight colour
2669 The interior of this shape is filled with the hatched brush if the thumb
2673 DrawBackground(dc
, wxNullColour
, rect
, flags
);
2675 bool transpose
= orient
== wxVERTICAL
;
2677 wxCoord x
, y
, x2
, y2
;
2682 x2
= rect
.GetBottom();
2683 y2
= rect
.GetRight();
2689 x2
= rect
.GetRight();
2690 y2
= rect
.GetBottom();
2693 // the size of the pointed part of the thumb
2694 wxCoord sizeArrow
= (transpose ? rect
.height
: rect
.width
) / 2;
2696 wxCoord x3
= x
+ sizeArrow
,
2697 y3
= y2
- sizeArrow
;
2699 dc
.SetPen(m_penHighlight
);
2700 DrawLine(dc
, x
, y
, x2
, y
, transpose
);
2701 DrawLine(dc
, x
, y
+ 1, x
, y2
- sizeArrow
, transpose
);
2702 DrawLine(dc
, x
, y3
, x3
, y2
, transpose
);
2704 dc
.SetPen(m_penBlack
);
2705 DrawLine(dc
, x3
, y2
, x2
, y3
, transpose
);
2706 DrawLine(dc
, x2
, y3
, x2
, y
- 1, transpose
);
2708 dc
.SetPen(m_penDarkGrey
);
2709 DrawLine(dc
, x3
, y2
- 1, x2
- 1, y3
, transpose
);
2710 DrawLine(dc
, x2
- 1, y3
, x2
- 1, y
, transpose
);
2712 if ( flags
& wxCONTROL_PRESSED
)
2714 // TODO: MSW fills the entire area inside, not just the rect
2715 wxRect rectInt
= rect
;
2717 rectInt
.SetRight(y3
);
2719 rectInt
.SetBottom(y3
);
2722 #if !defined(__WXMGL__)
2723 static const char *stipple_xpm
[] = {
2724 /* columns rows colors chars-per-pixel */
2733 // VS: MGL can only do 8x8 stipple brushes
2734 static const char *stipple_xpm
[] = {
2735 /* columns rows colors chars-per-pixel */
2750 dc
.SetBrush(wxBrush(stipple_xpm
));
2752 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, SHADOW_HIGHLIGHT
));
2753 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, CONTROL
));
2754 dc
.SetPen(*wxTRANSPARENT_PEN
);
2755 dc
.DrawRectangle(rectInt
);
2759 void wxWin32Renderer
::DrawSliderTicks(wxDC
& dc
,
2761 const wxSize
& sizeThumb
,
2762 wxOrientation orient
,
2774 // this would lead to an infinite loop below
2775 wxCHECK_RET( step
> 1, _T("invalid step in wxRenderer::DrawSliderTicks") );
2777 // the variable names correspond to horizontal case, but they can be used
2778 // for both orientations
2779 wxCoord x1
, x2
, y1
, y2
, len
, widthThumb
;
2780 if ( orient
== wxHORIZONTAL
)
2782 x1
= rect
.GetLeft();
2783 x2
= rect
.GetRight();
2785 // draw from bottom to top to leave one pixel space between the ticks
2786 // and the slider as Windows do
2787 y1
= rect
.GetBottom();
2792 widthThumb
= sizeThumb
.x
;
2797 x2
= rect
.GetBottom();
2799 y1
= rect
.GetRight();
2800 y2
= rect
.GetLeft();
2804 widthThumb
= sizeThumb
.y
;
2807 // the first tick should be positioned in such way that a thumb drawn in
2808 // the first position points down directly to it
2809 x1
+= widthThumb
/ 2;
2810 x2
-= widthThumb
/ 2;
2812 // this also means that we have slightly less space for the ticks in
2813 // between the first and the last
2816 dc
.SetPen(m_penBlack
);
2818 int range
= end
- start
;
2819 for ( int n
= 0; n
< range
; n
+= step
)
2821 wxCoord x
= x1
+ (len
*n
) / range
;
2823 DrawLine(dc
, x
, y1
, x
, y2
, orient
== wxVERTICAL
);
2826 // always draw the line at the end position
2827 DrawLine(dc
, x2
, y1
, x2
, y2
, orient
== wxVERTICAL
);
2830 // ----------------------------------------------------------------------------
2832 // ----------------------------------------------------------------------------
2834 // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
2835 class WXDLLEXPORT wxWin32MenuGeometryInfo
: public wxMenuGeometryInfo
2838 virtual wxSize
GetSize() const { return m_size
; }
2840 wxCoord
GetLabelOffset() const { return m_ofsLabel
; }
2841 wxCoord
GetAccelOffset() const { return m_ofsAccel
; }
2843 wxCoord
GetItemHeight() const { return m_heightItem
; }
2846 // the total size of the menu
2849 // the offset of the start of the menu item label
2852 // the offset of the start of the accel label
2855 // the height of a normal (not separator) item
2856 wxCoord m_heightItem
;
2858 friend wxMenuGeometryInfo
*
2859 wxWin32Renderer
::GetMenuGeometry(wxWindow
*, const wxMenu
&) const;
2862 // FIXME: all constants are hardcoded but shouldn't be
2863 static const wxCoord MENU_LEFT_MARGIN
= 9;
2864 static const wxCoord MENU_RIGHT_MARGIN
= 18;
2865 static const wxCoord MENU_VERT_MARGIN
= 3;
2867 // the margin around bitmap/check marks (on each side)
2868 static const wxCoord MENU_BMP_MARGIN
= 2;
2870 // the margin between the labels and accel strings
2871 static const wxCoord MENU_ACCEL_MARGIN
= 8;
2873 // the separator height in pixels: in fact, strangely enough, the real height
2874 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
2876 static const wxCoord MENU_SEPARATOR_HEIGHT
= 3;
2878 // the size of the standard checkmark bitmap
2879 static const wxCoord MENU_CHECK_SIZE
= 9;
2881 void wxWin32Renderer
::DrawMenuBarItem(wxDC
& dc
,
2882 const wxRect
& rectOrig
,
2883 const wxString
& label
,
2887 wxRect rect
= rectOrig
;
2890 wxDCTextColourChanger
colChanger(dc
);
2892 if ( flags
& wxCONTROL_SELECTED
)
2894 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2896 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2897 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2898 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2899 dc
.DrawRectangle(rect
);
2902 // don't draw the focus rect around menu bar items
2903 DrawLabel(dc
, label
, rect
, flags
& ~wxCONTROL_FOCUSED
,
2904 wxALIGN_CENTRE
, indexAccel
);
2907 void wxWin32Renderer
::DrawMenuItem(wxDC
& dc
,
2909 const wxMenuGeometryInfo
& gi
,
2910 const wxString
& label
,
2911 const wxString
& accel
,
2912 const wxBitmap
& bitmap
,
2916 const wxWin32MenuGeometryInfo
& geometryInfo
=
2917 (const wxWin32MenuGeometryInfo
&)gi
;
2922 rect
.width
= geometryInfo
.GetSize().x
;
2923 rect
.height
= geometryInfo
.GetItemHeight();
2925 // draw the selected item specially
2926 wxDCTextColourChanger
colChanger(dc
);
2927 if ( flags
& wxCONTROL_SELECTED
)
2929 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2931 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2932 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2933 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2934 dc
.DrawRectangle(rect
);
2937 // draw the bitmap: use the bitmap provided or the standard checkmark for
2938 // the checkable items
2939 wxBitmap bmp
= bitmap
;
2940 if ( !bmp
.Ok() && (flags
& wxCONTROL_CHECKED
) )
2942 bmp
= GetIndicator(IndicatorType_Menu
, flags
);
2947 rect
.SetRight(geometryInfo
.GetLabelOffset());
2948 wxControlRenderer
::DrawBitmap(dc
, bmp
, rect
);
2952 rect
.x
= geometryInfo
.GetLabelOffset();
2953 rect
.SetRight(geometryInfo
.GetAccelOffset());
2955 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
, indexAccel
);
2957 // draw the accel string
2958 rect
.x
= geometryInfo
.GetAccelOffset();
2959 rect
.SetRight(geometryInfo
.GetSize().x
);
2961 // NB: no accel index here
2962 DrawLabel(dc
, accel
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
);
2964 // draw the submenu indicator
2965 if ( flags
& wxCONTROL_ISSUBMENU
)
2967 rect
.x
= geometryInfo
.GetSize().x
- MENU_RIGHT_MARGIN
;
2968 rect
.width
= MENU_RIGHT_MARGIN
;
2970 wxArrowStyle arrowStyle
;
2971 if ( flags
& wxCONTROL_DISABLED
)
2972 arrowStyle
= flags
& wxCONTROL_SELECTED ? Arrow_InversedDisabled
2974 else if ( flags
& wxCONTROL_SELECTED
)
2975 arrowStyle
= Arrow_Inversed
;
2977 arrowStyle
= Arrow_Normal
;
2979 DrawArrow(dc
, rect
, Arrow_Right
, arrowStyle
);
2983 void wxWin32Renderer
::DrawMenuSeparator(wxDC
& dc
,
2985 const wxMenuGeometryInfo
& geomInfo
)
2987 DrawHorizontalLine(dc
, y
+ MENU_VERT_MARGIN
, 0, geomInfo
.GetSize().x
);
2990 wxSize wxWin32Renderer
::GetMenuBarItemSize(const wxSize
& sizeText
) const
2992 wxSize size
= sizeText
;
2994 // FIXME: menubar height is configurable under Windows
3001 wxMenuGeometryInfo
*wxWin32Renderer
::GetMenuGeometry(wxWindow
*win
,
3002 const wxMenu
& menu
) const
3004 // prepare the dc: for now we draw all the items with the system font
3006 dc
.SetFont(wxSystemSettings
::GetFont(wxSYS_DEFAULT_GUI_FONT
));
3008 // the height of a normal item
3009 wxCoord heightText
= dc
.GetCharHeight();
3014 // the max length of label and accel strings: the menu width is the sum of
3015 // them, even if they're for different items (as the accels should be
3018 // the max length of the bitmap is never 0 as Windows always leaves enough
3019 // space for a check mark indicator
3020 wxCoord widthLabelMax
= 0,
3022 widthBmpMax
= MENU_LEFT_MARGIN
;
3024 for ( wxMenuItemList
::Node
*node
= menu
.GetMenuItems().GetFirst();
3026 node
= node
->GetNext() )
3028 // height of this item
3031 wxMenuItem
*item
= node
->GetData();
3032 if ( item
->IsSeparator() )
3034 h
= MENU_SEPARATOR_HEIGHT
;
3036 else // not separator
3041 dc
.GetTextExtent(item
->GetLabel(), &widthLabel
, NULL
);
3042 if ( widthLabel
> widthLabelMax
)
3044 widthLabelMax
= widthLabel
;
3048 dc
.GetTextExtent(item
->GetAccelString(), &widthAccel
, NULL
);
3049 if ( widthAccel
> widthAccelMax
)
3051 widthAccelMax
= widthAccel
;
3054 const wxBitmap
& bmp
= item
->GetBitmap();
3057 wxCoord widthBmp
= bmp
.GetWidth();
3058 if ( widthBmp
> widthBmpMax
)
3059 widthBmpMax
= widthBmp
;
3061 //else if ( item->IsCheckable() ): no need to check for this as
3062 // MENU_LEFT_MARGIN is big enough to show the check mark
3065 h
+= 2*MENU_VERT_MARGIN
;
3067 // remember the item position and height
3068 item
->SetGeometry(height
, h
);
3073 // bundle the metrics into a struct and return it
3074 wxWin32MenuGeometryInfo
*gi
= new wxWin32MenuGeometryInfo
;
3076 gi
->m_ofsLabel
= widthBmpMax
+ 2*MENU_BMP_MARGIN
;
3077 gi
->m_ofsAccel
= gi
->m_ofsLabel
+ widthLabelMax
;
3078 if ( widthAccelMax
> 0 )
3080 // if we actually have any accesl, add a margin
3081 gi
->m_ofsAccel
+= MENU_ACCEL_MARGIN
;
3084 gi
->m_heightItem
= heightText
+ 2*MENU_VERT_MARGIN
;
3086 gi
->m_size
.x
= gi
->m_ofsAccel
+ widthAccelMax
+ MENU_RIGHT_MARGIN
;
3087 gi
->m_size
.y
= height
;
3092 // ----------------------------------------------------------------------------
3094 // ----------------------------------------------------------------------------
3096 static const wxCoord STATBAR_BORDER_X
= 2;
3097 static const wxCoord STATBAR_BORDER_Y
= 2;
3099 wxSize wxWin32Renderer
::GetStatusBarBorders(wxCoord
*borderBetweenFields
) const
3101 if ( borderBetweenFields
)
3102 *borderBetweenFields
= 2;
3104 return wxSize(STATBAR_BORDER_X
, STATBAR_BORDER_Y
);
3107 void wxWin32Renderer
::DrawStatusField(wxDC
& dc
,
3109 const wxString
& label
,
3114 if ( flags
& wxCONTROL_ISDEFAULT
)
3116 // draw the size grip: it is a normal rect except that in the lower
3117 // right corner we have several bands which may be used for dragging
3118 // the status bar corner
3120 // each band consists of 4 stripes: m_penHighlight, double
3121 // m_penDarkGrey and transparent one
3122 wxCoord x2
= rect
.GetRight(),
3123 y2
= rect
.GetBottom();
3125 // draw the upper left part of the rect normally
3126 dc
.SetPen(m_penDarkGrey
);
3127 dc
.DrawLine(rect
.GetLeft(), rect
.GetTop(), rect
.GetLeft(), y2
);
3128 dc
.DrawLine(rect
.GetLeft() + 1, rect
.GetTop(), x2
, rect
.GetTop());
3130 // draw the grey stripes of the grip
3132 wxCoord ofs
= WIDTH_STATUSBAR_GRIP_BAND
- 1;
3133 for ( n
= 0; n
< NUM_STATUSBAR_GRIP_BANDS
; n
++, ofs
+= WIDTH_STATUSBAR_GRIP_BAND
)
3135 dc
.DrawLine(x2
- ofs
+ 1, y2
- 1, x2
, y2
- ofs
);
3136 dc
.DrawLine(x2
- ofs
, y2
- 1, x2
, y2
- ofs
- 1);
3139 // draw the white stripes
3140 dc
.SetPen(m_penHighlight
);
3141 ofs
= WIDTH_STATUSBAR_GRIP_BAND
+ 1;
3142 for ( n
= 0; n
< NUM_STATUSBAR_GRIP_BANDS
; n
++, ofs
+= WIDTH_STATUSBAR_GRIP_BAND
)
3144 dc
.DrawLine(x2
- ofs
+ 1, y2
- 1, x2
, y2
- ofs
);
3147 // draw the remaining rect boundaries
3148 ofs
-= WIDTH_STATUSBAR_GRIP_BAND
;
3149 dc
.DrawLine(x2
, rect
.GetTop(), x2
, y2
- ofs
+ 1);
3150 dc
.DrawLine(rect
.GetLeft(), y2
, x2
- ofs
+ 1, y2
);
3155 rectIn
.width
-= STATUSBAR_GRIP_SIZE
;
3159 DrawBorder(dc
, wxBORDER_STATIC
, rect
, flags
, &rectIn
);
3162 rectIn
.Deflate(STATBAR_BORDER_X
, STATBAR_BORDER_Y
);
3164 wxDCClipper
clipper(dc
, rectIn
);
3165 DrawLabel(dc
, label
, rectIn
, flags
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
3168 // ----------------------------------------------------------------------------
3170 // ----------------------------------------------------------------------------
3172 void wxWin32Renderer
::GetComboBitmaps(wxBitmap
*bmpNormal
,
3174 wxBitmap
*bmpPressed
,
3175 wxBitmap
*bmpDisabled
)
3177 static const wxCoord widthCombo
= 16;
3178 static const wxCoord heightCombo
= 17;
3184 bmpNormal
->Create(widthCombo
, heightCombo
);
3185 dcMem
.SelectObject(*bmpNormal
);
3186 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
3187 Arrow_Down
, Arrow_Normal
);
3192 bmpPressed
->Create(widthCombo
, heightCombo
);
3193 dcMem
.SelectObject(*bmpPressed
);
3194 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
3195 Arrow_Down
, Arrow_Pressed
);
3200 bmpDisabled
->Create(widthCombo
, heightCombo
);
3201 dcMem
.SelectObject(*bmpDisabled
);
3202 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
3203 Arrow_Down
, Arrow_Disabled
);
3207 // ----------------------------------------------------------------------------
3209 // ----------------------------------------------------------------------------
3211 void wxWin32Renderer
::DoDrawBackground(wxDC
& dc
,
3212 const wxColour
& col
,
3216 wxBrush
brush(col
, wxSOLID
);
3218 dc
.SetPen(*wxTRANSPARENT_PEN
);
3219 dc
.DrawRectangle(rect
);
3222 void wxWin32Renderer
::DrawBackground(wxDC
& dc
,
3223 const wxColour
& col
,
3228 // just fill it with the given or default bg colour
3229 wxColour colBg
= col
.Ok() ? col
: wxSCHEME_COLOUR(m_scheme
, CONTROL
);
3230 DoDrawBackground(dc
, colBg
, rect
, window
);
3233 // ----------------------------------------------------------------------------
3235 // ----------------------------------------------------------------------------
3237 void wxWin32Renderer
::DrawArrow(wxDC
& dc
,
3242 // get the bitmap for this arrow
3243 wxArrowDirection arrowDir
;
3246 case wxLEFT
: arrowDir
= Arrow_Left
; break;
3247 case wxRIGHT
: arrowDir
= Arrow_Right
; break;
3248 case wxUP
: arrowDir
= Arrow_Up
; break;
3249 case wxDOWN
: arrowDir
= Arrow_Down
; break;
3252 wxFAIL_MSG(_T("unknown arrow direction"));
3256 wxArrowStyle arrowStyle
;
3257 if ( flags
& wxCONTROL_PRESSED
)
3259 // can't be pressed and disabled
3260 arrowStyle
= Arrow_Pressed
;
3264 arrowStyle
= flags
& wxCONTROL_DISABLED ? Arrow_Disabled
: Arrow_Normal
;
3267 DrawArrowButton(dc
, rect
, arrowDir
, arrowStyle
);
3270 void wxWin32Renderer
::DrawArrow(wxDC
& dc
,
3272 wxArrowDirection arrowDir
,
3273 wxArrowStyle arrowStyle
)
3275 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
3277 // under Windows the arrows always have the same size so just centre it in
3278 // the provided rectangle
3279 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
3280 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
3282 // Windows does it like this...
3283 if ( arrowDir
== Arrow_Left
)
3287 dc
.DrawBitmap(bmp
, x
, y
, TRUE
/* use mask */);
3290 void wxWin32Renderer
::DrawArrowButton(wxDC
& dc
,
3291 const wxRect
& rectAll
,
3292 wxArrowDirection arrowDir
,
3293 wxArrowStyle arrowStyle
)
3295 wxRect rect
= rectAll
;
3296 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
3297 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
3298 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
3301 void wxWin32Renderer
::DrawScrollbarThumb(wxDC
& dc
,
3302 wxOrientation orient
,
3306 // we don't use the flags, the thumb never changes appearance
3307 wxRect rectThumb
= rect
;
3308 DrawArrowBorder(dc
, &rectThumb
);
3309 DrawBackground(dc
, wxNullColour
, rectThumb
);
3312 void wxWin32Renderer
::DrawScrollbarShaft(wxDC
& dc
,
3313 wxOrientation orient
,
3314 const wxRect
& rectBar
,
3317 wxColourScheme
::StdColour col
= flags
& wxCONTROL_PRESSED
3318 ? wxColourScheme
::SCROLLBAR_PRESSED
3319 : wxColourScheme
::SCROLLBAR
;
3320 DoDrawBackground(dc
, m_scheme
->Get(col
), rectBar
);
3323 void wxWin32Renderer
::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
3325 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
3328 wxRect wxWin32Renderer
::GetScrollbarRect(const wxScrollBar
*scrollbar
,
3329 wxScrollBar
::Element elem
,
3332 return StandardGetScrollbarRect(scrollbar
, elem
,
3333 thumbPos
, m_sizeScrollbarArrow
);
3336 wxCoord wxWin32Renderer
::GetScrollbarSize(const wxScrollBar
*scrollbar
)
3338 return StandardScrollBarSize(scrollbar
, m_sizeScrollbarArrow
);
3341 wxHitTest wxWin32Renderer
::HitTestScrollbar(const wxScrollBar
*scrollbar
,
3342 const wxPoint
& pt
) const
3344 return StandardHitTestScrollbar(scrollbar
, pt
, m_sizeScrollbarArrow
);
3347 wxCoord wxWin32Renderer
::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
3350 return StandardScrollbarToPixel(scrollbar
, thumbPos
, m_sizeScrollbarArrow
);
3353 int wxWin32Renderer
::PixelToScrollbar(const wxScrollBar
*scrollbar
,
3356 return StandardPixelToScrollbar(scrollbar
, coord
, m_sizeScrollbarArrow
);
3359 // ----------------------------------------------------------------------------
3360 // top level windows
3361 // ----------------------------------------------------------------------------
3363 int wxWin32Renderer
::HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const
3365 wxRect client
= GetFrameClientArea(rect
, flags
);
3367 if ( client
.Inside(pt
) )
3368 return wxHT_TOPLEVEL_CLIENT_AREA
;
3370 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3372 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3374 if ( flags
& wxTOPLEVEL_ICON
)
3376 if ( wxRect(client
.GetPosition(), GetFrameIconSize()).Inside(pt
) )
3377 return wxHT_TOPLEVEL_ICON
;
3380 wxRect
btnRect(client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
,
3381 client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2,
3382 FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
3384 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3386 if ( btnRect
.Inside(pt
) )
3387 return wxHT_TOPLEVEL_BUTTON_CLOSE
;
3388 btnRect
.x
-= FRAME_BUTTON_WIDTH
+ 2;
3390 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3392 if ( btnRect
.Inside(pt
) )
3393 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE
;
3394 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3396 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3398 if ( btnRect
.Inside(pt
) )
3399 return wxHT_TOPLEVEL_BUTTON_RESTORE
;
3400 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3402 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3404 if ( btnRect
.Inside(pt
) )
3405 return wxHT_TOPLEVEL_BUTTON_ICONIZE
;
3406 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3408 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3410 if ( btnRect
.Inside(pt
) )
3411 return wxHT_TOPLEVEL_BUTTON_HELP
;
3412 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3415 if ( pt
.y
>= client
.y
&& pt
.y
< client
.y
+ FRAME_TITLEBAR_HEIGHT
)
3416 return wxHT_TOPLEVEL_TITLEBAR
;
3419 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3421 // we are certainly at one of borders, lets decide which one:
3424 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
3425 if ( pt
.x
< client
.x
)
3426 border
|= wxHT_TOPLEVEL_BORDER_W
;
3427 else if ( pt
.x
>= client
.width
+ client
.x
)
3428 border
|= wxHT_TOPLEVEL_BORDER_E
;
3429 if ( pt
.y
< client
.y
)
3430 border
|= wxHT_TOPLEVEL_BORDER_N
;
3431 else if ( pt
.y
>= client
.height
+ client
.y
)
3432 border
|= wxHT_TOPLEVEL_BORDER_S
;
3436 return wxHT_NOWHERE
;
3439 void wxWin32Renderer
::DrawFrameTitleBar(wxDC
& dc
,
3441 const wxString
& title
,
3445 int specialButtonFlags
)
3447 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3449 DrawFrameBorder(dc
, rect
, flags
);
3451 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3453 DrawFrameBackground(dc
, rect
, flags
);
3454 if ( flags
& wxTOPLEVEL_ICON
)
3455 DrawFrameIcon(dc
, rect
, icon
, flags
);
3456 DrawFrameTitle(dc
, rect
, title
, flags
);
3458 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3460 x
= client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
;
3461 y
= client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2;
3463 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3465 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_CLOSE
,
3466 (specialButton
== wxTOPLEVEL_BUTTON_CLOSE
) ?
3467 specialButtonFlags
: 0);
3468 x
-= FRAME_BUTTON_WIDTH
+ 2;
3470 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3472 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_MAXIMIZE
,
3473 (specialButton
== wxTOPLEVEL_BUTTON_MAXIMIZE
) ?
3474 specialButtonFlags
: 0);
3475 x
-= FRAME_BUTTON_WIDTH
;
3477 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3479 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_RESTORE
,
3480 (specialButton
== wxTOPLEVEL_BUTTON_RESTORE
) ?
3481 specialButtonFlags
: 0);
3482 x
-= FRAME_BUTTON_WIDTH
;
3484 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3486 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_ICONIZE
,
3487 (specialButton
== wxTOPLEVEL_BUTTON_ICONIZE
) ?
3488 specialButtonFlags
: 0);
3489 x
-= FRAME_BUTTON_WIDTH
;
3491 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3493 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_HELP
,
3494 (specialButton
== wxTOPLEVEL_BUTTON_HELP
) ?
3495 specialButtonFlags
: 0);
3496 x
-= FRAME_BUTTON_WIDTH
;
3501 void wxWin32Renderer
::DrawFrameBorder(wxDC
& dc
,
3505 if ( !(flags
& wxTOPLEVEL_BORDER
) ) return;
3509 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penBlack
);
3510 DrawShadedRect(dc
, &r
, m_penHighlight
, m_penDarkGrey
);
3511 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penLightGrey
);
3512 if ( flags
& wxTOPLEVEL_RESIZEABLE
)
3513 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penLightGrey
);
3516 void wxWin32Renderer
::DrawFrameBackground(wxDC
& dc
,
3520 if ( !(flags
& wxTOPLEVEL_TITLEBAR
) ) return;
3522 wxColour col
= (flags
& wxTOPLEVEL_ACTIVE
) ?
3523 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_ACTIVE
) :
3524 wxSCHEME_COLOUR(m_scheme
, TITLEBAR
);
3526 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3527 r
.height
= FRAME_TITLEBAR_HEIGHT
;
3529 DrawBackground(dc
, col
, r
);
3532 void wxWin32Renderer
::DrawFrameTitle(wxDC
& dc
,
3534 const wxString
& title
,
3537 wxColour col
= (flags
& wxTOPLEVEL_ACTIVE
) ?
3538 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_ACTIVE_TEXT
) :
3539 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_TEXT
);
3541 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3542 r
.height
= FRAME_TITLEBAR_HEIGHT
;
3543 if ( flags
& wxTOPLEVEL_ICON
)
3545 r
.x
+= FRAME_TITLEBAR_HEIGHT
;
3546 r
.width
-= FRAME_TITLEBAR_HEIGHT
+ 2;
3554 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3555 r
.width
-= FRAME_BUTTON_WIDTH
+ 2;
3556 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3557 r
.width
-= FRAME_BUTTON_WIDTH
;
3558 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3559 r
.width
-= FRAME_BUTTON_WIDTH
;
3560 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3561 r
.width
-= FRAME_BUTTON_WIDTH
;
3562 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3563 r
.width
-= FRAME_BUTTON_WIDTH
;
3565 dc
.SetFont(m_titlebarFont
);
3566 dc
.SetTextForeground(col
);
3569 dc
.GetTextExtent(title
, &textW
, NULL
);
3570 if ( textW
> r
.width
)
3572 // text is too big, let's shorten it and add "..." after it:
3573 size_t len
= title
.length();
3574 wxCoord WSoFar
, letterW
;
3576 dc
.GetTextExtent(wxT("..."), &WSoFar
, NULL
);
3577 if ( WSoFar
> r
.width
)
3579 // not enough space to draw anything
3585 for (size_t i
= 0; i
< len
; i
++)
3587 dc
.GetTextExtent(title
[i
], &letterW
, NULL
);
3588 if ( letterW
+ WSoFar
> r
.width
)
3594 dc
.DrawLabel(s
, wxNullBitmap
, r
,
3595 wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
3598 dc
.DrawLabel(title
, wxNullBitmap
, r
,
3599 wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
3602 void wxWin32Renderer
::DrawFrameIcon(wxDC
& dc
,
3609 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3610 dc
.DrawIcon(icon
, r
.x
, r
.y
);
3614 void wxWin32Renderer
::DrawFrameButton(wxDC
& dc
,
3615 wxCoord x
, wxCoord y
,
3619 wxRect
r(x
, y
, FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
3624 case wxTOPLEVEL_BUTTON_CLOSE
: idx
= FrameButton_Close
; break;
3625 case wxTOPLEVEL_BUTTON_MAXIMIZE
: idx
= FrameButton_Maximize
; break;
3626 case wxTOPLEVEL_BUTTON_ICONIZE
: idx
= FrameButton_Minimize
; break;
3627 case wxTOPLEVEL_BUTTON_RESTORE
: idx
= FrameButton_Restore
; break;
3628 case wxTOPLEVEL_BUTTON_HELP
: idx
= FrameButton_Help
; break;
3630 wxFAIL_MSG(wxT("incorrect button specification"));
3633 if ( flags
& wxCONTROL_PRESSED
)
3635 DrawShadedRect(dc
, &r
, m_penBlack
, m_penHighlight
);
3636 DrawShadedRect(dc
, &r
, m_penDarkGrey
, m_penLightGrey
);
3637 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), r
);
3638 dc
.DrawBitmap(m_bmpFrameButtons
[idx
], r
.x
+1, r
.y
+1, TRUE
);
3642 DrawShadedRect(dc
, &r
, m_penHighlight
, m_penBlack
);
3643 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penDarkGrey
);
3644 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), r
);
3645 dc
.DrawBitmap(m_bmpFrameButtons
[idx
], r
.x
, r
.y
, TRUE
);
3650 wxRect wxWin32Renderer
::GetFrameClientArea(const wxRect
& rect
,
3655 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3657 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3658 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3659 FRAME_BORDER_THICKNESS
;
3662 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3664 r
.y
+= FRAME_TITLEBAR_HEIGHT
;
3665 r
.height
-= FRAME_TITLEBAR_HEIGHT
;
3671 wxSize wxWin32Renderer
::GetFrameTotalSize(const wxSize
& clientSize
,
3674 wxSize
s(clientSize
);
3676 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3678 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3679 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3680 FRAME_BORDER_THICKNESS
;
3684 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3685 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
3690 wxSize wxWin32Renderer
::GetFrameMinSize(int flags
) const
3694 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3696 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3697 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3698 FRAME_BORDER_THICKNESS
;
3703 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3705 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
3707 if ( flags
& wxTOPLEVEL_ICON
)
3708 s
.x
+= FRAME_TITLEBAR_HEIGHT
+ 2;
3709 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3710 s
.x
+= FRAME_BUTTON_WIDTH
+ 2;
3711 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3712 s
.x
+= FRAME_BUTTON_WIDTH
;
3713 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3714 s
.x
+= FRAME_BUTTON_WIDTH
;
3715 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3716 s
.x
+= FRAME_BUTTON_WIDTH
;
3717 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3718 s
.x
+= FRAME_BUTTON_WIDTH
;
3724 wxSize wxWin32Renderer
::GetFrameIconSize() const
3726 return wxSize(16, 16);
3730 // ----------------------------------------------------------------------------
3732 // ----------------------------------------------------------------------------
3734 static char *error_xpm
[]={
3741 "...........########.............",
3742 "........###aaaaaaaa###..........",
3743 ".......#aaaaaaaaaaaaaa#.........",
3744 ".....##aaaaaaaaaaaaaaaa##.......",
3745 "....#aaaaaaaaaaaaaaaaaaaa#......",
3746 "...#aaaaaaaaaaaaaaaaaaaaaa#.....",
3747 "...#aaaaaaaaaaaaaaaaaaaaaa#b....",
3748 "..#aaaaaacaaaaaaaaaacaaaaaa#b...",
3749 ".#aaaaaacccaaaaaaaacccaaaaaa#...",
3750 ".#aaaaacccccaaaaaacccccaaaaa#b..",
3751 ".#aaaaaacccccaaaacccccaaaaaa#bb.",
3752 "#aaaaaaaacccccaacccccaaaaaaaa#b.",
3753 "#aaaaaaaaaccccccccccaaaaaaaaa#b.",
3754 "#aaaaaaaaaaccccccccaaaaaaaaaa#bb",
3755 "#aaaaaaaaaaaccccccaaaaaaaaaaa#bb",
3756 "#aaaaaaaaaaaccccccaaaaaaaaaaa#bb",
3757 "#aaaaaaaaaaccccccccaaaaaaaaaa#bb",
3758 "#aaaaaaaaaccccccccccaaaaaaaaa#bb",
3759 "#aaaaaaaacccccaacccccaaaaaaaa#bb",
3760 ".#aaaaaacccccaaaacccccaaaaaa#bbb",
3761 ".#aaaaacccccaaaaaacccccaaaaa#bbb",
3762 ".#aaaaaacccaaaaaaaacccaaaaaa#bb.",
3763 "..#aaaaaacaaaaaaaaaacaaaaaa#bbb.",
3764 "...#aaaaaaaaaaaaaaaaaaaaaa#bbbb.",
3765 "...#aaaaaaaaaaaaaaaaaaaaaa#bbb..",
3766 "....#aaaaaaaaaaaaaaaaaaaa#bbb...",
3767 ".....##aaaaaaaaaaaaaaaa##bbbb...",
3768 "......b#aaaaaaaaaaaaaa#bbbbb....",
3769 ".......b###aaaaaaaa###bbbbb.....",
3770 ".........bb########bbbbbb.......",
3771 "..........bbbbbbbbbbbbbb........",
3772 ".............bbbbbbbb..........."};
3774 static char *info_xpm
[]={
3782 "...........########.............",
3783 "........###abbbbbba###..........",
3784 "......##abbbbbbbbbbbba##........",
3785 ".....#abbbbbbbbbbbbbbbba#.......",
3786 "....#bbbbbbbaccccabbbbbbbd......",
3787 "...#bbbbbbbbccccccbbbbbbbbd.....",
3788 "..#bbbbbbbbbccccccbbbbbbbbbd....",
3789 ".#abbbbbbbbbaccccabbbbbbbbbad...",
3790 ".#bbbbbbbbbbbbbbbbbbbbbbbbbbd#..",
3791 "#abbbbbbbbbbbbbbbbbbbbbbbbbbad#.",
3792 "#bbbbbbbbbbcccccccbbbbbbbbbbbd#.",
3793 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3794 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3795 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3796 "#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
3797 "#abbbbbbbbbbbcccccbbbbbbbbbbad##",
3798 ".#bbbbbbbbbbbcccccbbbbbbbbbbd###",
3799 ".#abbbbbbbbbbcccccbbbbbbbbbad###",
3800 "..#bbbbbbbbcccccccccbbbbbbbd###.",
3801 "...dbbbbbbbbbbbbbbbbbbbbbbd####.",
3802 "....dbbbbbbbbbbbbbbbbbbbbd####..",
3803 ".....dabbbbbbbbbbbbbbbbad####...",
3804 "......ddabbbbbbbbbbbbadd####....",
3805 ".......#dddabbbbbbaddd#####.....",
3806 "........###dddabbbd#######......",
3807 "..........####dbbbd#####........",
3808 ".............#dbbbd##...........",
3809 "...............dbbd##...........",
3810 "................dbd##...........",
3811 ".................dd##...........",
3812 "..................###...........",
3813 "...................##..........."};
3815 static char *question_xpm
[]={
3823 "...........########.............",
3824 "........###abbbbbba###..........",
3825 "......##abbbbbbbbbbbba##........",
3826 ".....#abbbbbbbbbbbbbbbba#.......",
3827 "....#bbbbbbbbbbbbbbbbbbbbc......",
3828 "...#bbbbbbbaddddddabbbbbbbc.....",
3829 "..#bbbbbbbadabbddddabbbbbbbc....",
3830 ".#abbbbbbbddbbbbddddbbbbbbbac...",
3831 ".#bbbbbbbbddddbbddddbbbbbbbbc#..",
3832 "#abbbbbbbbddddbaddddbbbbbbbbac#.",
3833 "#bbbbbbbbbaddabddddbbbbbbbbbbc#.",
3834 "#bbbbbbbbbbbbbadddbbbbbbbbbbbc##",
3835 "#bbbbbbbbbbbbbdddbbbbbbbbbbbbc##",
3836 "#bbbbbbbbbbbbbddabbbbbbbbbbbbc##",
3837 "#bbbbbbbbbbbbbddbbbbbbbbbbbbbc##",
3838 "#abbbbbbbbbbbbbbbbbbbbbbbbbbac##",
3839 ".#bbbbbbbbbbbaddabbbbbbbbbbbc###",
3840 ".#abbbbbbbbbbddddbbbbbbbbbbac###",
3841 "..#bbbbbbbbbbddddbbbbbbbbbbc###.",
3842 "...cbbbbbbbbbaddabbbbbbbbbc####.",
3843 "....cbbbbbbbbbbbbbbbbbbbbc####..",
3844 ".....cabbbbbbbbbbbbbbbbac####...",
3845 "......ccabbbbbbbbbbbbacc####....",
3846 ".......#cccabbbbbbaccc#####.....",
3847 "........###cccabbbc#######......",
3848 "..........####cbbbc#####........",
3849 ".............#cbbbc##...........",
3850 "...............cbbc##...........",
3851 "................cbc##...........",
3852 ".................cc##...........",
3853 "..................###...........",
3854 "...................##..........."};
3856 static char *warning_xpm
[]={
3864 ".............###................",
3865 "............#aabc...............",
3866 "...........#aaaabcd.............",
3867 "...........#aaaaacdd............",
3868 "..........#aaaaaabcdd...........",
3869 "..........#aaaaaaacdd...........",
3870 ".........#aaaaaaaabcdd..........",
3871 ".........#aaaaaaaaacdd..........",
3872 "........#aaaaaaaaaabcdd.........",
3873 "........#aaabcccbaaacdd.........",
3874 ".......#aaaacccccaaabcdd........",
3875 ".......#aaaacccccaaaacdd........",
3876 "......#aaaaacccccaaaabcdd.......",
3877 "......#aaaaacccccaaaaacdd.......",
3878 ".....#aaaaaacccccaaaaabcdd......",
3879 ".....#aaaaaa#ccc#aaaaaacdd......",
3880 "....#aaaaaaabcccbaaaaaabcdd.....",
3881 "....#aaaaaaaacccaaaaaaaacdd.....",
3882 "...#aaaaaaaaa#c#aaaaaaaabcdd....",
3883 "...#aaaaaaaaabcbaaaaaaaaacdd....",
3884 "..#aaaaaaaaaaacaaaaaaaaaabcdd...",
3885 "..#aaaaaaaaaaaaaaaaaaaaaaacdd...",
3886 ".#aaaaaaaaaaabccbaaaaaaaaabcdd..",
3887 ".#aaaaaaaaaaaccccaaaaaaaaaacdd..",
3888 "#aaaaaaaaaaaaccccaaaaaaaaaabcdd.",
3889 "#aaaaaaaaaaaabccbaaaaaaaaaaacdd.",
3890 "#aaaaaaaaaaaaaaaaaaaaaaaaaaacddd",
3891 "#aaaaaaaaaaaaaaaaaaaaaaaaaabcddd",
3892 ".#aaaaaaaaaaaaaaaaaaaaaaaabcdddd",
3893 "..#ccccccccccccccccccccccccddddd",
3894 "....ddddddddddddddddddddddddddd.",
3895 ".....ddddddddddddddddddddddddd.."};
3897 wxBitmap wxWin32ArtProvider
::CreateBitmap(const wxArtID
& id
,
3898 const wxArtClient
& WXUNUSED(client
),
3899 const wxSize
& WXUNUSED(size
))
3901 if ( id
== wxART_INFORMATION
)
3902 return wxBitmap(info_xpm
);
3903 if ( id
== wxART_ERROR
)
3904 return wxBitmap(error_xpm
);
3905 if ( id
== wxART_WARNING
)
3906 return wxBitmap(warning_xpm
);
3907 if ( id
== wxART_QUESTION
)
3908 return wxBitmap(question_xpm
);
3909 return wxNullBitmap
;
3913 // ----------------------------------------------------------------------------
3914 // text control geometry
3915 // ----------------------------------------------------------------------------
3917 static inline int GetTextBorderWidth()
3922 wxRect wxWin32Renderer
::GetTextTotalArea(const wxTextCtrl
*text
,
3923 const wxRect
& rect
) const
3925 wxRect rectTotal
= rect
;
3927 wxCoord widthBorder
= GetTextBorderWidth();
3928 rectTotal
.Inflate(widthBorder
);
3930 // this is what Windows does
3936 wxRect wxWin32Renderer
::GetTextClientArea(const wxTextCtrl
*text
,
3938 wxCoord
*extraSpaceBeyond
) const
3940 wxRect rectText
= rect
;
3942 // undo GetTextTotalArea()
3943 if ( rectText
.height
> 0 )
3946 wxCoord widthBorder
= GetTextBorderWidth();
3947 rectText
.Inflate(-widthBorder
);
3949 if ( extraSpaceBeyond
)
3950 *extraSpaceBeyond
= 0;
3955 // ----------------------------------------------------------------------------
3957 // ----------------------------------------------------------------------------
3959 void wxWin32Renderer
::AdjustSize(wxSize
*size
, const wxWindow
*window
)
3962 if ( wxDynamicCast(window
, wxScrollBar
) )
3964 // we only set the width of vert scrollbars and height of the
3966 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
3967 size
->y
= m_sizeScrollbarArrow
.y
;
3969 size
->x
= m_sizeScrollbarArrow
.x
;
3971 // skip border width adjustments, they don't make sense for us
3974 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
3977 if ( wxDynamicCast(window
, wxButton
) )
3979 if ( !(window
->GetWindowStyle() & wxBU_EXACTFIT
) )
3981 // TODO: don't harcode all this
3982 size
->x
+= 3*window
->GetCharWidth();
3984 wxCoord heightBtn
= (11*(window
->GetCharHeight() + 8))/10;
3985 if ( size
->y
< heightBtn
- 8 )
3986 size
->y
= heightBtn
;
3991 // no border width adjustments for buttons
3994 #endif // wxUSE_BUTTON
3996 // take into account the border width
3997 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
3998 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
3999 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
4002 // ============================================================================
4004 // ============================================================================
4006 // ----------------------------------------------------------------------------
4007 // wxWin32InputHandler
4008 // ----------------------------------------------------------------------------
4010 wxWin32InputHandler
::wxWin32InputHandler(wxWin32Renderer
*renderer
)
4012 m_renderer
= renderer
;
4015 bool wxWin32InputHandler
::HandleKey(wxInputConsumer
*control
,
4016 const wxKeyEvent
& event
,
4022 bool wxWin32InputHandler
::HandleMouse(wxInputConsumer
*control
,
4023 const wxMouseEvent
& event
)
4025 // clicking on the control gives it focus
4026 if ( event
.ButtonDown() )
4028 wxWindow
*win
= control
->GetInputWindow();
4030 if (( wxWindow
::FindFocus() != control
->GetInputWindow() ) &&
4031 ( win
->AcceptsFocus() ) )
4042 // ----------------------------------------------------------------------------
4043 // wxWin32ScrollBarInputHandler
4044 // ----------------------------------------------------------------------------
4046 wxWin32ScrollBarInputHandler
::
4047 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
4048 wxInputHandler
*handler
)
4049 : wxStdScrollBarInputHandler(renderer
, handler
)
4051 m_scrollPaused
= FALSE
;
4055 bool wxWin32ScrollBarInputHandler
::OnScrollTimer(wxScrollBar
*scrollbar
,
4056 const wxControlAction
& action
)
4058 // stop if went beyond the position of the original click (this can only
4059 // happen when we scroll by pages)
4061 if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
4063 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
4064 != wxHT_SCROLLBAR_BAR_2
;
4066 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
4068 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
4069 != wxHT_SCROLLBAR_BAR_1
;
4074 StopScrolling(scrollbar
);
4076 scrollbar
->Refresh();
4081 return wxStdScrollBarInputHandler
::OnScrollTimer(scrollbar
, action
);
4084 bool wxWin32ScrollBarInputHandler
::HandleMouse(wxInputConsumer
*control
,
4085 const wxMouseEvent
& event
)
4087 // remember the current state
4088 bool wasDraggingThumb
= m_htLast
== wxHT_SCROLLBAR_THUMB
;
4090 // do process the message
4091 bool rc
= wxStdScrollBarInputHandler
::HandleMouse(control
, event
);
4093 // analyse the changes
4094 if ( !wasDraggingThumb
&& (m_htLast
== wxHT_SCROLLBAR_THUMB
) )
4096 // we just started dragging the thumb, remember its initial position to
4097 // be able to restore it if the drag is cancelled later
4098 m_eventStartDrag
= event
;
4104 bool wxWin32ScrollBarInputHandler
::HandleMouseMove(wxInputConsumer
*control
,
4105 const wxMouseEvent
& event
)
4107 // we don't highlight scrollbar elements, so there is no need to process
4108 // mouse move events normally - only do it while mouse is captured (i.e.
4109 // when we're dragging the thumb or pressing on something)
4110 if ( !m_winCapture
)
4113 if ( event
.Entering() )
4115 // we're not interested in this at all
4119 wxScrollBar
*scrollbar
= wxStaticCast(control
->GetInputWindow(), wxScrollBar
);
4121 if ( m_scrollPaused
)
4123 // check if the mouse returned to its original location
4125 if ( event
.Leaving() )
4131 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
4132 if ( ht
== m_htLast
)
4134 // yes it did, resume scrolling
4135 m_scrollPaused
= FALSE
;
4136 if ( m_timerScroll
)
4138 // we were scrolling by line/page, restart timer
4139 m_timerScroll
->Start(m_interval
);
4141 Press(scrollbar
, TRUE
);
4143 else // we were dragging the thumb
4145 // restore its last location
4146 HandleThumbMove(scrollbar
, m_eventLastDrag
);
4152 else // normal case, scrolling hasn't been paused
4154 // if we're scrolling the scrollbar because the arrow or the shaft was
4155 // pressed, check that the mouse stays on the same scrollbar element
4158 // Always let thumb jump back if we leave the scrollbar
4159 if ( event
.Moving() )
4161 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
4163 else // event.Leaving()
4168 // Jump back only if we get far away from it
4169 wxPoint pos
= event
.GetPosition();
4170 if (scrollbar
->HasFlag( wxVERTICAL
))
4172 if (pos
.x
> -40 && pos
.x
< scrollbar
->GetSize().x
+40)
4177 if (pos
.y
> -40 && pos
.y
< scrollbar
->GetSize().y
+40)
4180 ht
= m_renderer
->HitTestScrollbar(scrollbar
, pos
);
4183 // if we're dragging the thumb and the mouse stays in the scrollbar, it
4184 // is still ok - we only want to catch the case when the mouse leaves
4185 // the scrollbar here
4186 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
&& ht
!= wxHT_NOWHERE
)
4188 ht
= wxHT_SCROLLBAR_THUMB
;
4191 if ( ht
!= m_htLast
)
4193 // what were we doing? 2 possibilities: either an arrow/shaft was
4194 // pressed in which case we have a timer and so we just stop it or
4195 // we were dragging the thumb
4196 if ( m_timerScroll
)
4199 m_interval
= m_timerScroll
->GetInterval();
4200 m_timerScroll
->Stop();
4201 m_scrollPaused
= TRUE
;
4203 // unpress the arrow
4204 Press(scrollbar
, FALSE
);
4206 else // we were dragging the thumb
4208 // remember the current thumb position to be able to restore it
4209 // if the mouse returns to it later
4210 m_eventLastDrag
= event
;
4212 // and restore the original position (before dragging) of the
4214 HandleThumbMove(scrollbar
, m_eventStartDrag
);
4221 return wxStdScrollBarInputHandler
::HandleMouseMove(control
, event
);
4224 // ----------------------------------------------------------------------------
4225 // wxWin32CheckboxInputHandler
4226 // ----------------------------------------------------------------------------
4228 bool wxWin32CheckboxInputHandler
::HandleKey(wxInputConsumer
*control
,
4229 const wxKeyEvent
& event
,
4234 wxControlAction action
;
4235 int keycode
= event
.GetKeyCode();
4239 action
= wxACTION_CHECKBOX_TOGGLE
;
4243 case WXK_NUMPAD_SUBTRACT
:
4244 action
= wxACTION_CHECKBOX_CHECK
;
4248 case WXK_NUMPAD_ADD
:
4249 case WXK_NUMPAD_EQUAL
:
4250 action
= wxACTION_CHECKBOX_CLEAR
;
4256 control
->PerformAction(action
);
4265 // ----------------------------------------------------------------------------
4266 // wxWin32TextCtrlInputHandler
4267 // ----------------------------------------------------------------------------
4269 bool wxWin32TextCtrlInputHandler
::HandleKey(wxInputConsumer
*control
,
4270 const wxKeyEvent
& event
,
4273 // handle only MSW-specific text bindings here, the others are handled in
4277 int keycode
= event
.GetKeyCode();
4279 wxControlAction action
;
4280 if ( keycode
== WXK_DELETE
&& event
.ShiftDown() )
4282 action
= wxACTION_TEXT_CUT
;
4284 else if ( keycode
== WXK_INSERT
)
4286 if ( event
.ControlDown() )
4287 action
= wxACTION_TEXT_COPY
;
4288 else if ( event
.ShiftDown() )
4289 action
= wxACTION_TEXT_PASTE
;
4292 if ( action
!= wxACTION_NONE
)
4294 control
->PerformAction(action
);
4300 return wxStdTextCtrlInputHandler
::HandleKey(control
, event
, pressed
);
4303 // ----------------------------------------------------------------------------
4304 // wxWin32StatusBarInputHandler
4305 // ----------------------------------------------------------------------------
4307 wxWin32StatusBarInputHandler
::
4308 wxWin32StatusBarInputHandler(wxInputHandler
*handler
)
4309 : wxStdInputHandler(handler
)
4314 bool wxWin32StatusBarInputHandler
::IsOnGrip(wxWindow
*statbar
,
4315 const wxPoint
& pt
) const
4317 if ( statbar
->HasFlag(wxST_SIZEGRIP
) &&
4318 statbar
->GetParent()->HasFlag(wxRESIZE_BORDER
) )
4321 parentTLW
= wxDynamicCast(statbar
->GetParent(), wxTopLevelWindow
);
4323 wxCHECK_MSG( parentTLW
, FALSE
,
4324 _T("the status bar should be a child of a TLW") );
4326 // a maximized window can't be resized anyhow
4327 if ( !parentTLW
->IsMaximized() )
4329 // VZ: I think that the standard Windows behaviour is to only
4330 // show the resizing cursor when the mouse is on top of the
4331 // grip itself but apparently different Windows versions behave
4332 // differently (?) and it seems a better UI to allow resizing
4333 // the status bar even when the mouse is above the grip
4334 wxSize sizeSbar
= statbar
->GetSize();
4336 int diff
= sizeSbar
.x
- pt
.x
;
4337 return diff
>= 0 && diff
< (wxCoord
)STATUSBAR_GRIP_SIZE
;
4344 bool wxWin32StatusBarInputHandler
::HandleMouse(wxInputConsumer
*consumer
,
4345 const wxMouseEvent
& event
)
4347 if ( event
.Button(1) )
4349 if ( event
.ButtonDown(1) )
4351 wxWindow
*statbar
= consumer
->GetInputWindow();
4353 if ( IsOnGrip(statbar
, event
.GetPosition()) )
4355 wxTopLevelWindow
*tlw
= wxDynamicCast(statbar
->GetParent(),
4359 tlw
->PerformAction(wxACTION_TOPLEVEL_RESIZE
,
4360 wxHT_TOPLEVEL_BORDER_SE
);
4362 statbar
->SetCursor(m_cursorOld
);
4370 return wxStdInputHandler
::HandleMouse(consumer
, event
);
4373 bool wxWin32StatusBarInputHandler
::HandleMouseMove(wxInputConsumer
*consumer
,
4374 const wxMouseEvent
& event
)
4376 wxWindow
*statbar
= consumer
->GetInputWindow();
4378 bool isOnGrip
= IsOnGrip(statbar
, event
.GetPosition());
4379 if ( isOnGrip
!= m_isOnGrip
)
4381 m_isOnGrip
= isOnGrip
;
4384 m_cursorOld
= statbar
->GetCursor();
4385 statbar
->SetCursor(wxCURSOR_SIZENWSE
);
4389 statbar
->SetCursor(m_cursorOld
);
4393 return wxStdInputHandler
::HandleMouseMove(consumer
, event
);
4396 // ----------------------------------------------------------------------------
4397 // wxWin32FrameInputHandler
4398 // ----------------------------------------------------------------------------
4400 class wxWin32SystemMenuEvtHandler
: public wxEvtHandler
4403 wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler
*handler
);
4405 void Attach(wxInputConsumer
*consumer
);
4409 DECLARE_EVENT_TABLE()
4410 void OnSystemMenu(wxCommandEvent
&event
);
4411 void OnCloseFrame(wxCommandEvent
&event
);
4412 void OnClose(wxCloseEvent
&event
);
4414 wxWin32FrameInputHandler
*m_inputHnd
;
4415 wxTopLevelWindow
*m_wnd
;
4416 wxAcceleratorTable m_oldAccelTable
;
4419 wxWin32SystemMenuEvtHandler
::wxWin32SystemMenuEvtHandler(
4420 wxWin32FrameInputHandler
*handler
)
4422 m_inputHnd
= handler
;
4426 void wxWin32SystemMenuEvtHandler
::Attach(wxInputConsumer
*consumer
)
4428 wxASSERT_MSG( m_wnd
== NULL
, _T("can't attach the handler twice!") );
4430 m_wnd
= wxStaticCast(consumer
->GetInputWindow(), wxTopLevelWindow
);
4431 m_wnd
->PushEventHandler(this);
4433 // VS: This code relies on using generic implementation of
4434 // wxAcceleratorTable in wxUniv!
4435 wxAcceleratorTable table
= *m_wnd
->GetAcceleratorTable();
4436 m_oldAccelTable
= table
;
4437 table
.Add(wxAcceleratorEntry(wxACCEL_ALT
, WXK_SPACE
, wxID_SYSTEM_MENU
));
4438 table
.Add(wxAcceleratorEntry(wxACCEL_ALT
, WXK_F4
, wxID_CLOSE_FRAME
));
4439 m_wnd
->SetAcceleratorTable(table
);
4442 void wxWin32SystemMenuEvtHandler
::Detach()
4446 m_wnd
->SetAcceleratorTable(m_oldAccelTable
);
4447 m_wnd
->RemoveEventHandler(this);
4452 BEGIN_EVENT_TABLE(wxWin32SystemMenuEvtHandler
, wxEvtHandler
)
4453 EVT_MENU(wxID_SYSTEM_MENU
, wxWin32SystemMenuEvtHandler
::OnSystemMenu
)
4454 EVT_MENU(wxID_CLOSE_FRAME
, wxWin32SystemMenuEvtHandler
::OnCloseFrame
)
4455 EVT_CLOSE(wxWin32SystemMenuEvtHandler
::OnClose
)
4458 void wxWin32SystemMenuEvtHandler
::OnSystemMenu(wxCommandEvent
&WXUNUSED(event
))
4460 int border
= ((m_wnd
->GetWindowStyle() & wxRESIZE_BORDER
) &&
4461 !m_wnd
->IsMaximized()) ?
4462 RESIZEABLE_FRAME_BORDER_THICKNESS
:
4463 FRAME_BORDER_THICKNESS
;
4464 wxPoint pt
= m_wnd
->GetClientAreaOrigin();
4465 pt
.x
= -pt
.x
+ border
;
4466 pt
.y
= -pt
.y
+ border
+ FRAME_TITLEBAR_HEIGHT
;
4468 wxAcceleratorTable table
= *m_wnd
->GetAcceleratorTable();
4469 m_wnd
->SetAcceleratorTable(wxNullAcceleratorTable
);
4470 m_inputHnd
->PopupSystemMenu(m_wnd
, pt
);
4471 m_wnd
->SetAcceleratorTable(table
);
4474 void wxWin32SystemMenuEvtHandler
::OnCloseFrame(wxCommandEvent
&WXUNUSED(event
))
4476 m_wnd
->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK
,
4477 wxTOPLEVEL_BUTTON_CLOSE
);
4480 void wxWin32SystemMenuEvtHandler
::OnClose(wxCloseEvent
&event
)
4487 wxWin32FrameInputHandler
::wxWin32FrameInputHandler(wxInputHandler
*handler
)
4488 : wxStdFrameInputHandler(handler
)
4490 m_menuHandler
= new wxWin32SystemMenuEvtHandler(this);
4493 wxWin32FrameInputHandler
::~wxWin32FrameInputHandler()
4495 if ( m_menuHandler
)
4497 m_menuHandler
->Detach();
4498 delete m_menuHandler
;
4502 bool wxWin32FrameInputHandler
::HandleMouse(wxInputConsumer
*consumer
,
4503 const wxMouseEvent
& event
)
4505 if ( event
.LeftDClick() || event
.LeftDown() || event
.RightDown() )
4507 wxTopLevelWindow
*tlw
=
4508 wxStaticCast(consumer
->GetInputWindow(), wxTopLevelWindow
);
4510 long hit
= tlw
->HitTest(event
.GetPosition());
4512 if ( event
.LeftDClick() && hit
== wxHT_TOPLEVEL_TITLEBAR
)
4514 tlw
->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK
,
4515 tlw
->IsMaximized() ? wxTOPLEVEL_BUTTON_RESTORE
4516 : wxTOPLEVEL_BUTTON_MAXIMIZE
);
4519 else if ( tlw
->GetWindowStyle() & wxSYSTEM_MENU
)
4521 if ( (event
.LeftDown() && hit
== wxHT_TOPLEVEL_ICON
) ||
4522 (event
.RightDown() &&
4523 (hit
== wxHT_TOPLEVEL_TITLEBAR
||
4524 hit
== wxHT_TOPLEVEL_ICON
)) )
4526 PopupSystemMenu(tlw
, event
.GetPosition());
4532 return wxStdFrameInputHandler
::HandleMouse(consumer
, event
);
4535 void wxWin32FrameInputHandler
::PopupSystemMenu(wxTopLevelWindow
*window
,
4536 const wxPoint
& pos
) const
4538 wxMenu
*menu
= new wxMenu
;
4540 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4541 menu
->Append(wxID_RESTORE_FRAME
, _("&Restore"));
4542 menu
->Append(wxID_MOVE_FRAME
, _("&Move"));
4543 if ( window
->GetWindowStyle() & wxRESIZE_BORDER
)
4544 menu
->Append(wxID_RESIZE_FRAME
, _("&Size"));
4545 if ( wxSystemSettings
::HasFeature(wxSYS_CAN_ICONIZE_FRAME
) )
4546 menu
->Append(wxID_ICONIZE_FRAME
, _("Mi&nimize"));
4547 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4548 menu
->Append(wxID_MAXIMIZE_FRAME
, _("Ma&ximize"));
4549 menu
->AppendSeparator();
4550 menu
->Append(wxID_CLOSE_FRAME
, _("Close\tAlt-F4"));
4552 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4554 if ( window
->IsMaximized() )
4556 menu
->Enable(wxID_MAXIMIZE_FRAME
, FALSE
);
4557 menu
->Enable(wxID_MOVE_FRAME
, FALSE
);
4558 if ( window
->GetWindowStyle() & wxRESIZE_BORDER
)
4559 menu
->Enable(wxID_RESIZE_FRAME
, FALSE
);
4562 menu
->Enable(wxID_RESTORE_FRAME
, FALSE
);
4565 window
->PopupMenu(menu
, pos
);
4569 bool wxWin32FrameInputHandler
::HandleActivation(wxInputConsumer
*consumer
,
4572 if ( consumer
->GetInputWindow()->GetWindowStyle() & wxSYSTEM_MENU
)
4574 // always detach if active frame changed:
4575 m_menuHandler
->Detach();
4579 m_menuHandler
->Attach(consumer
);
4583 return wxStdFrameInputHandler
::HandleActivation(consumer
, activated
);