1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/univ/themes/win32.cpp
3 // Purpose: wxUniversal theme implementing Win32-like LNF
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
31 #include "wx/window.h"
33 #include "wx/dcmemory.h"
35 #include "wx/button.h"
36 #include "wx/bmpbuttn.h"
37 #include "wx/listbox.h"
38 #include "wx/checklst.h"
39 #include "wx/combobox.h"
40 #include "wx/scrolbar.h"
41 #include "wx/slider.h"
42 #include "wx/textctrl.h"
43 #include "wx/listbox.h"
44 #include "wx/toolbar.h"
45 #include "wx/statusbr.h"
48 // for COLOR_* constants
49 #include "wx/msw/private.h"
54 #include "wx/notebook.h"
55 #include "wx/spinbutt.h"
56 #include "wx/settings.h"
57 #include "wx/artprov.h"
58 #include "wx/toplevel.h"
61 #include "wx/univ/scrtimer.h"
62 #include "wx/univ/renderer.h"
63 #include "wx/univ/inphand.h"
64 #include "wx/univ/colschem.h"
65 #include "wx/univ/theme.h"
67 // ----------------------------------------------------------------------------
69 // ----------------------------------------------------------------------------
71 static const int BORDER_THICKNESS
= 2;
73 // the offset between the label and focus rect around it
74 static const int FOCUS_RECT_OFFSET_X
= 1;
75 static const int FOCUS_RECT_OFFSET_Y
= 1;
77 static const int FRAME_BORDER_THICKNESS
= 3;
78 static const int RESIZEABLE_FRAME_BORDER_THICKNESS
= 4;
79 static const int FRAME_TITLEBAR_HEIGHT
= 18;
80 static const int FRAME_BUTTON_WIDTH
= 16;
81 static const int FRAME_BUTTON_HEIGHT
= 14;
83 static const size_t NUM_STATUSBAR_GRIP_BANDS
= 3;
84 static const size_t WIDTH_STATUSBAR_GRIP_BAND
= 4;
85 static const size_t STATUSBAR_GRIP_SIZE
=
86 WIDTH_STATUSBAR_GRIP_BAND
*NUM_STATUSBAR_GRIP_BANDS
;
88 static const wxCoord SLIDER_MARGIN
= 6; // margin around slider
89 static const wxCoord SLIDER_THUMB_LENGTH
= 18;
90 static const wxCoord SLIDER_TICK_LENGTH
= 6;
102 IndicatorState_Normal
,
103 IndicatorState_Pressed
, // this one is for check/radioboxes
104 IndicatorState_Selected
= IndicatorState_Pressed
, // for menus
105 IndicatorState_Disabled
,
106 IndicatorState_SelectedDisabled
, // only for the menus
112 IndicatorStatus_Checked
,
113 IndicatorStatus_Unchecked
,
114 IndicatorStatus_Undeterminated
,
118 // wxWin32Renderer: draw the GUI elements in Win32 style
119 // ----------------------------------------------------------------------------
121 class wxWin32Renderer
: public wxRenderer
125 enum wxArrowDirection
140 Arrow_InvertedDisabled
,
144 enum wxFrameButtonType
147 FrameButton_Minimize
,
148 FrameButton_Maximize
,
155 wxWin32Renderer(const wxColourScheme
*scheme
);
157 // implement the base class pure virtuals
158 virtual void DrawBackground(wxDC
& dc
,
162 wxWindow
*window
= NULL
);
163 virtual void DrawLabel(wxDC
& dc
,
164 const wxString
& label
,
167 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
169 wxRect
*rectBounds
= NULL
);
170 virtual void DrawButtonLabel(wxDC
& dc
,
171 const wxString
& label
,
172 const wxBitmap
& image
,
175 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
177 wxRect
*rectBounds
= NULL
);
178 virtual void DrawBorder(wxDC
& dc
,
182 wxRect
*rectIn
= (wxRect
*)NULL
);
183 virtual void DrawHorizontalLine(wxDC
& dc
,
184 wxCoord y
, wxCoord x1
, wxCoord x2
);
185 virtual void DrawVerticalLine(wxDC
& dc
,
186 wxCoord x
, wxCoord y1
, wxCoord y2
);
187 virtual void DrawFrame(wxDC
& dc
,
188 const wxString
& label
,
191 int alignment
= wxALIGN_LEFT
,
192 int indexAccel
= -1);
193 virtual void DrawTextBorder(wxDC
& dc
,
197 wxRect
*rectIn
= (wxRect
*)NULL
);
198 virtual void DrawButtonBorder(wxDC
& dc
,
201 wxRect
*rectIn
= (wxRect
*)NULL
);
202 virtual void DrawArrow(wxDC
& dc
,
206 virtual void DrawScrollbarArrow(wxDC
& dc
,
210 { DrawArrow(dc
, dir
, rect
, flags
); }
211 virtual void DrawScrollbarThumb(wxDC
& dc
,
212 wxOrientation orient
,
215 virtual void DrawScrollbarShaft(wxDC
& dc
,
216 wxOrientation orient
,
219 virtual void DrawScrollCorner(wxDC
& dc
,
221 virtual void DrawItem(wxDC
& dc
,
222 const wxString
& label
,
225 virtual void DrawCheckItem(wxDC
& dc
,
226 const wxString
& label
,
227 const wxBitmap
& bitmap
,
230 virtual void DrawCheckButton(wxDC
& dc
,
231 const wxString
& label
,
232 const wxBitmap
& bitmap
,
235 wxAlignment align
= wxALIGN_LEFT
,
236 int indexAccel
= -1);
237 virtual void DrawRadioButton(wxDC
& dc
,
238 const wxString
& label
,
239 const wxBitmap
& bitmap
,
242 wxAlignment align
= wxALIGN_LEFT
,
243 int indexAccel
= -1);
244 virtual void DrawToolBarButton(wxDC
& dc
,
245 const wxString
& label
,
246 const wxBitmap
& bitmap
,
250 virtual void DrawTextLine(wxDC
& dc
,
251 const wxString
& text
,
256 virtual void DrawLineWrapMark(wxDC
& dc
, const wxRect
& rect
);
257 virtual void DrawTab(wxDC
& dc
,
260 const wxString
& label
,
261 const wxBitmap
& bitmap
= wxNullBitmap
,
263 int indexAccel
= -1);
265 virtual void DrawSliderShaft(wxDC
& dc
,
268 wxOrientation orient
,
271 wxRect
*rectShaft
= NULL
);
272 virtual void DrawSliderThumb(wxDC
& dc
,
274 wxOrientation orient
,
277 virtual void DrawSliderTicks(wxDC
& dc
,
280 wxOrientation orient
,
287 virtual void DrawMenuBarItem(wxDC
& dc
,
289 const wxString
& label
,
291 int indexAccel
= -1);
292 virtual void DrawMenuItem(wxDC
& dc
,
294 const wxMenuGeometryInfo
& geometryInfo
,
295 const wxString
& label
,
296 const wxString
& accel
,
297 const wxBitmap
& bitmap
= wxNullBitmap
,
299 int indexAccel
= -1);
300 virtual void DrawMenuSeparator(wxDC
& dc
,
302 const wxMenuGeometryInfo
& geomInfo
);
304 virtual void DrawStatusField(wxDC
& dc
,
306 const wxString
& label
,
307 int flags
= 0, int style
= 0);
310 virtual void DrawFrameTitleBar(wxDC
& dc
,
312 const wxString
& title
,
315 int specialButton
= 0,
316 int specialButtonFlags
= 0);
317 virtual void DrawFrameBorder(wxDC
& dc
,
320 virtual void DrawFrameBackground(wxDC
& dc
,
323 virtual void DrawFrameTitle(wxDC
& dc
,
325 const wxString
& title
,
327 virtual void DrawFrameIcon(wxDC
& dc
,
331 virtual void DrawFrameButton(wxDC
& dc
,
332 wxCoord x
, wxCoord y
,
335 virtual wxRect
GetFrameClientArea(const wxRect
& rect
, int flags
) const;
336 virtual wxSize
GetFrameTotalSize(const wxSize
& clientSize
, int flags
) const;
337 virtual wxSize
GetFrameMinSize(int flags
) const;
338 virtual wxSize
GetFrameIconSize() const;
339 virtual int HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const;
341 virtual void GetComboBitmaps(wxBitmap
*bmpNormal
,
343 wxBitmap
*bmpPressed
,
344 wxBitmap
*bmpDisabled
);
346 virtual void AdjustSize(wxSize
*size
, const wxWindow
*window
);
347 virtual wxRect
GetBorderDimensions(wxBorder border
) const;
348 virtual bool AreScrollbarsInsideBorder() const;
350 virtual wxSize
GetScrollbarArrowSize() const
351 { return m_sizeScrollbarArrow
; }
352 virtual wxRect
GetScrollbarRect(const wxScrollBar
*scrollbar
,
353 wxScrollBar
::Element elem
,
354 int thumbPos
= -1) const;
355 virtual wxCoord
GetScrollbarSize(const wxScrollBar
*scrollbar
);
356 virtual wxHitTest
HitTestScrollbar(const wxScrollBar
*scrollbar
,
357 const wxPoint
& pt
) const;
358 virtual wxCoord
ScrollbarToPixel(const wxScrollBar
*scrollbar
,
360 virtual int PixelToScrollbar(const wxScrollBar
*scrollbar
, wxCoord coord
);
361 virtual wxCoord
GetListboxItemHeight(wxCoord fontHeight
)
362 { return fontHeight
+ 2; }
363 virtual wxSize
GetCheckBitmapSize() const
364 { return wxSize(13, 13); }
365 virtual wxSize
GetRadioBitmapSize() const
366 { return wxSize(12, 12); }
367 virtual wxCoord
GetCheckItemMargin() const
370 virtual wxSize
GetToolBarButtonSize(wxCoord
*separator
) const
371 { if ( separator
) *separator
= 5; return wxSize(16, 15); }
372 virtual wxSize
GetToolBarMargin() const
373 { return wxSize(4, 4); }
375 virtual wxRect
GetTextTotalArea(const wxTextCtrl
*text
,
376 const wxRect
& rect
) const;
377 virtual wxRect
GetTextClientArea(const wxTextCtrl
*text
,
379 wxCoord
*extraSpaceBeyond
) const;
381 virtual wxSize
GetTabIndent() const { return wxSize(2, 2); }
382 virtual wxSize
GetTabPadding() const { return wxSize(6, 5); }
384 virtual wxCoord
GetSliderDim() const { return SLIDER_THUMB_LENGTH
+ 2*BORDER_THICKNESS
; }
385 virtual wxCoord
GetSliderTickLen() const { return SLIDER_TICK_LENGTH
; }
386 virtual wxRect
GetSliderShaftRect(const wxRect
& rect
,
388 wxOrientation orient
,
389 long style
= 0) const;
390 virtual wxSize
GetSliderThumbSize(const wxRect
& rect
,
392 wxOrientation orient
) const;
393 virtual wxSize
GetProgressBarStep() const { return wxSize(16, 32); }
395 virtual wxSize
GetMenuBarItemSize(const wxSize
& sizeText
) const;
396 virtual wxMenuGeometryInfo
*GetMenuGeometry(wxWindow
*win
,
397 const wxMenu
& menu
) const;
399 virtual wxSize
GetStatusBarBorders(wxCoord
*borderBetweenFields
) const;
402 // helper of DrawLabel() and DrawCheckOrRadioButton()
403 void DoDrawLabel(wxDC
& dc
,
404 const wxString
& label
,
407 int alignment
= wxALIGN_LEFT
| wxALIGN_TOP
,
409 wxRect
*rectBounds
= NULL
,
410 const wxPoint
& focusOffset
411 = wxPoint(FOCUS_RECT_OFFSET_X
, FOCUS_RECT_OFFSET_Y
));
413 // common part of DrawLabel() and DrawItem()
414 void DrawFocusRect(wxDC
& dc
, const wxRect
& rect
);
416 // DrawLabel() and DrawButtonLabel() helper
417 void DrawLabelShadow(wxDC
& dc
,
418 const wxString
& label
,
423 // DrawButtonBorder() helper
424 void DoDrawBackground(wxDC
& dc
,
427 wxWindow
*window
= NULL
);
429 // DrawBorder() helpers: all of them shift and clip the DC after drawing
432 // just draw a rectangle with the given pen
433 void DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
435 // draw the lower left part of rectangle
436 void DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
);
438 // draw the rectange using the first brush for the left and top sides and
439 // the second one for the bottom and right ones
440 void DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
441 const wxPen
& pen1
, const wxPen
& pen2
);
443 // draw the normal 3D border
444 void DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
);
446 // draw the sunken 3D border
447 void DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
);
449 // draw the border used for scrollbar arrows
450 void DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
= false);
452 // public DrawArrow()s helper
453 void DrawArrow(wxDC
& dc
, const wxRect
& rect
,
454 wxArrowDirection arrowDir
, wxArrowStyle arrowStyle
);
456 // DrawArrowButton is used by DrawScrollbar and DrawComboButton
457 void DrawArrowButton(wxDC
& dc
, const wxRect
& rect
,
458 wxArrowDirection arrowDir
,
459 wxArrowStyle arrowStyle
);
461 // DrawCheckButton/DrawRadioButton helper
462 void DrawCheckOrRadioButton(wxDC
& dc
,
463 const wxString
& label
,
464 const wxBitmap
& bitmap
,
469 wxCoord focusOffsetY
);
471 // draw a normal or transposed line (useful for using the same code fo both
472 // horizontal and vertical widgets)
473 void DrawLine(wxDC
& dc
,
474 wxCoord x1
, wxCoord y1
,
475 wxCoord x2
, wxCoord y2
,
476 bool transpose
= false)
479 dc
.DrawLine(y1
, x1
, y2
, x2
);
481 dc
.DrawLine(x1
, y1
, x2
, y2
);
484 // get the standard check/radio button bitmap
485 wxBitmap
GetIndicator(IndicatorType indType
, int flags
);
486 wxBitmap
GetCheckBitmap(int flags
)
487 { return GetIndicator(IndicatorType_Check
, flags
); }
488 wxBitmap
GetRadioBitmap(int flags
)
489 { return GetIndicator(IndicatorType_Radio
, flags
); }
492 const wxColourScheme
*m_scheme
;
494 // the sizing parameters (TODO make them changeable)
495 wxSize m_sizeScrollbarArrow
;
497 // GDI objects we use for drawing
498 wxColour m_colDarkGrey
,
506 wxFont m_titlebarFont
;
508 // the checked and unchecked bitmaps for DrawCheckItem()
509 wxBitmap m_bmpCheckBitmaps
[IndicatorStatus_Max
];
511 // the bitmaps returned by GetIndicator()
512 wxBitmap m_bmpIndicators
[IndicatorType_Max
]
514 [IndicatorStatus_Max
];
517 wxBitmap m_bmpFrameButtons
[FrameButton_Max
];
519 // first row is for the normal state, second - for the disabled
520 wxBitmap m_bmpArrows
[Arrow_StateMax
][Arrow_Max
];
523 // ----------------------------------------------------------------------------
524 // wxWin32InputHandler and derived classes: process the keyboard and mouse
525 // messages according to Windows standards
526 // ----------------------------------------------------------------------------
528 class wxWin32InputHandler
: public wxInputHandler
531 wxWin32InputHandler(wxWin32Renderer
*renderer
);
533 virtual bool HandleKey(wxInputConsumer
*control
,
534 const wxKeyEvent
& event
,
536 virtual bool HandleMouse(wxInputConsumer
*control
,
537 const wxMouseEvent
& event
);
540 wxWin32Renderer
*m_renderer
;
543 class wxWin32ScrollBarInputHandler
: public wxStdScrollBarInputHandler
546 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
547 wxInputHandler
*handler
);
549 virtual bool HandleMouse(wxInputConsumer
*control
, const wxMouseEvent
& event
);
550 virtual bool HandleMouseMove(wxInputConsumer
*control
, const wxMouseEvent
& event
);
552 virtual bool OnScrollTimer(wxScrollBar
*scrollbar
,
553 const wxControlAction
& action
);
556 virtual bool IsAllowedButton(int button
) { return button
== 1; }
558 virtual void Highlight(wxScrollBar
* WXUNUSED(scrollbar
),
561 // we don't highlight anything
564 // the first and last event which caused the thumb to move
565 wxMouseEvent m_eventStartDrag
,
568 // have we paused the scrolling because the mouse moved?
571 // we remember the interval of the timer to be able to restart it
575 class wxWin32CheckboxInputHandler
: public wxStdCheckboxInputHandler
578 wxWin32CheckboxInputHandler(wxInputHandler
*handler
)
579 : wxStdCheckboxInputHandler(handler
) { }
581 virtual bool HandleKey(wxInputConsumer
*control
,
582 const wxKeyEvent
& event
,
586 class wxWin32TextCtrlInputHandler
: public wxStdTextCtrlInputHandler
589 wxWin32TextCtrlInputHandler(wxInputHandler
*handler
)
590 : wxStdTextCtrlInputHandler(handler
) { }
592 virtual bool HandleKey(wxInputConsumer
*control
,
593 const wxKeyEvent
& event
,
597 class wxWin32StatusBarInputHandler
: public wxStdInputHandler
600 wxWin32StatusBarInputHandler(wxInputHandler
*handler
);
602 virtual bool HandleMouse(wxInputConsumer
*consumer
,
603 const wxMouseEvent
& event
);
605 virtual bool HandleMouseMove(wxInputConsumer
*consumer
,
606 const wxMouseEvent
& event
);
609 // is the given point over the statusbar grip?
610 bool IsOnGrip(wxWindow
*statbar
, const wxPoint
& pt
) const;
613 // the cursor we had replaced with the resize one
614 wxCursor m_cursorOld
;
616 // was the mouse over the grip last time we checked?
620 class wxWin32SystemMenuEvtHandler
;
622 class wxWin32FrameInputHandler
: public wxStdFrameInputHandler
625 wxWin32FrameInputHandler(wxInputHandler
*handler
);
626 ~wxWin32FrameInputHandler();
628 virtual bool HandleMouse(wxInputConsumer
*control
,
629 const wxMouseEvent
& event
);
631 virtual bool HandleActivation(wxInputConsumer
*consumer
, bool activated
);
633 void PopupSystemMenu(wxTopLevelWindow
*window
, const wxPoint
& pos
) const;
636 // was the mouse over the grip last time we checked?
637 wxWin32SystemMenuEvtHandler
*m_menuHandler
;
640 // ----------------------------------------------------------------------------
641 // wxWin32ColourScheme: uses (default) Win32 colours
642 // ----------------------------------------------------------------------------
644 class wxWin32ColourScheme
: public wxColourScheme
647 virtual wxColour
Get(StdColour col
) const;
648 virtual wxColour
GetBackground(wxWindow
*win
) const;
651 // ----------------------------------------------------------------------------
652 // wxWin32ArtProvider
653 // ----------------------------------------------------------------------------
655 class wxWin32ArtProvider
: public wxArtProvider
658 virtual wxBitmap
CreateBitmap(const wxArtID
& id
,
659 const wxArtClient
& client
,
663 // ----------------------------------------------------------------------------
665 // ----------------------------------------------------------------------------
667 WX_DEFINE_ARRAY_PTR(wxInputHandler
*, wxArrayHandlers
);
669 class wxWin32Theme
: public wxTheme
673 virtual ~wxWin32Theme();
675 virtual wxRenderer
*GetRenderer();
676 virtual wxArtProvider
*GetArtProvider();
677 virtual wxInputHandler
*GetInputHandler(const wxString
& control
);
678 virtual wxColourScheme
*GetColourScheme();
681 // get the default input handler
682 wxInputHandler
*GetDefaultInputHandler();
684 wxWin32Renderer
*m_renderer
;
686 wxWin32ArtProvider
*m_artProvider
;
688 // the names of the already created handlers and the handlers themselves
689 // (these arrays are synchronized)
690 wxSortedArrayString m_handlerNames
;
691 wxArrayHandlers m_handlers
;
693 wxWin32InputHandler
*m_handlerDefault
;
695 wxWin32ColourScheme
*m_scheme
;
697 WX_DECLARE_THEME(win32
)
700 // ----------------------------------------------------------------------------
702 // ----------------------------------------------------------------------------
704 // frame buttons bitmaps
706 static const char *frame_button_close_xpm
[] = {
721 static const char *frame_button_help_xpm
[] = {
736 static const char *frame_button_maximize_xpm
[] = {
751 static const char *frame_button_minimize_xpm
[] = {
766 static const char *frame_button_restore_xpm
[] = {
783 static const char *checked_menu_xpm
[] = {
784 /* columns rows colors chars-per-pixel */
800 static const char *selected_checked_menu_xpm
[] = {
801 /* columns rows colors chars-per-pixel */
817 static const char *disabled_checked_menu_xpm
[] = {
818 /* columns rows colors chars-per-pixel */
835 static const char *selected_disabled_checked_menu_xpm
[] = {
836 /* columns rows colors chars-per-pixel */
852 // checkbox and radiobox bitmaps below
854 static const char *checked_xpm
[] = {
855 /* columns rows colors chars-per-pixel */
878 static const char *pressed_checked_xpm
[] = {
879 /* columns rows colors chars-per-pixel */
901 static const char *pressed_disabled_checked_xpm
[] = {
902 /* columns rows colors chars-per-pixel */
924 static const char *checked_item_xpm
[] = {
925 /* columns rows colors chars-per-pixel */
946 static const char *unchecked_xpm
[] = {
947 /* columns rows colors chars-per-pixel */
970 static const char *pressed_unchecked_xpm
[] = {
971 /* columns rows colors chars-per-pixel */
993 static const char *unchecked_item_xpm
[] = {
994 /* columns rows colors chars-per-pixel */
1014 static const char *undetermined_xpm
[] = {
1015 /* columns rows colors chars-per-pixel */
1038 static const char *pressed_undetermined_xpm
[] = {
1039 /* columns rows colors chars-per-pixel */
1062 static const char *checked_radio_xpm
[] = {
1063 /* columns rows colors chars-per-pixel */
1086 static const char *pressed_checked_radio_xpm
[] = {
1087 /* columns rows colors chars-per-pixel */
1110 static const char *pressed_disabled_checked_radio_xpm
[] = {
1111 /* columns rows colors chars-per-pixel */
1134 static const char *unchecked_radio_xpm
[] = {
1135 /* columns rows colors chars-per-pixel */
1158 static const char *pressed_unchecked_radio_xpm
[] = {
1159 /* columns rows colors chars-per-pixel */
1182 static const char **
1183 xpmIndicators
[IndicatorType_Max
][IndicatorState_Max
][IndicatorStatus_Max
] =
1188 { checked_xpm
, unchecked_xpm
, undetermined_xpm
},
1191 { pressed_checked_xpm
, pressed_unchecked_xpm
, pressed_undetermined_xpm
},
1194 { pressed_disabled_checked_xpm
, pressed_unchecked_xpm
, pressed_disabled_checked_xpm
},
1200 { checked_radio_xpm
, unchecked_radio_xpm
, NULL
},
1203 { pressed_checked_radio_xpm
, pressed_unchecked_radio_xpm
, NULL
},
1206 { pressed_disabled_checked_radio_xpm
, pressed_unchecked_radio_xpm
, NULL
},
1212 { checked_menu_xpm
, NULL
, NULL
},
1215 { selected_checked_menu_xpm
, NULL
, NULL
},
1218 { disabled_checked_menu_xpm
, NULL
, NULL
},
1220 // disabled selected state
1221 { selected_disabled_checked_menu_xpm
, NULL
, NULL
},
1225 static const char **xpmChecked
[IndicatorStatus_Max
] =
1231 // ============================================================================
1233 // ============================================================================
1235 WX_IMPLEMENT_THEME(wxWin32Theme
, win32
, wxTRANSLATE("Win32 theme"));
1237 // ----------------------------------------------------------------------------
1239 // ----------------------------------------------------------------------------
1241 wxWin32Theme
::wxWin32Theme()
1245 m_handlerDefault
= NULL
;
1246 m_artProvider
= NULL
;
1249 wxWin32Theme
::~wxWin32Theme()
1251 size_t count
= m_handlers
.GetCount();
1252 for ( size_t n
= 0; n
< count
; n
++ )
1254 if ( m_handlers
[n
] != m_handlerDefault
)
1255 delete m_handlers
[n
];
1258 delete m_handlerDefault
;
1262 wxArtProvider
::RemoveProvider(m_artProvider
);
1265 wxRenderer
*wxWin32Theme
::GetRenderer()
1269 m_renderer
= new wxWin32Renderer(GetColourScheme());
1275 wxArtProvider
*wxWin32Theme
::GetArtProvider()
1277 if ( !m_artProvider
)
1279 m_artProvider
= new wxWin32ArtProvider
;
1282 return m_artProvider
;
1285 wxInputHandler
*wxWin32Theme
::GetDefaultInputHandler()
1287 if ( !m_handlerDefault
)
1289 m_handlerDefault
= new wxWin32InputHandler(m_renderer
);
1292 return m_handlerDefault
;
1295 wxInputHandler
*wxWin32Theme
::GetInputHandler(const wxString
& control
)
1297 wxInputHandler
*handler
;
1298 int n
= m_handlerNames
.Index(control
);
1299 if ( n
== wxNOT_FOUND
)
1301 // create a new handler
1302 if ( control
== wxINP_HANDLER_SCROLLBAR
)
1303 handler
= new wxWin32ScrollBarInputHandler(m_renderer
,
1304 GetDefaultInputHandler());
1306 else if ( control
== wxINP_HANDLER_BUTTON
)
1307 handler
= new wxStdButtonInputHandler(GetDefaultInputHandler());
1308 #endif // wxUSE_BUTTON
1310 else if ( control
== wxINP_HANDLER_CHECKBOX
)
1311 handler
= new wxWin32CheckboxInputHandler(GetDefaultInputHandler());
1312 #endif // wxUSE_CHECKBOX
1314 else if ( control
== wxINP_HANDLER_COMBOBOX
)
1315 handler
= new wxStdComboBoxInputHandler(GetDefaultInputHandler());
1316 #endif // wxUSE_COMBOBOX
1318 else if ( control
== wxINP_HANDLER_LISTBOX
)
1319 handler
= new wxStdListboxInputHandler(GetDefaultInputHandler());
1320 #endif // wxUSE_LISTBOX
1321 #if wxUSE_CHECKLISTBOX
1322 else if ( control
== wxINP_HANDLER_CHECKLISTBOX
)
1323 handler
= new wxStdCheckListboxInputHandler(GetDefaultInputHandler());
1324 #endif // wxUSE_CHECKLISTBOX
1326 else if ( control
== wxINP_HANDLER_TEXTCTRL
)
1327 handler
= new wxWin32TextCtrlInputHandler(GetDefaultInputHandler());
1328 #endif // wxUSE_TEXTCTRL
1330 else if ( control
== wxINP_HANDLER_SLIDER
)
1331 handler
= new wxStdSliderButtonInputHandler(GetDefaultInputHandler());
1332 #endif // wxUSE_SLIDER
1334 else if ( control
== wxINP_HANDLER_SPINBTN
)
1335 handler
= new wxStdSpinButtonInputHandler(GetDefaultInputHandler());
1336 #endif // wxUSE_SPINBTN
1338 else if ( control
== wxINP_HANDLER_NOTEBOOK
)
1339 handler
= new wxStdNotebookInputHandler(GetDefaultInputHandler());
1340 #endif // wxUSE_NOTEBOOK
1342 else if ( control
== wxINP_HANDLER_STATUSBAR
)
1343 handler
= new wxWin32StatusBarInputHandler(GetDefaultInputHandler());
1344 #endif // wxUSE_STATUSBAR
1346 else if ( control
== wxINP_HANDLER_TOOLBAR
)
1347 handler
= new wxStdToolbarInputHandler(GetDefaultInputHandler());
1348 #endif // wxUSE_TOOLBAR
1349 else if ( control
== wxINP_HANDLER_TOPLEVEL
)
1350 handler
= new wxWin32FrameInputHandler(GetDefaultInputHandler());
1352 handler
= GetDefaultInputHandler();
1354 n
= m_handlerNames
.Add(control
);
1355 m_handlers
.Insert(handler
, n
);
1357 else // we already have it
1359 handler
= m_handlers
[n
];
1365 wxColourScheme
*wxWin32Theme
::GetColourScheme()
1369 m_scheme
= new wxWin32ColourScheme
;
1374 // ============================================================================
1375 // wxWin32ColourScheme
1376 // ============================================================================
1378 wxColour wxWin32ColourScheme
::GetBackground(wxWindow
*win
) const
1381 if ( win
->UseBgCol() )
1383 // use the user specified colour
1384 col
= win
->GetBackgroundColour();
1387 if ( !win
->ShouldInheritColours() )
1389 wxTextCtrl
*text
= wxDynamicCast(win
, wxTextCtrl
);
1391 wxListBox
* listBox
= wxDynamicCast(win
, wxListBox
);
1399 if ( !win
->IsEnabled() ) // not IsEditable()
1405 // doesn't depend on the state
1412 col
= Get(CONTROL
); // Most controls should be this colour, not WINDOW
1416 int flags
= win
->GetStateFlags();
1418 // the colour set by the user should be used for the normal state
1419 // and for the states for which we don't have any specific colours
1420 if ( !col
.Ok() || (flags
& wxCONTROL_PRESSED
) != 0 )
1422 if ( wxDynamicCast(win
, wxScrollBar
) )
1423 col
= Get(flags
& wxCONTROL_PRESSED ? SCROLLBAR_PRESSED
1433 wxColour wxWin32ColourScheme
::Get(wxWin32ColourScheme
::StdColour col
) const
1437 // use the system colours under Windows
1438 #if defined(__WXMSW__)
1439 case WINDOW
: return wxColour(GetSysColor(COLOR_WINDOW
));
1441 case CONTROL_PRESSED
:
1442 case CONTROL_CURRENT
:
1443 case CONTROL
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1445 case CONTROL_TEXT
: return wxColour(GetSysColor(COLOR_BTNTEXT
));
1447 #if defined(COLOR_3DLIGHT)
1448 case SCROLLBAR
: return wxColour(GetSysColor(COLOR_3DLIGHT
));
1450 case SCROLLBAR
: return wxColour(0xe0e0e0);
1452 case SCROLLBAR_PRESSED
: return wxColour(GetSysColor(COLOR_BTNTEXT
));
1454 case HIGHLIGHT
: return wxColour(GetSysColor(COLOR_HIGHLIGHT
));
1455 case HIGHLIGHT_TEXT
: return wxColour(GetSysColor(COLOR_HIGHLIGHTTEXT
));
1457 #if defined(COLOR_3DDKSHADOW)
1458 case SHADOW_DARK
: return wxColour(GetSysColor(COLOR_3DDKSHADOW
));
1460 case SHADOW_DARK
: return wxColour(GetSysColor(COLOR_3DHADOW
));
1463 case CONTROL_TEXT_DISABLED
:
1464 case SHADOW_HIGHLIGHT
: return wxColour(GetSysColor(COLOR_BTNHIGHLIGHT
));
1466 case SHADOW_IN
: return wxColour(GetSysColor(COLOR_BTNFACE
));
1468 case CONTROL_TEXT_DISABLED_SHADOW
:
1469 case SHADOW_OUT
: return wxColour(GetSysColor(COLOR_BTNSHADOW
));
1471 case TITLEBAR
: return wxColour(GetSysColor(COLOR_INACTIVECAPTION
));
1472 case TITLEBAR_ACTIVE
: return wxColour(GetSysColor(COLOR_ACTIVECAPTION
));
1473 case TITLEBAR_TEXT
: return wxColour(GetSysColor(COLOR_INACTIVECAPTIONTEXT
));
1474 case TITLEBAR_ACTIVE_TEXT
: return wxColour(GetSysColor(COLOR_CAPTIONTEXT
));
1476 case DESKTOP
: return wxColour(0x808000);
1478 // use the standard Windows colours elsewhere
1479 case WINDOW
: return *wxWHITE
;
1481 case CONTROL_PRESSED
:
1482 case CONTROL_CURRENT
:
1483 case CONTROL
: return wxColour(0xc0c0c0);
1485 case CONTROL_TEXT
: return *wxBLACK
;
1487 case SCROLLBAR
: return wxColour(0xe0e0e0);
1488 case SCROLLBAR_PRESSED
: return *wxBLACK
;
1490 case HIGHLIGHT
: return wxColour(0x800000);
1491 case HIGHLIGHT_TEXT
: return wxColour(0xffffff);
1493 case SHADOW_DARK
: return *wxBLACK
;
1495 case CONTROL_TEXT_DISABLED
:return wxColour(0xe0e0e0);
1496 case SHADOW_HIGHLIGHT
: return wxColour(0xffffff);
1498 case SHADOW_IN
: return wxColour(0xc0c0c0);
1500 case CONTROL_TEXT_DISABLED_SHADOW
:
1501 case SHADOW_OUT
: return wxColour(0x7f7f7f);
1503 case TITLEBAR
: return wxColour(0xaeaaae);
1504 case TITLEBAR_ACTIVE
: return wxColour(0x820300);
1505 case TITLEBAR_TEXT
: return wxColour(0xc0c0c0);
1506 case TITLEBAR_ACTIVE_TEXT
:return *wxWHITE
;
1508 case DESKTOP
: return wxColour(0x808000);
1511 case GAUGE
: return Get(HIGHLIGHT
);
1515 wxFAIL_MSG(_T("invalid standard colour"));
1520 // ============================================================================
1522 // ============================================================================
1524 // ----------------------------------------------------------------------------
1526 // ----------------------------------------------------------------------------
1528 wxWin32Renderer
::wxWin32Renderer(const wxColourScheme
*scheme
)
1532 m_sizeScrollbarArrow
= wxSize(16, 16);
1534 // init colours and pens
1535 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
), 0, wxSOLID
);
1537 m_colDarkGrey
= wxSCHEME_COLOUR(scheme
, SHADOW_OUT
);
1538 m_penDarkGrey
= wxPen(m_colDarkGrey
, 0, wxSOLID
);
1540 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
), 0, wxSOLID
);
1542 m_colHighlight
= wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
);
1543 m_penHighlight
= wxPen(m_colHighlight
, 0, wxSOLID
);
1545 m_titlebarFont
= wxSystemSettings
::GetFont(wxSYS_DEFAULT_GUI_FONT
);
1546 m_titlebarFont
.SetWeight(wxFONTWEIGHT_BOLD
);
1548 // init the arrow bitmaps
1549 static const size_t ARROW_WIDTH
= 7;
1550 static const size_t ARROW_LENGTH
= 4;
1553 wxMemoryDC dcNormal
,
1556 for ( size_t n
= 0; n
< Arrow_Max
; n
++ )
1558 bool isVertical
= n
> Arrow_Right
;
1571 // disabled arrow is larger because of the shadow
1572 m_bmpArrows
[Arrow_Normal
][n
].Create(w
, h
);
1573 m_bmpArrows
[Arrow_Disabled
][n
].Create(w
+ 1, h
+ 1);
1575 dcNormal
.SelectObject(m_bmpArrows
[Arrow_Normal
][n
]);
1576 dcDisabled
.SelectObject(m_bmpArrows
[Arrow_Disabled
][n
]);
1578 dcNormal
.SetBackground(*wxWHITE_BRUSH
);
1579 dcDisabled
.SetBackground(*wxWHITE_BRUSH
);
1583 dcNormal
.SetPen(m_penBlack
);
1584 dcDisabled
.SetPen(m_penDarkGrey
);
1586 // calculate the position of the point of the arrow
1590 x1
= (ARROW_WIDTH
- 1)/2;
1591 y1
= n
== Arrow_Up ?
0 : ARROW_LENGTH
- 1;
1595 x1
= n
== Arrow_Left ?
0 : ARROW_LENGTH
- 1;
1596 y1
= (ARROW_WIDTH
- 1)/2;
1607 for ( size_t i
= 0; i
< ARROW_LENGTH
; i
++ )
1609 dcNormal
.DrawLine(x1
, y1
, x2
, y2
);
1610 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1617 if ( n
== Arrow_Up
)
1628 else // left or right arrow
1633 if ( n
== Arrow_Left
)
1646 // draw the shadow for the disabled one
1647 dcDisabled
.SetPen(m_penHighlight
);
1652 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1656 x1
= ARROW_LENGTH
- 1;
1657 y1
= (ARROW_WIDTH
- 1)/2 + 1;
1660 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1661 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1666 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1670 x1
= ARROW_WIDTH
- 1;
1672 x2
= (ARROW_WIDTH
- 1)/2;
1674 dcDisabled
.DrawLine(x1
, y1
, x2
, y2
);
1675 dcDisabled
.DrawLine(++x1
, y1
, x2
, ++y2
);
1680 // create the inverted bitmap but only for the right arrow as we only
1681 // use it for the menus
1682 if ( n
== Arrow_Right
)
1684 m_bmpArrows
[Arrow_Inverted
][n
].Create(w
, h
);
1685 dcInverse
.SelectObject(m_bmpArrows
[Arrow_Inverted
][n
]);
1687 dcInverse
.Blit(0, 0, w
, h
,
1690 dcInverse
.SelectObject(wxNullBitmap
);
1692 mask
= new wxMask(m_bmpArrows
[Arrow_Inverted
][n
], *wxBLACK
);
1693 m_bmpArrows
[Arrow_Inverted
][n
].SetMask(mask
);
1695 m_bmpArrows
[Arrow_InvertedDisabled
][n
].Create(w
, h
);
1696 dcInverse
.SelectObject(m_bmpArrows
[Arrow_InvertedDisabled
][n
]);
1698 dcInverse
.Blit(0, 0, w
, h
,
1701 dcInverse
.SelectObject(wxNullBitmap
);
1703 mask
= new wxMask(m_bmpArrows
[Arrow_InvertedDisabled
][n
], *wxBLACK
);
1704 m_bmpArrows
[Arrow_InvertedDisabled
][n
].SetMask(mask
);
1707 dcNormal
.SelectObject(wxNullBitmap
);
1708 dcDisabled
.SelectObject(wxNullBitmap
);
1710 mask
= new wxMask(m_bmpArrows
[Arrow_Normal
][n
], *wxWHITE
);
1711 m_bmpArrows
[Arrow_Normal
][n
].SetMask(mask
);
1712 mask
= new wxMask(m_bmpArrows
[Arrow_Disabled
][n
], *wxWHITE
);
1713 m_bmpArrows
[Arrow_Disabled
][n
].SetMask(mask
);
1715 m_bmpArrows
[Arrow_Pressed
][n
] = m_bmpArrows
[Arrow_Normal
][n
];
1718 // init the frame buttons bitmaps
1719 m_bmpFrameButtons
[FrameButton_Close
] = wxBitmap(frame_button_close_xpm
);
1720 m_bmpFrameButtons
[FrameButton_Minimize
] = wxBitmap(frame_button_minimize_xpm
);
1721 m_bmpFrameButtons
[FrameButton_Maximize
] = wxBitmap(frame_button_maximize_xpm
);
1722 m_bmpFrameButtons
[FrameButton_Restore
] = wxBitmap(frame_button_restore_xpm
);
1723 m_bmpFrameButtons
[FrameButton_Help
] = wxBitmap(frame_button_help_xpm
);
1726 // ----------------------------------------------------------------------------
1728 // ----------------------------------------------------------------------------
1731 The raised border in Win32 looks like this:
1733 IIIIIIIIIIIIIIIIIIIIIIB
1735 I GB I = white (HILIGHT)
1736 I GB H = light grey (LIGHT)
1737 I GB G = dark grey (SHADOI)
1738 I GB B = black (DKSHADOI)
1739 I GB I = hIghlight (COLOR_3DHILIGHT)
1741 IGGGGGGGGGGGGGGGGGGGGGB
1742 BBBBBBBBBBBBBBBBBBBBBBB
1744 The sunken border looks like this:
1746 GGGGGGGGGGGGGGGGGGGGGGI
1747 GBBBBBBBBBBBBBBBBBBBBHI
1754 GHHHHHHHHHHHHHHHHHHHHHI
1755 IIIIIIIIIIIIIIIIIIIIIII
1757 The static border (used for the controls which don't get focus) is like
1760 GGGGGGGGGGGGGGGGGGGGGGW
1768 WWWWWWWWWWWWWWWWWWWWWWW
1770 The most complicated is the double border:
1772 HHHHHHHHHHHHHHHHHHHHHHB
1773 HWWWWWWWWWWWWWWWWWWWWGB
1774 HWHHHHHHHHHHHHHHHHHHHGB
1779 HWHHHHHHHHHHHHHHHHHHHGB
1780 HGGGGGGGGGGGGGGGGGGGGGB
1781 BBBBBBBBBBBBBBBBBBBBBBB
1783 And the simple border is, well, simple:
1785 BBBBBBBBBBBBBBBBBBBBBBB
1794 BBBBBBBBBBBBBBBBBBBBBBB
1797 void wxWin32Renderer
::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1801 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1802 dc
.DrawRectangle(*rect
);
1808 void wxWin32Renderer
::DrawHalfRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
1810 // draw the bottom and right sides
1812 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1813 rect
->GetRight() + 1, rect
->GetBottom());
1814 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1815 rect
->GetRight(), rect
->GetBottom());
1821 void wxWin32Renderer
::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
1822 const wxPen
& pen1
, const wxPen
& pen2
)
1824 // draw the rectangle
1826 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
1827 rect
->GetLeft(), rect
->GetBottom());
1828 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
1829 rect
->GetRight(), rect
->GetTop());
1831 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
1832 rect
->GetRight(), rect
->GetBottom());
1833 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
1834 rect
->GetRight() + 1, rect
->GetBottom());
1840 void wxWin32Renderer
::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
1842 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
1843 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
1846 void wxWin32Renderer
::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
1848 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
1849 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
1852 void wxWin32Renderer
::DrawArrowBorder(wxDC
& dc
, wxRect
*rect
, bool isPressed
)
1856 DrawRect(dc
, rect
, m_penDarkGrey
);
1858 // the arrow is usually drawn inside border of width 2 and is offset by
1859 // another pixel in both directions when it's pressed - as the border
1860 // in this case is more narrow as well, we have to adjust rect like
1868 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
1869 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
1873 void wxWin32Renderer
::DrawBorder(wxDC
& dc
,
1875 const wxRect
& rectTotal
,
1876 int WXUNUSED(flags
),
1881 wxRect rect
= rectTotal
;
1885 case wxBORDER_SUNKEN
:
1886 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1888 DrawSunkenBorder(dc
, &rect
);
1892 case wxBORDER_STATIC
:
1893 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
1896 case wxBORDER_RAISED
:
1897 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1899 DrawRaisedBorder(dc
, &rect
);
1903 case wxBORDER_DOUBLE
:
1904 DrawArrowBorder(dc
, &rect
);
1905 DrawRect(dc
, &rect
, m_penLightGrey
);
1908 case wxBORDER_SIMPLE
:
1909 for ( i
= 0; i
< BORDER_THICKNESS
/ 2; i
++ )
1911 DrawRect(dc
, &rect
, m_penBlack
);
1916 wxFAIL_MSG(_T("unknown border type"));
1919 case wxBORDER_DEFAULT
:
1928 wxRect wxWin32Renderer
::GetBorderDimensions(wxBorder border
) const
1933 case wxBORDER_RAISED
:
1934 case wxBORDER_SUNKEN
:
1935 width
= BORDER_THICKNESS
;
1938 case wxBORDER_SIMPLE
:
1939 case wxBORDER_STATIC
:
1943 case wxBORDER_DOUBLE
:
1949 // char *crash = NULL;
1951 wxFAIL_MSG(_T("unknown border type"));
1955 case wxBORDER_DEFAULT
:
1965 rect
.height
= width
;
1970 bool wxWin32Renderer
::AreScrollbarsInsideBorder() const
1975 // ----------------------------------------------------------------------------
1977 // ----------------------------------------------------------------------------
1979 void wxWin32Renderer
::DrawTextBorder(wxDC
& dc
,
1985 // text controls are not special under windows
1986 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
1989 void wxWin32Renderer
::DrawButtonBorder(wxDC
& dc
,
1990 const wxRect
& rectTotal
,
1994 wxRect rect
= rectTotal
;
1996 if ( flags
& wxCONTROL_PRESSED
)
1998 // button pressed: draw a double border around it
1999 DrawRect(dc
, &rect
, m_penBlack
);
2000 DrawRect(dc
, &rect
, m_penDarkGrey
);
2004 // button not pressed
2006 if ( flags
& (wxCONTROL_FOCUSED
| wxCONTROL_ISDEFAULT
) )
2008 // button either default or focused (or both): add an extra border around it
2009 DrawRect(dc
, &rect
, m_penBlack
);
2012 // now draw a normal button
2013 DrawShadedRect(dc
, &rect
, m_penHighlight
, m_penBlack
);
2014 DrawHalfRect(dc
, &rect
, m_penDarkGrey
);
2023 // ----------------------------------------------------------------------------
2025 // ----------------------------------------------------------------------------
2027 void wxWin32Renderer
::DrawHorizontalLine(wxDC
& dc
,
2028 wxCoord y
, wxCoord x1
, wxCoord x2
)
2030 dc
.SetPen(m_penDarkGrey
);
2031 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
2032 dc
.SetPen(m_penHighlight
);
2034 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
2037 void wxWin32Renderer
::DrawVerticalLine(wxDC
& dc
,
2038 wxCoord x
, wxCoord y1
, wxCoord y2
)
2040 dc
.SetPen(m_penDarkGrey
);
2041 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
2042 dc
.SetPen(m_penHighlight
);
2044 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
2047 void wxWin32Renderer
::DrawFrame(wxDC
& dc
,
2048 const wxString
& label
,
2054 wxCoord height
= 0; // of the label
2055 wxRect rectFrame
= rect
;
2056 if ( !label
.empty() )
2058 // the text should touch the top border of the rect, so the frame
2059 // itself should be lower
2060 dc
.GetTextExtent(label
, NULL
, &height
);
2061 rectFrame
.y
+= height
/ 2;
2062 rectFrame
.height
-= height
/ 2;
2064 // we have to draw each part of the frame individually as we can't
2065 // erase the background beyond the label as it might contain some
2066 // pixmap already, so drawing everything and then overwriting part of
2067 // the frame with label doesn't work
2069 // TODO: the +5 and space insertion should be customizable
2072 rectText
.x
= rectFrame
.x
+ 5;
2073 rectText
.y
= rect
.y
;
2074 rectText
.width
= rectFrame
.width
- 7; // +2 border width
2075 rectText
.height
= height
;
2078 label2
<< _T(' ') << label
<< _T(' ');
2079 if ( indexAccel
!= -1 )
2081 // adjust it as we prepended a space
2086 DrawLabel(dc
, label2
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
2088 StandardDrawFrame(dc
, rectFrame
, rectLabel
);
2092 // just draw the complete frame
2093 DrawShadedRect(dc
, &rectFrame
, m_penDarkGrey
, m_penHighlight
);
2094 DrawShadedRect(dc
, &rectFrame
, m_penHighlight
, m_penDarkGrey
);
2098 // ----------------------------------------------------------------------------
2100 // ----------------------------------------------------------------------------
2102 void wxWin32Renderer
::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
2104 // VZ: this doesn't work under Windows, the dotted pen has dots of 3
2105 // pixels each while we really need dots here... PS_ALTERNATE might
2106 // work, but it is for NT 5 only
2108 DrawRect(dc
, &rect
, wxPen(*wxBLACK
, 0, wxDOT
));
2110 // draw the pixels manually: note that to behave in the same manner as
2111 // DrawRect(), we must exclude the bottom and right borders from the
2113 wxCoord x1
= rect
.GetLeft(),
2115 x2
= rect
.GetRight(),
2116 y2
= rect
.GetBottom();
2118 dc
.SetPen(wxPen(*wxBLACK
, 0, wxSOLID
));
2120 // this seems to be closer than what Windows does than wxINVERT although
2121 // I'm still not sure if it's correct
2122 dc
.SetLogicalFunction(wxAND_REVERSE
);
2125 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
2126 dc
.DrawPoint(z
, rect
.GetTop());
2128 wxCoord shift
= z
== x2 ?
0 : 1;
2129 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
2130 dc
.DrawPoint(x2
, z
);
2132 shift
= z
== y2 ?
0 : 1;
2133 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
2134 dc
.DrawPoint(z
, y2
);
2136 shift
= z
== x1 ?
0 : 1;
2137 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
2138 dc
.DrawPoint(x1
, z
);
2140 dc
.SetLogicalFunction(wxCOPY
);
2144 void wxWin32Renderer
::DrawLabelShadow(wxDC
& dc
,
2145 const wxString
& label
,
2150 // draw shadow of the text
2151 dc
.SetTextForeground(m_colHighlight
);
2152 wxRect rectShadow
= rect
;
2155 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
2157 // make the text grey
2158 dc
.SetTextForeground(m_colDarkGrey
);
2161 void wxWin32Renderer
::DrawLabel(wxDC
& dc
,
2162 const wxString
& label
,
2169 DoDrawLabel(dc
, label
, rect
, flags
, alignment
, indexAccel
, rectBounds
);
2172 void wxWin32Renderer
::DoDrawLabel(wxDC
& dc
,
2173 const wxString
& label
,
2179 const wxPoint
& focusOffset
)
2181 // the underscores are not drawn for focused controls in wxMSW
2182 if ( flags
& wxCONTROL_FOCUSED
)
2187 if ( flags
& wxCONTROL_DISABLED
)
2189 // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
2190 // currently only can happen for a menu item and it seems that Windows
2191 // doesn't draw the shadow in this case, so we don't do it neither
2192 if ( flags
& wxCONTROL_SELECTED
)
2194 // just make the label text greyed out
2195 dc
.SetTextForeground(m_colDarkGrey
);
2197 else // draw normal disabled label
2199 DrawLabelShadow(dc
, label
, rect
, alignment
, indexAccel
);
2204 dc
.DrawLabel(label
, wxNullBitmap
, rect
, alignment
, indexAccel
, &rectLabel
);
2206 if ( flags
& wxCONTROL_DISABLED
)
2208 // restore the fg colour
2209 dc
.SetTextForeground(*wxBLACK
);
2212 if ( flags
& wxCONTROL_FOCUSED
)
2214 if ( focusOffset
.x
|| focusOffset
.y
)
2216 rectLabel
.Inflate(focusOffset
.x
, focusOffset
.y
);
2219 DrawFocusRect(dc
, rectLabel
);
2223 *rectBounds
= rectLabel
;
2226 void wxWin32Renderer
::DrawButtonLabel(wxDC
& dc
,
2227 const wxString
& label
,
2228 const wxBitmap
& image
,
2235 // the underscores are not drawn for focused controls in wxMSW
2236 if ( flags
& wxCONTROL_PRESSED
)
2241 wxRect rectLabel
= rect
;
2242 if ( !label
.empty() )
2244 // shift the label if a button is pressed
2245 if ( flags
& wxCONTROL_PRESSED
)
2251 if ( flags
& wxCONTROL_DISABLED
)
2253 DrawLabelShadow(dc
, label
, rectLabel
, alignment
, indexAccel
);
2256 // leave enough space for the focus rectangle
2257 if ( flags
& wxCONTROL_FOCUSED
)
2259 rectLabel
.Inflate(-2);
2263 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
2265 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
2267 if ( flags
& wxCONTROL_PRESSED
)
2269 // the focus rectangle is never pressed, so undo the shift done
2277 DrawFocusRect(dc
, rectLabel
);
2281 // ----------------------------------------------------------------------------
2282 // (check)listbox items
2283 // ----------------------------------------------------------------------------
2285 void wxWin32Renderer
::DrawItem(wxDC
& dc
,
2286 const wxString
& label
,
2290 wxDCTextColourChanger
colChanger(dc
);
2292 if ( flags
& wxCONTROL_SELECTED
)
2294 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
2296 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
2297 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
2298 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
2299 dc
.DrawRectangle(rect
);
2302 wxRect rectText
= rect
;
2304 rectText
.width
-= 2;
2305 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
2307 if ( flags
& wxCONTROL_FOCUSED
)
2309 DrawFocusRect(dc
, rect
);
2313 void wxWin32Renderer
::DrawCheckItem(wxDC
& dc
,
2314 const wxString
& label
,
2315 const wxBitmap
& bitmap
,
2324 else // use default bitmap
2326 IndicatorStatus i
= flags
& wxCONTROL_CHECKED
2327 ? IndicatorStatus_Checked
2328 : IndicatorStatus_Unchecked
;
2330 if ( !m_bmpCheckBitmaps
[i
].Ok() )
2332 m_bmpCheckBitmaps
[i
] = wxBitmap(xpmChecked
[i
]);
2335 bmp
= m_bmpCheckBitmaps
[i
];
2338 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2 - 1,
2339 true /* use mask */);
2341 wxRect rectLabel
= rect
;
2342 int bmpWidth
= bmp
.GetWidth();
2343 rectLabel
.x
+= bmpWidth
;
2344 rectLabel
.width
-= bmpWidth
;
2346 DrawItem(dc
, label
, rectLabel
, flags
);
2349 // ----------------------------------------------------------------------------
2350 // check/radio buttons
2351 // ----------------------------------------------------------------------------
2353 wxBitmap wxWin32Renderer
::GetIndicator(IndicatorType indType
, int flags
)
2355 IndicatorState indState
;
2356 if ( flags
& wxCONTROL_SELECTED
)
2357 indState
= flags
& wxCONTROL_DISABLED ? IndicatorState_SelectedDisabled
2358 : IndicatorState_Selected
;
2359 else if ( flags
& wxCONTROL_DISABLED
)
2360 indState
= IndicatorState_Disabled
;
2361 else if ( flags
& wxCONTROL_PRESSED
)
2362 indState
= IndicatorState_Pressed
;
2364 indState
= IndicatorState_Normal
;
2366 IndicatorStatus indStatus
= flags
& wxCONTROL_CHECKED
2367 ? IndicatorStatus_Checked
2368 : ( flags
& wxCONTROL_UNDETERMINED
2369 ? IndicatorStatus_Undeterminated
2370 : IndicatorStatus_Unchecked
);
2372 wxBitmap bmp
= m_bmpIndicators
[indType
][indState
][indStatus
];
2375 const char **xpm
= xpmIndicators
[indType
][indState
][indStatus
];
2378 // create and cache it
2379 bmp
= wxBitmap(xpm
);
2380 m_bmpIndicators
[indType
][indState
][indStatus
] = bmp
;
2387 void wxWin32Renderer
::DrawCheckOrRadioButton(wxDC
& dc
,
2388 const wxString
& label
,
2389 const wxBitmap
& bitmap
,
2394 wxCoord focusOffsetY
)
2396 // calculate the position of the bitmap and of the label
2397 wxCoord heightBmp
= bitmap
.GetHeight();
2399 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
2402 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
2403 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
2405 // align label vertically with the bitmap - looks nicer like this
2406 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
2408 // calc horz position
2409 if ( align
== wxALIGN_RIGHT
)
2411 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
2412 rectLabel
.x
= rect
.x
+ 3;
2413 rectLabel
.SetRight(xBmp
);
2415 else // normal (checkbox to the left of the text) case
2418 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
2419 rectLabel
.SetRight(rect
.GetRight());
2422 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, true /* use mask */);
2425 dc
, label
, rectLabel
,
2427 wxALIGN_LEFT
| wxALIGN_TOP
,
2429 NULL
, // we don't need bounding rect
2430 // use custom vert focus rect offset
2431 wxPoint(FOCUS_RECT_OFFSET_X
, focusOffsetY
)
2435 void wxWin32Renderer
::DrawRadioButton(wxDC
& dc
,
2436 const wxString
& label
,
2437 const wxBitmap
& bitmap
,
2447 bmp
= GetRadioBitmap(flags
);
2449 DrawCheckOrRadioButton(dc
, label
,
2451 rect
, flags
, align
, indexAccel
,
2452 FOCUS_RECT_OFFSET_Y
); // default focus rect offset
2455 void wxWin32Renderer
::DrawCheckButton(wxDC
& dc
,
2456 const wxString
& label
,
2457 const wxBitmap
& bitmap
,
2467 bmp
= GetCheckBitmap(flags
);
2469 DrawCheckOrRadioButton(dc
, label
,
2471 rect
, flags
, align
, indexAccel
,
2472 0); // no focus rect offset for checkboxes
2475 void wxWin32Renderer
::DrawToolBarButton(wxDC
& dc
,
2476 const wxString
& label
,
2477 const wxBitmap
& bitmap
,
2478 const wxRect
& rectOrig
,
2482 if (style
== wxTOOL_STYLE_BUTTON
)
2484 wxRect rect
= rectOrig
;
2485 rect
.Deflate(BORDER_THICKNESS
);
2487 if ( flags
& wxCONTROL_PRESSED
)
2489 DrawBorder(dc
, wxBORDER_SUNKEN
, rect
, flags
);
2491 else if ( flags
& wxCONTROL_CURRENT
)
2493 DrawBorder(dc
, wxBORDER_RAISED
, rect
, flags
);
2496 dc
.DrawLabel(label
, bitmap
, rect
, wxALIGN_CENTRE
);
2498 else if (style
== wxTOOL_STYLE_SEPARATOR
)
2500 // leave a small gap aroudn the line, also account for the toolbar
2502 if(rectOrig
.height
> rectOrig
.width
)
2505 DrawVerticalLine(dc
, rectOrig
.x
+ rectOrig
.width
/2,
2506 rectOrig
.y
+ 2*BORDER_THICKNESS
,
2507 rectOrig
.GetBottom() - BORDER_THICKNESS
);
2512 DrawHorizontalLine(dc
, rectOrig
.y
+ rectOrig
.height
/2,
2513 rectOrig
.x
+ 2*BORDER_THICKNESS
,
2514 rectOrig
.GetRight() - BORDER_THICKNESS
);
2517 // don't draw wxTOOL_STYLE_CONTROL
2520 // ----------------------------------------------------------------------------
2522 // ----------------------------------------------------------------------------
2524 void wxWin32Renderer
::DrawTextLine(wxDC
& dc
,
2525 const wxString
& text
,
2531 // nothing special to do here
2532 StandardDrawTextLine(dc
, text
, rect
, selStart
, selEnd
, flags
);
2536 wxWin32Renderer
::DrawLineWrapMark(wxDC
& WXUNUSED(dc
),
2537 const wxRect
& WXUNUSED(rect
))
2539 // we don't draw them
2542 // ----------------------------------------------------------------------------
2544 // ----------------------------------------------------------------------------
2546 void wxWin32Renderer
::DrawTab(wxDC
& dc
,
2547 const wxRect
& rectOrig
,
2549 const wxString
& label
,
2550 const wxBitmap
& bitmap
,
2554 #define SELECT_FOR_VERTICAL(X,Y) ( isVertical ? Y : X )
2555 #define REVERSE_FOR_VERTICAL(X,Y) \
2556 SELECT_FOR_VERTICAL(X,Y) \
2558 SELECT_FOR_VERTICAL(Y,X)
2560 wxRect rect
= rectOrig
;
2562 bool isVertical
= ( dir
== wxLEFT
) || ( dir
== wxRIGHT
);
2564 // the current tab is drawn indented (to the top for default case) and
2565 // bigger than the other ones
2566 const wxSize indent
= GetTabIndent();
2567 if ( flags
& wxCONTROL_SELECTED
)
2569 rect
.Inflate( SELECT_FOR_VERTICAL( indent
.x
, 0),
2570 SELECT_FOR_VERTICAL( 0, indent
.y
));
2574 wxFAIL_MSG(_T("invaild notebook tab orientation"));
2581 rect
.height
+= indent
.y
;
2588 rect
.width
+= indent
.x
;
2593 // draw the text, image and the focus around them (if necessary)
2594 wxRect
rectLabel( REVERSE_FOR_VERTICAL(rect
.x
,rect
.y
),
2595 REVERSE_FOR_VERTICAL(rect
.width
,rect
.height
)
2597 rectLabel
.Deflate(1, 1);
2600 // draw it horizontally into memory and rotate for screen
2602 wxBitmap bitmapRotated
,
2603 bitmapMem( rectLabel
.x
+ rectLabel
.width
,
2604 rectLabel
.y
+ rectLabel
.height
);
2605 dcMem
.SelectObject(bitmapMem
);
2606 dcMem
.SetBackground(dc
.GetBackground());
2607 dcMem
.SetFont(dc
.GetFont());
2608 dcMem
.SetTextForeground(dc
.GetTextForeground());
2610 bitmapRotated
= wxBitmap( wxImage( bitmap
.ConvertToImage() ).Rotate90(dir
==wxLEFT
) );
2611 DrawButtonLabel(dcMem
, label
, bitmapRotated
, rectLabel
,
2612 flags
, wxALIGN_CENTRE
, indexAccel
);
2613 dcMem
.SelectObject(wxNullBitmap
);
2614 bitmapMem
= bitmapMem
.GetSubBitmap(rectLabel
);
2615 bitmapMem
= wxBitmap(wxImage(bitmapMem
.ConvertToImage()).Rotate90(dir
==wxRIGHT
));
2616 dc
.DrawBitmap(bitmapMem
, rectLabel
.y
, rectLabel
.x
, false);
2620 DrawButtonLabel(dc
, label
, bitmap
, rectLabel
,
2621 flags
, wxALIGN_CENTRE
, indexAccel
);
2624 // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
2625 static const wxCoord CUTOFF
= 2; // radius of the rounded corner
2626 wxCoord x
= SELECT_FOR_VERTICAL(rect
.x
,rect
.y
),
2627 y
= SELECT_FOR_VERTICAL(rect
.y
,rect
.x
),
2628 x2
= SELECT_FOR_VERTICAL(rect
.GetRight(),rect
.GetBottom()),
2629 y2
= SELECT_FOR_VERTICAL(rect
.GetBottom(),rect
.GetRight());
2631 // FIXME: all this code will break if the tab indent or the border width,
2632 // it is tied to the fact that both of them are equal to 2
2638 // left orientation looks like top but IsVertical makes x and y reversed
2640 // top is not vertical so use coordinates in written order
2641 dc
.SetPen(m_penHighlight
);
2642 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
, y2
),
2643 REVERSE_FOR_VERTICAL(x
, y
+ CUTOFF
));
2644 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
, y
+ CUTOFF
),
2645 REVERSE_FOR_VERTICAL(x
+ CUTOFF
, y
));
2646 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
+ CUTOFF
, y
),
2647 REVERSE_FOR_VERTICAL(x2
- CUTOFF
+ 1, y
));
2649 dc
.SetPen(m_penBlack
);
2650 dc
.DrawLine(REVERSE_FOR_VERTICAL(x2
, y2
),
2651 REVERSE_FOR_VERTICAL(x2
, y
+ CUTOFF
));
2652 dc
.DrawLine(REVERSE_FOR_VERTICAL(x2
, y
+ CUTOFF
),
2653 REVERSE_FOR_VERTICAL(x2
- CUTOFF
, y
));
2655 dc
.SetPen(m_penDarkGrey
);
2656 dc
.DrawLine(REVERSE_FOR_VERTICAL(x2
- 1, y2
),
2657 REVERSE_FOR_VERTICAL(x2
- 1, y
+ CUTOFF
- 1));
2659 if ( flags
& wxCONTROL_SELECTED
)
2661 dc
.SetPen(m_penLightGrey
);
2663 // overwrite the part of the border below this tab
2664 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
+ 1, y2
+ 1),
2665 REVERSE_FOR_VERTICAL(x2
- 1, y2
+ 1));
2667 // and the shadow of the tab to the left of us
2668 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
+ 1, y
+ CUTOFF
+ 1),
2669 REVERSE_FOR_VERTICAL(x
+ 1, y2
+ 1));
2674 // right orientation looks like bottom but IsVertical makes x and y reversed
2676 // bottom is not vertical so use coordinates in written order
2677 dc
.SetPen(m_penHighlight
);
2678 // we need to continue one pixel further to overwrite the corner of
2679 // the border for the selected tab
2680 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
, y
- (flags
& wxCONTROL_SELECTED ?
1 : 0)),
2681 REVERSE_FOR_VERTICAL(x
, y2
- CUTOFF
));
2682 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
, y2
- CUTOFF
),
2683 REVERSE_FOR_VERTICAL(x
+ CUTOFF
, y2
));
2685 dc
.SetPen(m_penBlack
);
2686 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
+ CUTOFF
, y2
),
2687 REVERSE_FOR_VERTICAL(x2
- CUTOFF
+ 1, y2
));
2688 dc
.DrawLine(REVERSE_FOR_VERTICAL(x2
, y
),
2689 REVERSE_FOR_VERTICAL(x2
, y2
- CUTOFF
));
2690 dc
.DrawLine(REVERSE_FOR_VERTICAL(x2
, y2
- CUTOFF
),
2691 REVERSE_FOR_VERTICAL(x2
- CUTOFF
, y2
));
2693 dc
.SetPen(m_penDarkGrey
);
2694 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
+ CUTOFF
, y2
- 1),
2695 REVERSE_FOR_VERTICAL(x2
- CUTOFF
+ 1, y2
- 1));
2696 dc
.DrawLine(REVERSE_FOR_VERTICAL(x2
- 1, y
),
2697 REVERSE_FOR_VERTICAL(x2
- 1, y2
- CUTOFF
+ 1));
2699 if ( flags
& wxCONTROL_SELECTED
)
2701 dc
.SetPen(m_penLightGrey
);
2703 // overwrite the part of the (double!) border above this tab
2704 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
+ 1, y
- 1),
2705 REVERSE_FOR_VERTICAL(x2
- 1, y
- 1));
2706 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
+ 1, y
- 2),
2707 REVERSE_FOR_VERTICAL(x2
- 1, y
- 2));
2709 // and the shadow of the tab to the left of us
2710 dc
.DrawLine(REVERSE_FOR_VERTICAL(x
+ 1, y2
- CUTOFF
),
2711 REVERSE_FOR_VERTICAL(x
+ 1, y
- 1));
2716 #undef SELECT_FOR_VERTICAL
2717 #undef REVERSE_FOR_VERTICAL
2720 // ----------------------------------------------------------------------------
2722 // ----------------------------------------------------------------------------
2725 wxWin32Renderer
::GetSliderThumbSize(const wxRect
& WXUNUSED(rect
),
2727 wxOrientation orient
) const
2730 wxCoord width
= wxMax (lenThumb
, SLIDER_THUMB_LENGTH
) / 2;
2731 wxCoord height
= wxMax (lenThumb
, SLIDER_THUMB_LENGTH
);
2733 if (orient
== wxHORIZONTAL
)
2747 wxRect wxWin32Renderer
::GetSliderShaftRect(const wxRect
& rectOrig
,
2749 wxOrientation orient
,
2752 bool transpose
= (orient
== wxVERTICAL
);
2753 bool left
= ((style
& wxSL_AUTOTICKS
) != 0) &
2754 (((style
& wxSL_TOP
) != 0) & !transpose
|
2755 ((style
& wxSL_LEFT
) != 0) & transpose
|
2756 ((style
& wxSL_BOTH
) != 0));
2757 bool right
= ((style
& wxSL_AUTOTICKS
) != 0) &
2758 (((style
& wxSL_BOTTOM
) != 0) & !transpose
|
2759 ((style
& wxSL_RIGHT
) != 0) & transpose
|
2760 ((style
& wxSL_BOTH
) != 0));
2762 wxRect rect
= rectOrig
;
2764 wxSize sizeThumb
= GetSliderThumbSize (rect
, lenThumb
, orient
);
2766 if (orient
== wxHORIZONTAL
) {
2767 rect
.x
+= SLIDER_MARGIN
;
2770 rect
.y
+= wxMax ((rect
.height
- 2*BORDER_THICKNESS
) / 2, sizeThumb
.y
/2);
2774 rect
.y
+= wxMax ((rect
.height
- 2*BORDER_THICKNESS
- sizeThumb
.y
/2), sizeThumb
.y
/2);
2778 rect
.y
+= sizeThumb
.y
/2;
2780 rect
.width
-= 2*SLIDER_MARGIN
;
2781 rect
.height
= 2*BORDER_THICKNESS
;
2785 rect
.y
+= SLIDER_MARGIN
;
2788 rect
.x
+= wxMax ((rect
.width
- 2*BORDER_THICKNESS
) / 2, sizeThumb
.x
/2);
2792 rect
.x
+= wxMax ((rect
.width
- 2*BORDER_THICKNESS
- sizeThumb
.x
/2), sizeThumb
.x
/2);
2796 rect
.x
+= sizeThumb
.x
/2;
2798 rect
.width
= 2*BORDER_THICKNESS
;
2799 rect
.height
-= 2*SLIDER_MARGIN
;
2805 void wxWin32Renderer
::DrawSliderShaft(wxDC
& dc
,
2806 const wxRect
& rectOrig
,
2808 wxOrientation orient
,
2813 /* show shaft geometry
2831 if (flags
& wxCONTROL_FOCUSED
) {
2832 DrawFocusRect(dc
, rectOrig
);
2835 wxRect rect
= GetSliderShaftRect(rectOrig
, lenThumb
, orient
, style
);
2837 if (rectShaft
) *rectShaft
= rect
;
2839 DrawSunkenBorder(dc
, &rect
);
2842 void wxWin32Renderer
::DrawSliderThumb(wxDC
& dc
,
2844 wxOrientation orient
,
2848 /* show thumb geometry
2857 H D B where H is highlight colour
2871 The interior of this shape is filled with the hatched brush if the thumb
2875 DrawBackground(dc
, wxNullColour
, rect
, flags
);
2877 bool transpose
= (orient
== wxVERTICAL
);
2878 bool left
= ((style
& wxSL_AUTOTICKS
) != 0) &
2879 (((style
& wxSL_TOP
) != 0) & !transpose
|
2880 ((style
& wxSL_LEFT
) != 0) & transpose
) &
2881 ((style
& wxSL_BOTH
) == 0);
2882 bool right
= ((style
& wxSL_AUTOTICKS
) != 0) &
2883 (((style
& wxSL_BOTTOM
) != 0) & !transpose
|
2884 ((style
& wxSL_RIGHT
) != 0) & transpose
) &
2885 ((style
& wxSL_BOTH
) == 0);
2887 wxCoord sizeArrow
= (transpose ? rect
.height
: rect
.width
) / 2;
2888 wxCoord c
= ((transpose ? rect
.height
: rect
.width
) - 2*sizeArrow
);
2890 wxCoord x1
, x2
, x3
, y1
, y2
, y3
, y4
;
2891 x1
= (transpose ? rect
.y
: rect
.x
);
2892 x2
= (transpose ? rect
.GetBottom() : rect
.GetRight());
2893 x3
= (x1
-1+c
) + sizeArrow
;
2894 y1
= (transpose ? rect
.x
: rect
.y
);
2895 y2
= (transpose ? rect
.GetRight() : rect
.GetBottom());
2896 y3
= (left ?
(y1
-1+c
) + sizeArrow
: y1
);
2897 y4
= (right ?
(y2
+1-c
) - sizeArrow
: y2
);
2899 dc
.SetPen(m_penBlack
);
2901 DrawLine(dc
, x3
+1-c
, y1
, x2
, y3
, transpose
);
2903 DrawLine(dc
, x2
, y3
, x2
, y4
, transpose
);
2906 DrawLine(dc
, x3
+1-c
, y2
, x2
, y4
, transpose
);
2910 DrawLine(dc
, x1
, y2
, x2
, y2
, transpose
);
2913 dc
.SetPen(m_penDarkGrey
);
2914 DrawLine(dc
, x2
-1, y3
+1, x2
-1, y4
-1, transpose
);
2916 DrawLine(dc
, x3
+1-c
, y2
-1, x2
-1, y4
, transpose
);
2920 DrawLine(dc
, x1
+1, y2
-1, x2
-1, y2
-1, transpose
);
2923 dc
.SetPen(m_penHighlight
);
2926 DrawLine(dc
, x1
, y3
, x3
, y1
, transpose
);
2927 DrawLine(dc
, x3
+1-c
, y1
+1, x2
-1, y3
, transpose
);
2931 DrawLine(dc
, x1
, y1
, x2
, y1
, transpose
);
2933 DrawLine(dc
, x1
, y3
, x1
, y4
, transpose
);
2936 DrawLine(dc
, x1
, y4
, x3
+c
, y2
+c
, transpose
);
2939 if (flags
& wxCONTROL_PRESSED
) {
2940 // TODO: MSW fills the entire area inside, not just the rect
2941 wxRect rectInt
= rect
;
2944 rectInt
.SetLeft(y3
);
2945 rectInt
.SetRight(y4
);
2950 rectInt
.SetBottom(y4
);
2954 #if !defined(__WXMGL__)
2955 static const char *stipple_xpm
[] = {
2956 /* columns rows colors chars-per-pixel */
2965 // VS: MGL can only do 8x8 stipple brushes
2966 static const char *stipple_xpm
[] = {
2967 /* columns rows colors chars-per-pixel */
2982 dc
.SetBrush(wxBrush(stipple_xpm
));
2984 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, SHADOW_HIGHLIGHT
));
2985 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, CONTROL
));
2986 dc
.SetPen(*wxTRANSPARENT_PEN
);
2987 dc
.DrawRectangle(rectInt
);
2991 void wxWin32Renderer
::DrawSliderTicks(wxDC
& dc
,
2994 wxOrientation orient
,
2998 int WXUNUSED(flags
),
3001 /* show ticks geometry
3016 if (end
== start
) return;
3018 bool transpose
= (orient
== wxVERTICAL
);
3019 bool left
= ((style
& wxSL_AUTOTICKS
) != 0) &
3020 (((style
& wxSL_TOP
) != 0) & !transpose
|
3021 ((style
& wxSL_LEFT
) != 0) & transpose
|
3022 ((style
& wxSL_BOTH
) != 0));
3023 bool right
= ((style
& wxSL_AUTOTICKS
) != 0) &
3024 (((style
& wxSL_BOTTOM
) != 0) & !transpose
|
3025 ((style
& wxSL_RIGHT
) != 0) & transpose
|
3026 ((style
& wxSL_BOTH
) != 0));
3028 // default thumb size
3029 wxSize sizeThumb
= GetSliderThumbSize (rect
, 0, orient
);
3030 wxCoord defaultLen
= (transpose ? sizeThumb
.x
: sizeThumb
.y
);
3032 // normal thumb size
3033 sizeThumb
= GetSliderThumbSize (rect
, lenThumb
, orient
);
3034 wxCoord widthThumb
= (transpose ? sizeThumb
.y
: sizeThumb
.x
);
3036 wxRect rectShaft
= GetSliderShaftRect (rect
, lenThumb
, orient
, style
);
3038 wxCoord x1
, x2
, y1
, y2
, y3
, y4
, len
;
3039 x1
= (transpose ? rectShaft
.y
: rectShaft
.x
) + widthThumb
/2;
3040 x2
= (transpose ? rectShaft
.GetBottom() : rectShaft
.GetRight()) - widthThumb
/2;
3041 y1
= (transpose ? rectShaft
.x
: rectShaft
.y
) - defaultLen
/2;
3042 y2
= (transpose ? rectShaft
.GetRight() : rectShaft
.GetBottom()) + defaultLen
/2;
3043 y3
= (transpose ? rect
.x
: rect
.y
);
3044 y4
= (transpose ? rect
.GetRight() : rect
.GetBottom());
3047 dc
.SetPen(m_penBlack
);
3049 int range
= end
- start
;
3050 for ( int n
= 0; n
< range
; n
+= step
) {
3051 wxCoord x
= x1
+ (len
*n
) / range
;
3053 if (left
& (y1
> y3
)) {
3054 DrawLine(dc
, x
, y1
, x
, y3
, orient
== wxVERTICAL
);
3056 if (right
& (y4
> y2
)) {
3057 DrawLine(dc
, x
, y2
, x
, y4
, orient
== wxVERTICAL
);
3060 // always draw the line at the end position
3061 if (left
& (y1
> y3
)) {
3062 DrawLine(dc
, x2
, y1
, x2
, y3
, orient
== wxVERTICAL
);
3064 if (right
& (y4
> y2
)) {
3065 DrawLine(dc
, x2
, y2
, x2
, y4
, orient
== wxVERTICAL
);
3069 // ----------------------------------------------------------------------------
3071 // ----------------------------------------------------------------------------
3073 // wxWin32MenuGeometryInfo: the wxMenuGeometryInfo used by wxWin32Renderer
3074 class WXDLLEXPORT wxWin32MenuGeometryInfo
: public wxMenuGeometryInfo
3077 virtual wxSize
GetSize() const { return m_size
; }
3079 wxCoord
GetLabelOffset() const { return m_ofsLabel
; }
3080 wxCoord
GetAccelOffset() const { return m_ofsAccel
; }
3082 wxCoord
GetItemHeight() const { return m_heightItem
; }
3085 // the total size of the menu
3088 // the offset of the start of the menu item label
3091 // the offset of the start of the accel label
3094 // the height of a normal (not separator) item
3095 wxCoord m_heightItem
;
3097 friend wxMenuGeometryInfo
*
3098 wxWin32Renderer
::GetMenuGeometry(wxWindow
*, const wxMenu
&) const;
3101 // FIXME: all constants are hardcoded but shouldn't be
3102 static const wxCoord MENU_LEFT_MARGIN
= 9;
3103 static const wxCoord MENU_RIGHT_MARGIN
= 18;
3104 static const wxCoord MENU_VERT_MARGIN
= 3;
3106 // the margin around bitmap/check marks (on each side)
3107 static const wxCoord MENU_BMP_MARGIN
= 2;
3109 // the margin between the labels and accel strings
3110 static const wxCoord MENU_ACCEL_MARGIN
= 8;
3112 // the separator height in pixels: in fact, strangely enough, the real height
3113 // is 2 but Windows adds one extra pixel in the bottom margin, so take it into
3115 static const wxCoord MENU_SEPARATOR_HEIGHT
= 3;
3117 // the size of the standard checkmark bitmap
3118 static const wxCoord MENU_CHECK_SIZE
= 9;
3120 void wxWin32Renderer
::DrawMenuBarItem(wxDC
& dc
,
3121 const wxRect
& rectOrig
,
3122 const wxString
& label
,
3126 wxRect rect
= rectOrig
;
3129 wxDCTextColourChanger
colChanger(dc
);
3131 if ( flags
& wxCONTROL_SELECTED
)
3133 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
3135 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
3136 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
3137 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
3138 dc
.DrawRectangle(rect
);
3141 // don't draw the focus rect around menu bar items
3142 DrawLabel(dc
, label
, rect
, flags
& ~wxCONTROL_FOCUSED
,
3143 wxALIGN_CENTRE
, indexAccel
);
3146 void wxWin32Renderer
::DrawMenuItem(wxDC
& dc
,
3148 const wxMenuGeometryInfo
& gi
,
3149 const wxString
& label
,
3150 const wxString
& accel
,
3151 const wxBitmap
& bitmap
,
3155 const wxWin32MenuGeometryInfo
& geometryInfo
=
3156 (const wxWin32MenuGeometryInfo
&)gi
;
3161 rect
.width
= geometryInfo
.GetSize().x
;
3162 rect
.height
= geometryInfo
.GetItemHeight();
3164 // draw the selected item specially
3165 wxDCTextColourChanger
colChanger(dc
);
3166 if ( flags
& wxCONTROL_SELECTED
)
3168 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
3170 wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
3171 dc
.SetBrush(wxBrush(colBg
, wxSOLID
));
3172 dc
.SetPen(wxPen(colBg
, 0, wxSOLID
));
3173 dc
.DrawRectangle(rect
);
3176 // draw the bitmap: use the bitmap provided or the standard checkmark for
3177 // the checkable items
3178 wxBitmap bmp
= bitmap
;
3179 if ( !bmp
.Ok() && (flags
& wxCONTROL_CHECKED
) )
3181 bmp
= GetIndicator(IndicatorType_Menu
, flags
);
3186 rect
.SetRight(geometryInfo
.GetLabelOffset());
3187 wxControlRenderer
::DrawBitmap(dc
, bmp
, rect
);
3191 rect
.x
= geometryInfo
.GetLabelOffset();
3192 rect
.SetRight(geometryInfo
.GetAccelOffset());
3194 DrawLabel(dc
, label
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
, indexAccel
);
3196 // draw the accel string
3197 rect
.x
= geometryInfo
.GetAccelOffset();
3198 rect
.SetRight(geometryInfo
.GetSize().x
);
3200 // NB: no accel index here
3201 DrawLabel(dc
, accel
, rect
, flags
, wxALIGN_CENTRE_VERTICAL
);
3203 // draw the submenu indicator
3204 if ( flags
& wxCONTROL_ISSUBMENU
)
3206 rect
.x
= geometryInfo
.GetSize().x
- MENU_RIGHT_MARGIN
;
3207 rect
.width
= MENU_RIGHT_MARGIN
;
3209 wxArrowStyle arrowStyle
;
3210 if ( flags
& wxCONTROL_DISABLED
)
3211 arrowStyle
= flags
& wxCONTROL_SELECTED ? Arrow_InvertedDisabled
3213 else if ( flags
& wxCONTROL_SELECTED
)
3214 arrowStyle
= Arrow_Inverted
;
3216 arrowStyle
= Arrow_Normal
;
3218 DrawArrow(dc
, rect
, Arrow_Right
, arrowStyle
);
3222 void wxWin32Renderer
::DrawMenuSeparator(wxDC
& dc
,
3224 const wxMenuGeometryInfo
& geomInfo
)
3226 DrawHorizontalLine(dc
, y
+ MENU_VERT_MARGIN
, 0, geomInfo
.GetSize().x
);
3229 wxSize wxWin32Renderer
::GetMenuBarItemSize(const wxSize
& sizeText
) const
3231 wxSize size
= sizeText
;
3233 // FIXME: menubar height is configurable under Windows
3240 wxMenuGeometryInfo
*wxWin32Renderer
::GetMenuGeometry(wxWindow
*win
,
3241 const wxMenu
& menu
) const
3243 // prepare the dc: for now we draw all the items with the system font
3245 dc
.SetFont(wxSystemSettings
::GetFont(wxSYS_DEFAULT_GUI_FONT
));
3247 // the height of a normal item
3248 wxCoord heightText
= dc
.GetCharHeight();
3253 // the max length of label and accel strings: the menu width is the sum of
3254 // them, even if they're for different items (as the accels should be
3257 // the max length of the bitmap is never 0 as Windows always leaves enough
3258 // space for a check mark indicator
3259 wxCoord widthLabelMax
= 0,
3261 widthBmpMax
= MENU_LEFT_MARGIN
;
3263 for ( wxMenuItemList
::compatibility_iterator node
= menu
.GetMenuItems().GetFirst();
3265 node
= node
->GetNext() )
3267 // height of this item
3270 wxMenuItem
*item
= node
->GetData();
3271 if ( item
->IsSeparator() )
3273 h
= MENU_SEPARATOR_HEIGHT
;
3275 else // not separator
3280 dc
.GetTextExtent(item
->GetLabel(), &widthLabel
, NULL
);
3281 if ( widthLabel
> widthLabelMax
)
3283 widthLabelMax
= widthLabel
;
3287 dc
.GetTextExtent(item
->GetAccelString(), &widthAccel
, NULL
);
3288 if ( widthAccel
> widthAccelMax
)
3290 widthAccelMax
= widthAccel
;
3293 const wxBitmap
& bmp
= item
->GetBitmap();
3296 wxCoord widthBmp
= bmp
.GetWidth();
3297 if ( widthBmp
> widthBmpMax
)
3298 widthBmpMax
= widthBmp
;
3300 //else if ( item->IsCheckable() ): no need to check for this as
3301 // MENU_LEFT_MARGIN is big enough to show the check mark
3304 h
+= 2*MENU_VERT_MARGIN
;
3306 // remember the item position and height
3307 item
->SetGeometry(height
, h
);
3312 // bundle the metrics into a struct and return it
3313 wxWin32MenuGeometryInfo
*gi
= new wxWin32MenuGeometryInfo
;
3315 gi
->m_ofsLabel
= widthBmpMax
+ 2*MENU_BMP_MARGIN
;
3316 gi
->m_ofsAccel
= gi
->m_ofsLabel
+ widthLabelMax
;
3317 if ( widthAccelMax
> 0 )
3319 // if we actually have any accesl, add a margin
3320 gi
->m_ofsAccel
+= MENU_ACCEL_MARGIN
;
3323 gi
->m_heightItem
= heightText
+ 2*MENU_VERT_MARGIN
;
3325 gi
->m_size
.x
= gi
->m_ofsAccel
+ widthAccelMax
+ MENU_RIGHT_MARGIN
;
3326 gi
->m_size
.y
= height
;
3331 // ----------------------------------------------------------------------------
3333 // ----------------------------------------------------------------------------
3335 static const wxCoord STATBAR_BORDER_X
= 2;
3336 static const wxCoord STATBAR_BORDER_Y
= 2;
3338 wxSize wxWin32Renderer
::GetStatusBarBorders(wxCoord
*borderBetweenFields
) const
3340 if ( borderBetweenFields
)
3341 *borderBetweenFields
= 2;
3343 return wxSize(STATBAR_BORDER_X
, STATBAR_BORDER_Y
);
3346 void wxWin32Renderer
::DrawStatusField(wxDC
& dc
,
3348 const wxString
& label
,
3349 int flags
, int style
/*=0*/)
3353 if ( flags
& wxCONTROL_ISDEFAULT
)
3355 // draw the size grip: it is a normal rect except that in the lower
3356 // right corner we have several bands which may be used for dragging
3357 // the status bar corner
3359 // each band consists of 4 stripes: m_penHighlight, double
3360 // m_penDarkGrey and transparent one
3361 wxCoord x2
= rect
.GetRight(),
3362 y2
= rect
.GetBottom();
3364 // draw the upper left part of the rect normally
3365 if (style
!= wxSB_FLAT
)
3367 if (style
== wxSB_RAISED
)
3368 dc
.SetPen(m_penHighlight
);
3370 dc
.SetPen(m_penDarkGrey
);
3371 dc
.DrawLine(rect
.GetLeft(), rect
.GetTop(), rect
.GetLeft(), y2
);
3372 dc
.DrawLine(rect
.GetLeft() + 1, rect
.GetTop(), x2
, rect
.GetTop());
3375 // draw the grey stripes of the grip
3377 wxCoord ofs
= WIDTH_STATUSBAR_GRIP_BAND
- 1;
3378 for ( n
= 0; n
< NUM_STATUSBAR_GRIP_BANDS
; n
++, ofs
+= WIDTH_STATUSBAR_GRIP_BAND
)
3380 dc
.DrawLine(x2
- ofs
+ 1, y2
- 1, x2
, y2
- ofs
);
3381 dc
.DrawLine(x2
- ofs
, y2
- 1, x2
, y2
- ofs
- 1);
3384 // draw the white stripes
3385 dc
.SetPen(m_penHighlight
);
3386 ofs
= WIDTH_STATUSBAR_GRIP_BAND
+ 1;
3387 for ( n
= 0; n
< NUM_STATUSBAR_GRIP_BANDS
; n
++, ofs
+= WIDTH_STATUSBAR_GRIP_BAND
)
3389 dc
.DrawLine(x2
- ofs
+ 1, y2
- 1, x2
, y2
- ofs
);
3392 // draw the remaining rect boundaries
3393 if (style
!= wxSB_FLAT
)
3395 if (style
== wxSB_RAISED
)
3396 dc
.SetPen(m_penDarkGrey
);
3398 dc
.SetPen(m_penHighlight
);
3399 ofs
-= WIDTH_STATUSBAR_GRIP_BAND
;
3400 dc
.DrawLine(x2
, rect
.GetTop(), x2
, y2
- ofs
+ 1);
3401 dc
.DrawLine(rect
.GetLeft(), y2
, x2
- ofs
+ 1, y2
);
3407 rectIn
.width
-= STATUSBAR_GRIP_SIZE
;
3411 if (style
== wxSB_RAISED
)
3412 DrawBorder(dc
, wxBORDER_RAISED
, rect
, flags
, &rectIn
);
3413 else if (style
!= wxSB_FLAT
)
3414 DrawBorder(dc
, wxBORDER_STATIC
, rect
, flags
, &rectIn
);
3417 rectIn
.Deflate(STATBAR_BORDER_X
, STATBAR_BORDER_Y
);
3419 wxDCClipper
clipper(dc
, rectIn
);
3420 DrawLabel(dc
, label
, rectIn
, flags
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
3423 // ----------------------------------------------------------------------------
3425 // ----------------------------------------------------------------------------
3427 void wxWin32Renderer
::GetComboBitmaps(wxBitmap
*bmpNormal
,
3428 wxBitmap
* WXUNUSED(bmpFocus
),
3429 wxBitmap
*bmpPressed
,
3430 wxBitmap
*bmpDisabled
)
3432 static const wxCoord widthCombo
= 16;
3433 static const wxCoord heightCombo
= 17;
3439 bmpNormal
->Create(widthCombo
, heightCombo
);
3440 dcMem
.SelectObject(*bmpNormal
);
3441 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
3442 Arrow_Down
, Arrow_Normal
);
3447 bmpPressed
->Create(widthCombo
, heightCombo
);
3448 dcMem
.SelectObject(*bmpPressed
);
3449 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
3450 Arrow_Down
, Arrow_Pressed
);
3455 bmpDisabled
->Create(widthCombo
, heightCombo
);
3456 dcMem
.SelectObject(*bmpDisabled
);
3457 DrawArrowButton(dcMem
, wxRect(0, 0, widthCombo
, heightCombo
),
3458 Arrow_Down
, Arrow_Disabled
);
3462 // ----------------------------------------------------------------------------
3464 // ----------------------------------------------------------------------------
3466 void wxWin32Renderer
::DoDrawBackground(wxDC
& dc
,
3467 const wxColour
& col
,
3469 wxWindow
* WXUNUSED(window
))
3471 wxBrush
brush(col
, wxSOLID
);
3473 dc
.SetPen(*wxTRANSPARENT_PEN
);
3474 dc
.DrawRectangle(rect
);
3477 void wxWin32Renderer
::DrawBackground(wxDC
& dc
,
3478 const wxColour
& col
,
3480 int WXUNUSED(flags
),
3483 // just fill it with the given or default bg colour
3484 wxColour colBg
= col
.Ok() ? col
: wxSCHEME_COLOUR(m_scheme
, CONTROL
);
3485 DoDrawBackground(dc
, colBg
, rect
, window
);
3488 // ----------------------------------------------------------------------------
3490 // ----------------------------------------------------------------------------
3492 void wxWin32Renderer
::DrawArrow(wxDC
& dc
,
3497 // get the bitmap for this arrow
3498 wxArrowDirection arrowDir
;
3501 case wxLEFT
: arrowDir
= Arrow_Left
; break;
3502 case wxRIGHT
: arrowDir
= Arrow_Right
; break;
3503 case wxUP
: arrowDir
= Arrow_Up
; break;
3504 case wxDOWN
: arrowDir
= Arrow_Down
; break;
3507 wxFAIL_MSG(_T("unknown arrow direction"));
3511 wxArrowStyle arrowStyle
;
3512 if ( flags
& wxCONTROL_PRESSED
)
3514 // can't be pressed and disabled
3515 arrowStyle
= Arrow_Pressed
;
3519 arrowStyle
= flags
& wxCONTROL_DISABLED ? Arrow_Disabled
: Arrow_Normal
;
3522 DrawArrowButton(dc
, rect
, arrowDir
, arrowStyle
);
3525 void wxWin32Renderer
::DrawArrow(wxDC
& dc
,
3527 wxArrowDirection arrowDir
,
3528 wxArrowStyle arrowStyle
)
3530 const wxBitmap
& bmp
= m_bmpArrows
[arrowStyle
][arrowDir
];
3532 // under Windows the arrows always have the same size so just centre it in
3533 // the provided rectangle
3534 wxCoord x
= rect
.x
+ (rect
.width
- bmp
.GetWidth()) / 2,
3535 y
= rect
.y
+ (rect
.height
- bmp
.GetHeight()) / 2;
3537 // Windows does it like this...
3538 if ( arrowDir
== Arrow_Left
)
3542 dc
.DrawBitmap(bmp
, x
, y
, true /* use mask */);
3545 void wxWin32Renderer
::DrawArrowButton(wxDC
& dc
,
3546 const wxRect
& rectAll
,
3547 wxArrowDirection arrowDir
,
3548 wxArrowStyle arrowStyle
)
3550 wxRect rect
= rectAll
;
3551 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
3552 DrawArrowBorder(dc
, &rect
, arrowStyle
== Arrow_Pressed
);
3553 DrawArrow(dc
, rect
, arrowDir
, arrowStyle
);
3556 void wxWin32Renderer
::DrawScrollbarThumb(wxDC
& dc
,
3557 wxOrientation
WXUNUSED(orient
),
3559 int WXUNUSED(flags
))
3561 // we don't use the flags, the thumb never changes appearance
3562 wxRect rectThumb
= rect
;
3563 DrawArrowBorder(dc
, &rectThumb
);
3564 DrawBackground(dc
, wxNullColour
, rectThumb
);
3567 void wxWin32Renderer
::DrawScrollbarShaft(wxDC
& dc
,
3568 wxOrientation
WXUNUSED(orient
),
3569 const wxRect
& rectBar
,
3572 wxColourScheme
::StdColour col
= flags
& wxCONTROL_PRESSED
3573 ? wxColourScheme
::SCROLLBAR_PRESSED
3574 : wxColourScheme
::SCROLLBAR
;
3575 DoDrawBackground(dc
, m_scheme
->Get(col
), rectBar
);
3578 void wxWin32Renderer
::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
3580 DoDrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
3583 wxRect wxWin32Renderer
::GetScrollbarRect(const wxScrollBar
*scrollbar
,
3584 wxScrollBar
::Element elem
,
3587 return StandardGetScrollbarRect(scrollbar
, elem
,
3588 thumbPos
, m_sizeScrollbarArrow
);
3591 wxCoord wxWin32Renderer
::GetScrollbarSize(const wxScrollBar
*scrollbar
)
3593 return StandardScrollBarSize(scrollbar
, m_sizeScrollbarArrow
);
3596 wxHitTest wxWin32Renderer
::HitTestScrollbar(const wxScrollBar
*scrollbar
,
3597 const wxPoint
& pt
) const
3599 return StandardHitTestScrollbar(scrollbar
, pt
, m_sizeScrollbarArrow
);
3602 wxCoord wxWin32Renderer
::ScrollbarToPixel(const wxScrollBar
*scrollbar
,
3605 return StandardScrollbarToPixel(scrollbar
, thumbPos
, m_sizeScrollbarArrow
);
3608 int wxWin32Renderer
::PixelToScrollbar(const wxScrollBar
*scrollbar
,
3611 return StandardPixelToScrollbar(scrollbar
, coord
, m_sizeScrollbarArrow
);
3614 // ----------------------------------------------------------------------------
3615 // top level windows
3616 // ----------------------------------------------------------------------------
3618 int wxWin32Renderer
::HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const
3620 wxRect client
= GetFrameClientArea(rect
, flags
);
3622 if ( client
.Inside(pt
) )
3623 return wxHT_TOPLEVEL_CLIENT_AREA
;
3625 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3627 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3629 if ( flags
& wxTOPLEVEL_ICON
)
3631 if ( wxRect(client
.GetPosition(), GetFrameIconSize()).Inside(pt
) )
3632 return wxHT_TOPLEVEL_ICON
;
3635 wxRect
btnRect(client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
,
3636 client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2,
3637 FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
3639 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3641 if ( btnRect
.Inside(pt
) )
3642 return wxHT_TOPLEVEL_BUTTON_CLOSE
;
3643 btnRect
.x
-= FRAME_BUTTON_WIDTH
+ 2;
3645 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3647 if ( btnRect
.Inside(pt
) )
3648 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE
;
3649 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3651 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3653 if ( btnRect
.Inside(pt
) )
3654 return wxHT_TOPLEVEL_BUTTON_RESTORE
;
3655 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3657 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3659 if ( btnRect
.Inside(pt
) )
3660 return wxHT_TOPLEVEL_BUTTON_ICONIZE
;
3661 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3663 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3665 if ( btnRect
.Inside(pt
) )
3666 return wxHT_TOPLEVEL_BUTTON_HELP
;
3667 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
3670 if ( pt
.y
>= client
.y
&& pt
.y
< client
.y
+ FRAME_TITLEBAR_HEIGHT
)
3671 return wxHT_TOPLEVEL_TITLEBAR
;
3674 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3676 // we are certainly at one of borders, lets decide which one:
3679 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
3680 if ( pt
.x
< client
.x
)
3681 border
|= wxHT_TOPLEVEL_BORDER_W
;
3682 else if ( pt
.x
>= client
.width
+ client
.x
)
3683 border
|= wxHT_TOPLEVEL_BORDER_E
;
3684 if ( pt
.y
< client
.y
)
3685 border
|= wxHT_TOPLEVEL_BORDER_N
;
3686 else if ( pt
.y
>= client
.height
+ client
.y
)
3687 border
|= wxHT_TOPLEVEL_BORDER_S
;
3691 return wxHT_NOWHERE
;
3694 void wxWin32Renderer
::DrawFrameTitleBar(wxDC
& dc
,
3696 const wxString
& title
,
3700 int specialButtonFlags
)
3702 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3704 DrawFrameBorder(dc
, rect
, flags
);
3706 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3708 DrawFrameBackground(dc
, rect
, flags
);
3709 if ( flags
& wxTOPLEVEL_ICON
)
3710 DrawFrameIcon(dc
, rect
, icon
, flags
);
3711 DrawFrameTitle(dc
, rect
, title
, flags
);
3713 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3715 x
= client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
;
3716 y
= client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2;
3718 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3720 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_CLOSE
,
3721 (specialButton
== wxTOPLEVEL_BUTTON_CLOSE
) ?
3722 specialButtonFlags
: 0);
3723 x
-= FRAME_BUTTON_WIDTH
+ 2;
3725 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3727 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_MAXIMIZE
,
3728 (specialButton
== wxTOPLEVEL_BUTTON_MAXIMIZE
) ?
3729 specialButtonFlags
: 0);
3730 x
-= FRAME_BUTTON_WIDTH
;
3732 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3734 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_RESTORE
,
3735 (specialButton
== wxTOPLEVEL_BUTTON_RESTORE
) ?
3736 specialButtonFlags
: 0);
3737 x
-= FRAME_BUTTON_WIDTH
;
3739 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3741 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_ICONIZE
,
3742 (specialButton
== wxTOPLEVEL_BUTTON_ICONIZE
) ?
3743 specialButtonFlags
: 0);
3744 x
-= FRAME_BUTTON_WIDTH
;
3746 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3748 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_HELP
,
3749 (specialButton
== wxTOPLEVEL_BUTTON_HELP
) ?
3750 specialButtonFlags
: 0);
3755 void wxWin32Renderer
::DrawFrameBorder(wxDC
& dc
,
3759 if ( !(flags
& wxTOPLEVEL_BORDER
) ) return;
3763 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penBlack
);
3764 DrawShadedRect(dc
, &r
, m_penHighlight
, m_penDarkGrey
);
3765 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penLightGrey
);
3766 if ( flags
& wxTOPLEVEL_RESIZEABLE
)
3767 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penLightGrey
);
3770 void wxWin32Renderer
::DrawFrameBackground(wxDC
& dc
,
3774 if ( !(flags
& wxTOPLEVEL_TITLEBAR
) ) return;
3776 wxColour col
= (flags
& wxTOPLEVEL_ACTIVE
) ?
3777 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_ACTIVE
) :
3778 wxSCHEME_COLOUR(m_scheme
, TITLEBAR
);
3780 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3781 r
.height
= FRAME_TITLEBAR_HEIGHT
;
3783 DrawBackground(dc
, col
, r
);
3786 void wxWin32Renderer
::DrawFrameTitle(wxDC
& dc
,
3788 const wxString
& title
,
3791 wxColour col
= (flags
& wxTOPLEVEL_ACTIVE
) ?
3792 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_ACTIVE_TEXT
) :
3793 wxSCHEME_COLOUR(m_scheme
, TITLEBAR_TEXT
);
3795 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3796 r
.height
= FRAME_TITLEBAR_HEIGHT
;
3797 if ( flags
& wxTOPLEVEL_ICON
)
3799 r
.x
+= FRAME_TITLEBAR_HEIGHT
;
3800 r
.width
-= FRAME_TITLEBAR_HEIGHT
+ 2;
3808 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3809 r
.width
-= FRAME_BUTTON_WIDTH
+ 2;
3810 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3811 r
.width
-= FRAME_BUTTON_WIDTH
;
3812 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3813 r
.width
-= FRAME_BUTTON_WIDTH
;
3814 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3815 r
.width
-= FRAME_BUTTON_WIDTH
;
3816 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3817 r
.width
-= FRAME_BUTTON_WIDTH
;
3819 dc
.SetFont(m_titlebarFont
);
3820 dc
.SetTextForeground(col
);
3823 dc
.GetTextExtent(title
, &textW
, NULL
);
3824 if ( textW
> r
.width
)
3826 // text is too big, let's shorten it and add "..." after it:
3827 size_t len
= title
.length();
3828 wxCoord WSoFar
, letterW
;
3830 dc
.GetTextExtent(wxT("..."), &WSoFar
, NULL
);
3831 if ( WSoFar
> r
.width
)
3833 // not enough space to draw anything
3839 for (size_t i
= 0; i
< len
; i
++)
3841 dc
.GetTextExtent(title
[i
], &letterW
, NULL
);
3842 if ( letterW
+ WSoFar
> r
.width
)
3848 dc
.DrawLabel(s
, wxNullBitmap
, r
,
3849 wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
3852 dc
.DrawLabel(title
, wxNullBitmap
, r
,
3853 wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
3856 void wxWin32Renderer
::DrawFrameIcon(wxDC
& dc
,
3863 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
3864 dc
.DrawIcon(icon
, r
.x
, r
.y
);
3868 void wxWin32Renderer
::DrawFrameButton(wxDC
& dc
,
3869 wxCoord x
, wxCoord y
,
3873 wxRect
r(x
, y
, FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
3878 case wxTOPLEVEL_BUTTON_CLOSE
: idx
= FrameButton_Close
; break;
3879 case wxTOPLEVEL_BUTTON_MAXIMIZE
: idx
= FrameButton_Maximize
; break;
3880 case wxTOPLEVEL_BUTTON_ICONIZE
: idx
= FrameButton_Minimize
; break;
3881 case wxTOPLEVEL_BUTTON_RESTORE
: idx
= FrameButton_Restore
; break;
3882 case wxTOPLEVEL_BUTTON_HELP
: idx
= FrameButton_Help
; break;
3884 wxFAIL_MSG(wxT("incorrect button specification"));
3887 if ( flags
& wxCONTROL_PRESSED
)
3889 DrawShadedRect(dc
, &r
, m_penBlack
, m_penHighlight
);
3890 DrawShadedRect(dc
, &r
, m_penDarkGrey
, m_penLightGrey
);
3891 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), r
);
3892 dc
.DrawBitmap(m_bmpFrameButtons
[idx
], r
.x
+1, r
.y
+1, true);
3896 DrawShadedRect(dc
, &r
, m_penHighlight
, m_penBlack
);
3897 DrawShadedRect(dc
, &r
, m_penLightGrey
, m_penDarkGrey
);
3898 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), r
);
3899 dc
.DrawBitmap(m_bmpFrameButtons
[idx
], r
.x
, r
.y
, true);
3904 wxRect wxWin32Renderer
::GetFrameClientArea(const wxRect
& rect
,
3909 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3911 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3912 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3913 FRAME_BORDER_THICKNESS
;
3916 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3918 r
.y
+= FRAME_TITLEBAR_HEIGHT
;
3919 r
.height
-= FRAME_TITLEBAR_HEIGHT
;
3925 wxSize wxWin32Renderer
::GetFrameTotalSize(const wxSize
& clientSize
,
3928 wxSize
s(clientSize
);
3930 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3932 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3933 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3934 FRAME_BORDER_THICKNESS
;
3938 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3939 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
3944 wxSize wxWin32Renderer
::GetFrameMinSize(int flags
) const
3948 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
3950 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
3951 RESIZEABLE_FRAME_BORDER_THICKNESS
:
3952 FRAME_BORDER_THICKNESS
;
3957 if ( flags
& wxTOPLEVEL_TITLEBAR
)
3959 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
3961 if ( flags
& wxTOPLEVEL_ICON
)
3962 s
.x
+= FRAME_TITLEBAR_HEIGHT
+ 2;
3963 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
3964 s
.x
+= FRAME_BUTTON_WIDTH
+ 2;
3965 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
3966 s
.x
+= FRAME_BUTTON_WIDTH
;
3967 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
3968 s
.x
+= FRAME_BUTTON_WIDTH
;
3969 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
3970 s
.x
+= FRAME_BUTTON_WIDTH
;
3971 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
3972 s
.x
+= FRAME_BUTTON_WIDTH
;
3978 wxSize wxWin32Renderer
::GetFrameIconSize() const
3980 return wxSize(16, 16);
3984 // ----------------------------------------------------------------------------
3986 // ----------------------------------------------------------------------------
3988 /* Copyright (c) Julian Smart */
3989 static char *error_xpm
[]={
3990 /* columns rows colors chars-per-pixel */
4067 " $oooooooooooo%& ",
4068 " *=-ooooooooooooo;: ",
4069 " *oooooooooooooooooo> ",
4070 " =ooooooooooooooooooo, ",
4071 " $-ooooooooooooooooooo<1 ",
4072 " .oooooo2334ooo533oooooo6 ",
4073 " +ooooooo789oo2883oooooo0q ",
4074 " oooooooo2w83o78eoooooooor ",
4075 " toooooooooy88u884oooooooori ",
4076 " Xooooooooooe888poooooooooas ",
4077 " ooooooooooo4889doooooooooof ",
4078 " ooooooooooo588w2oooooooooofi ",
4079 " oooooooooodw8887oooooooooofi ",
4080 " goooooooooh8w588jooooooookli ",
4081 " tooooooooz885op8wdooooooorix ",
4082 " oooooood98cood98cooooooori ",
4083 " @oooooop8w2ooo5885ooooovbi ",
4084 " n%ooooooooooooooooooooomiM ",
4085 " &;oooooooooooooooooooNBiV ",
4086 " :ooooooooooooooooooCZiA ",
4087 " nSooooooooooooooooCDiF ",
4088 " nG<oooooooooooooNZiiH ",
4089 " 160ooooooooovmBiFH ",
4090 " nqrraoookrrbiiA ",
4097 /* Copyright (c) Julian Smart */
4098 static char *info_xpm
[]={
4099 /* columns rows colors chars-per-pixel */
4121 " ..XXXXXXXXXXXXX.. ",
4122 " .XXXXXXXXXXXXXXXXX. ",
4123 " .XXXXXXXXoO+XXXXXXXX. ",
4124 " .XXXXXXXXX@#OXXXXXXXXX. ",
4125 " .XXXXXXXXXX$@oXXXXXXXXXX. ",
4126 " .XXXXXXXXXXXXXXXXXXXXXXX.% ",
4127 " .XXXXXXXXX&*=-XXXXXXXXXX.%% ",
4128 ".XXXXXXXXXX;:#>XXXXXXXXXXX.% ",
4129 ".XXXXXXXXXXX;#+XXXXXXXXXXX.% ",
4130 ".XXXXXXXXXXX;#+XXXXXXXXXXX.%% ",
4131 " .XXXXXXXXXX;#+XXXXXXXXXX.%%% ",
4132 " .XXXXXXXXXX;#+XXXXXXXXXX.%%% ",
4133 " .XXXXXXXXXX;#+XXXXXXXXXX.%% ",
4134 " .XXXXXXXX*-##+XXXXXXXX.%%% ",
4135 " .XXXXXXXXXXXXXXXXXXX.%%%% ",
4136 " .XXXXXXXXXXXXXXXXX.%%%% ",
4137 " ..XXXXXXXXXXXXX..%%%% ",
4138 " %...XXXXXXXX..%%%%% ",
4139 " %%%..XXXXXX.%%%%% ",
4153 /* Copyright (c) Julian Smart */
4154 static char *question_xpm
[]={
4155 /* columns rows colors chars-per-pixel */
4176 " ..XXXXXXXXXXXXX.. ",
4177 " .XXXXXXoO++@XXXXXX. ",
4178 " .XXXXXXO#$$$$#%XXXXX. ",
4179 " .XXXXXX@$$#&&#$#oXXXXX. ",
4180 " .XXXXXXX*$$%XX%$$=XXXXXX. ",
4181 " .XXXXXXX+-;XXXX$$-XXXXXX.: ",
4182 " .XXXXXXXXXXXXX+$$&XXXXXX.:: ",
4183 ".XXXXXXXXXXXXo;$$*oXXXXXXX.: ",
4184 ".XXXXXXXXXXXo*$$*oXXXXXXXX.: ",
4185 ".XXXXXXXXXXX+$$*oXXXXXXXXX.:: ",
4186 " .XXXXXXXXXX-$$oXXXXXXXXX.::: ",
4187 " .XXXXXXXXXXX--XXXXXXXXXX.::: ",
4188 " .XXXXXXXXXXXXXXXXXXXXXXX.:: ",
4189 " .XXXXXXXXX-$$XXXXXXXXX.::: ",
4190 " .XXXXXXXX-$$XXXXXXXX.:::: ",
4191 " .XXXXXXXO++XXXXXXX.:::: ",
4192 " ..XXXXXXXXXXXXX..:::: ",
4193 " :...XXXXXXXX..::::: ",
4194 " :::..XXXXXX.::::: ",
4208 /* Copyright (c) Julian Smart */
4209 static char *warning_xpm
[]={
4210 /* columns rows colors chars-per-pixel */
4236 " ..XXXXO@#XXX... ",
4237 " ...XXXXO@#XXXX.. ",
4238 " ..XXXXXO@#XXXX... ",
4239 " ...XXXXXo@OXXXXX.. ",
4240 " ...XXXXXXo@OXXXXXX.. ",
4241 " ..XXXXXXX$@OXXXXXX... ",
4242 " ...XXXXXXXX@XXXXXXXX.. ",
4243 " ...XXXXXXXXXXXXXXXXXX... ",
4244 " ..XXXXXXXXXXOXXXXXXXXX.. ",
4245 " ...XXXXXXXXXO@#XXXXXXXXX.. ",
4246 " ..XXXXXXXXXXX#XXXXXXXXXX... ",
4247 " ...XXXXXXXXXXXXXXXXXXXXXXX.. ",
4248 " ...XXXXXXXXXXXXXXXXXXXXXXXX... ",
4249 " .............................. ",
4250 " .............................. ",
4257 wxBitmap wxWin32ArtProvider
::CreateBitmap(const wxArtID
& id
,
4258 const wxArtClient
& WXUNUSED(client
),
4259 const wxSize
& WXUNUSED(size
))
4261 if ( id
== wxART_INFORMATION
)
4262 return wxBitmap(info_xpm
);
4263 if ( id
== wxART_ERROR
)
4264 return wxBitmap(error_xpm
);
4265 if ( id
== wxART_WARNING
)
4266 return wxBitmap(warning_xpm
);
4267 if ( id
== wxART_QUESTION
)
4268 return wxBitmap(question_xpm
);
4269 return wxNullBitmap
;
4273 // ----------------------------------------------------------------------------
4274 // text control geometry
4275 // ----------------------------------------------------------------------------
4277 static inline int GetTextBorderWidth()
4283 wxWin32Renderer
::GetTextTotalArea(const wxTextCtrl
* WXUNUSED(text
),
4284 const wxRect
& rect
) const
4286 wxRect rectTotal
= rect
;
4288 wxCoord widthBorder
= GetTextBorderWidth();
4289 rectTotal
.Inflate(widthBorder
);
4291 // this is what Windows does
4298 wxWin32Renderer
::GetTextClientArea(const wxTextCtrl
* WXUNUSED(text
),
4300 wxCoord
*extraSpaceBeyond
) const
4302 wxRect rectText
= rect
;
4304 // undo GetTextTotalArea()
4305 if ( rectText
.height
> 0 )
4308 wxCoord widthBorder
= GetTextBorderWidth();
4309 rectText
.Inflate(-widthBorder
);
4311 if ( extraSpaceBeyond
)
4312 *extraSpaceBeyond
= 0;
4317 // ----------------------------------------------------------------------------
4319 // ----------------------------------------------------------------------------
4321 void wxWin32Renderer
::AdjustSize(wxSize
*size
, const wxWindow
*window
)
4324 if ( wxDynamicCast(window
, wxScrollBar
) )
4326 // we only set the width of vert scrollbars and height of the
4328 if ( window
->GetWindowStyle() & wxSB_HORIZONTAL
)
4329 size
->y
= m_sizeScrollbarArrow
.y
;
4331 size
->x
= m_sizeScrollbarArrow
.x
;
4333 // skip border width adjustments, they don't make sense for us
4336 #endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
4339 if ( wxDynamicCast(window
, wxBitmapButton
) )
4343 #endif // wxUSE_BMPBUTTON
4345 if ( wxDynamicCast(window
, wxButton
) )
4347 if ( !(window
->GetWindowStyle() & wxBU_EXACTFIT
) )
4349 // TODO: don't harcode all this
4350 size
->x
+= 3*window
->GetCharWidth();
4352 wxCoord heightBtn
= (11*(window
->GetCharHeight() + 8))/10;
4353 if ( size
->y
< heightBtn
- 8 )
4354 size
->y
= heightBtn
;
4359 // for compatibility with other ports, the buttons default size is never
4360 // less than the standard one, but not when display not PDAs.
4361 if (wxSystemSettings
::GetScreenType() > wxSYS_SCREEN_PDA
)
4363 if ( !(window
->GetWindowStyle() & wxBU_EXACTFIT
) )
4365 wxSize szDef
= wxButton
::GetDefaultSize();
4366 if ( size
->x
< szDef
.x
)
4371 // no border width adjustments for buttons
4374 #endif // wxUSE_BUTTON
4376 // take into account the border width
4377 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
4378 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
4379 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
4382 // ============================================================================
4384 // ============================================================================
4386 // ----------------------------------------------------------------------------
4387 // wxWin32InputHandler
4388 // ----------------------------------------------------------------------------
4390 wxWin32InputHandler
::wxWin32InputHandler(wxWin32Renderer
*renderer
)
4392 m_renderer
= renderer
;
4395 bool wxWin32InputHandler
::HandleKey(wxInputConsumer
* WXUNUSED(control
),
4396 const wxKeyEvent
& WXUNUSED(event
),
4397 bool WXUNUSED(pressed
))
4402 bool wxWin32InputHandler
::HandleMouse(wxInputConsumer
*control
,
4403 const wxMouseEvent
& event
)
4405 // clicking on the control gives it focus
4406 if ( event
.ButtonDown() )
4408 wxWindow
*win
= control
->GetInputWindow();
4410 if (( wxWindow
::FindFocus() != control
->GetInputWindow() ) &&
4411 ( win
->AcceptsFocus() ) )
4422 // ----------------------------------------------------------------------------
4423 // wxWin32ScrollBarInputHandler
4424 // ----------------------------------------------------------------------------
4426 wxWin32ScrollBarInputHandler
::
4427 wxWin32ScrollBarInputHandler(wxWin32Renderer
*renderer
,
4428 wxInputHandler
*handler
)
4429 : wxStdScrollBarInputHandler(renderer
, handler
)
4431 m_scrollPaused
= false;
4435 bool wxWin32ScrollBarInputHandler
::OnScrollTimer(wxScrollBar
*scrollbar
,
4436 const wxControlAction
& action
)
4438 // stop if went beyond the position of the original click (this can only
4439 // happen when we scroll by pages)
4441 if ( action
== wxACTION_SCROLL_PAGE_DOWN
)
4443 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
4444 != wxHT_SCROLLBAR_BAR_2
;
4446 else if ( action
== wxACTION_SCROLL_PAGE_UP
)
4448 stop
= m_renderer
->HitTestScrollbar(scrollbar
, m_ptStartScrolling
)
4449 != wxHT_SCROLLBAR_BAR_1
;
4454 StopScrolling(scrollbar
);
4456 scrollbar
->Refresh();
4461 return wxStdScrollBarInputHandler
::OnScrollTimer(scrollbar
, action
);
4464 bool wxWin32ScrollBarInputHandler
::HandleMouse(wxInputConsumer
*control
,
4465 const wxMouseEvent
& event
)
4467 // remember the current state
4468 bool wasDraggingThumb
= m_htLast
== wxHT_SCROLLBAR_THUMB
;
4470 // do process the message
4471 bool rc
= wxStdScrollBarInputHandler
::HandleMouse(control
, event
);
4473 // analyse the changes
4474 if ( !wasDraggingThumb
&& (m_htLast
== wxHT_SCROLLBAR_THUMB
) )
4476 // we just started dragging the thumb, remember its initial position to
4477 // be able to restore it if the drag is cancelled later
4478 m_eventStartDrag
= event
;
4484 bool wxWin32ScrollBarInputHandler
::HandleMouseMove(wxInputConsumer
*control
,
4485 const wxMouseEvent
& event
)
4487 // we don't highlight scrollbar elements, so there is no need to process
4488 // mouse move events normally - only do it while mouse is captured (i.e.
4489 // when we're dragging the thumb or pressing on something)
4490 if ( !m_winCapture
)
4493 if ( event
.Entering() )
4495 // we're not interested in this at all
4499 wxScrollBar
*scrollbar
= wxStaticCast(control
->GetInputWindow(), wxScrollBar
);
4501 if ( m_scrollPaused
)
4503 // check if the mouse returned to its original location
4505 if ( event
.Leaving() )
4511 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
4512 if ( ht
== m_htLast
)
4514 // yes it did, resume scrolling
4515 m_scrollPaused
= false;
4516 if ( m_timerScroll
)
4518 // we were scrolling by line/page, restart timer
4519 m_timerScroll
->Start(m_interval
);
4521 Press(scrollbar
, true);
4523 else // we were dragging the thumb
4525 // restore its last location
4526 HandleThumbMove(scrollbar
, m_eventLastDrag
);
4532 else // normal case, scrolling hasn't been paused
4534 // if we're scrolling the scrollbar because the arrow or the shaft was
4535 // pressed, check that the mouse stays on the same scrollbar element
4538 // Always let thumb jump back if we leave the scrollbar
4539 if ( event
.Moving() )
4541 ht
= m_renderer
->HitTestScrollbar(scrollbar
, event
.GetPosition());
4543 else // event.Leaving()
4548 // Jump back only if we get far away from it
4549 wxPoint pos
= event
.GetPosition();
4550 if (scrollbar
->HasFlag( wxVERTICAL
))
4552 if (pos
.x
> -40 && pos
.x
< scrollbar
->GetSize().x
+40)
4557 if (pos
.y
> -40 && pos
.y
< scrollbar
->GetSize().y
+40)
4560 ht
= m_renderer
->HitTestScrollbar(scrollbar
, pos
);
4563 // if we're dragging the thumb and the mouse stays in the scrollbar, it
4564 // is still ok - we only want to catch the case when the mouse leaves
4565 // the scrollbar here
4566 if ( m_htLast
== wxHT_SCROLLBAR_THUMB
&& ht
!= wxHT_NOWHERE
)
4568 ht
= wxHT_SCROLLBAR_THUMB
;
4571 if ( ht
!= m_htLast
)
4573 // what were we doing? 2 possibilities: either an arrow/shaft was
4574 // pressed in which case we have a timer and so we just stop it or
4575 // we were dragging the thumb
4576 if ( m_timerScroll
)
4579 m_interval
= m_timerScroll
->GetInterval();
4580 m_timerScroll
->Stop();
4581 m_scrollPaused
= true;
4583 // unpress the arrow
4584 Press(scrollbar
, false);
4586 else // we were dragging the thumb
4588 // remember the current thumb position to be able to restore it
4589 // if the mouse returns to it later
4590 m_eventLastDrag
= event
;
4592 // and restore the original position (before dragging) of the
4594 HandleThumbMove(scrollbar
, m_eventStartDrag
);
4601 return wxStdScrollBarInputHandler
::HandleMouseMove(control
, event
);
4604 // ----------------------------------------------------------------------------
4605 // wxWin32CheckboxInputHandler
4606 // ----------------------------------------------------------------------------
4608 bool wxWin32CheckboxInputHandler
::HandleKey(wxInputConsumer
*control
,
4609 const wxKeyEvent
& event
,
4614 wxControlAction action
;
4615 int keycode
= event
.GetKeyCode();
4619 action
= wxACTION_CHECKBOX_TOGGLE
;
4623 case WXK_NUMPAD_SUBTRACT
:
4624 action
= wxACTION_CHECKBOX_CHECK
;
4628 case WXK_NUMPAD_ADD
:
4629 case WXK_NUMPAD_EQUAL
:
4630 action
= wxACTION_CHECKBOX_CLEAR
;
4634 if ( !action
.IsEmpty() )
4636 control
->PerformAction(action
);
4645 // ----------------------------------------------------------------------------
4646 // wxWin32TextCtrlInputHandler
4647 // ----------------------------------------------------------------------------
4649 bool wxWin32TextCtrlInputHandler
::HandleKey(wxInputConsumer
*control
,
4650 const wxKeyEvent
& event
,
4653 // handle only MSW-specific text bindings here, the others are handled in
4657 int keycode
= event
.GetKeyCode();
4659 wxControlAction action
;
4660 if ( keycode
== WXK_DELETE
&& event
.ShiftDown() )
4662 action
= wxACTION_TEXT_CUT
;
4664 else if ( keycode
== WXK_INSERT
)
4666 if ( event
.ControlDown() )
4667 action
= wxACTION_TEXT_COPY
;
4668 else if ( event
.ShiftDown() )
4669 action
= wxACTION_TEXT_PASTE
;
4672 if ( action
!= wxACTION_NONE
)
4674 control
->PerformAction(action
);
4680 return wxStdTextCtrlInputHandler
::HandleKey(control
, event
, pressed
);
4683 // ----------------------------------------------------------------------------
4684 // wxWin32StatusBarInputHandler
4685 // ----------------------------------------------------------------------------
4687 wxWin32StatusBarInputHandler
::
4688 wxWin32StatusBarInputHandler(wxInputHandler
*handler
)
4689 : wxStdInputHandler(handler
)
4694 bool wxWin32StatusBarInputHandler
::IsOnGrip(wxWindow
*statbar
,
4695 const wxPoint
& pt
) const
4697 if ( statbar
->HasFlag(wxST_SIZEGRIP
) &&
4698 statbar
->GetParent()->HasFlag(wxRESIZE_BORDER
) )
4701 parentTLW
= wxDynamicCast(statbar
->GetParent(), wxTopLevelWindow
);
4703 wxCHECK_MSG( parentTLW
, false,
4704 _T("the status bar should be a child of a TLW") );
4706 // a maximized window can't be resized anyhow
4707 if ( !parentTLW
->IsMaximized() )
4709 // VZ: I think that the standard Windows behaviour is to only
4710 // show the resizing cursor when the mouse is on top of the
4711 // grip itself but apparently different Windows versions behave
4712 // differently (?) and it seems a better UI to allow resizing
4713 // the status bar even when the mouse is above the grip
4714 wxSize sizeSbar
= statbar
->GetSize();
4716 int diff
= sizeSbar
.x
- pt
.x
;
4717 return diff
>= 0 && diff
< (wxCoord
)STATUSBAR_GRIP_SIZE
;
4724 bool wxWin32StatusBarInputHandler
::HandleMouse(wxInputConsumer
*consumer
,
4725 const wxMouseEvent
& event
)
4727 if ( event
.Button(1) )
4729 if ( event
.ButtonDown(1) )
4731 wxWindow
*statbar
= consumer
->GetInputWindow();
4733 if ( IsOnGrip(statbar
, event
.GetPosition()) )
4735 wxTopLevelWindow
*tlw
= wxDynamicCast(statbar
->GetParent(),
4739 tlw
->PerformAction(wxACTION_TOPLEVEL_RESIZE
,
4740 wxHT_TOPLEVEL_BORDER_SE
);
4742 statbar
->SetCursor(m_cursorOld
);
4750 return wxStdInputHandler
::HandleMouse(consumer
, event
);
4753 bool wxWin32StatusBarInputHandler
::HandleMouseMove(wxInputConsumer
*consumer
,
4754 const wxMouseEvent
& event
)
4756 wxWindow
*statbar
= consumer
->GetInputWindow();
4758 bool isOnGrip
= IsOnGrip(statbar
, event
.GetPosition());
4759 if ( isOnGrip
!= m_isOnGrip
)
4761 m_isOnGrip
= isOnGrip
;
4764 m_cursorOld
= statbar
->GetCursor();
4765 statbar
->SetCursor(wxCURSOR_SIZENWSE
);
4769 statbar
->SetCursor(m_cursorOld
);
4773 return wxStdInputHandler
::HandleMouseMove(consumer
, event
);
4776 // ----------------------------------------------------------------------------
4777 // wxWin32FrameInputHandler
4778 // ----------------------------------------------------------------------------
4780 class wxWin32SystemMenuEvtHandler
: public wxEvtHandler
4783 wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler
*handler
);
4785 void Attach(wxInputConsumer
*consumer
);
4789 DECLARE_EVENT_TABLE()
4790 void OnSystemMenu(wxCommandEvent
&event
);
4791 void OnCloseFrame(wxCommandEvent
&event
);
4792 void OnClose(wxCloseEvent
&event
);
4794 wxWin32FrameInputHandler
*m_inputHnd
;
4795 wxTopLevelWindow
*m_wnd
;
4797 wxAcceleratorTable m_oldAccelTable
;
4801 wxWin32SystemMenuEvtHandler
::wxWin32SystemMenuEvtHandler(
4802 wxWin32FrameInputHandler
*handler
)
4804 m_inputHnd
= handler
;
4808 void wxWin32SystemMenuEvtHandler
::Attach(wxInputConsumer
*consumer
)
4810 wxASSERT_MSG( m_wnd
== NULL
, _T("can't attach the handler twice!") );
4812 m_wnd
= wxStaticCast(consumer
->GetInputWindow(), wxTopLevelWindow
);
4813 m_wnd
->PushEventHandler(this);
4816 // VS: This code relies on using generic implementation of
4817 // wxAcceleratorTable in wxUniv!
4818 wxAcceleratorTable table
= *m_wnd
->GetAcceleratorTable();
4819 m_oldAccelTable
= table
;
4820 table
.Add(wxAcceleratorEntry(wxACCEL_ALT
, WXK_SPACE
, wxID_SYSTEM_MENU
));
4821 table
.Add(wxAcceleratorEntry(wxACCEL_ALT
, WXK_F4
, wxID_CLOSE_FRAME
));
4822 m_wnd
->SetAcceleratorTable(table
);
4826 void wxWin32SystemMenuEvtHandler
::Detach()
4831 m_wnd
->SetAcceleratorTable(m_oldAccelTable
);
4833 m_wnd
->RemoveEventHandler(this);
4838 BEGIN_EVENT_TABLE(wxWin32SystemMenuEvtHandler
, wxEvtHandler
)
4839 EVT_MENU(wxID_SYSTEM_MENU
, wxWin32SystemMenuEvtHandler
::OnSystemMenu
)
4840 EVT_MENU(wxID_CLOSE_FRAME
, wxWin32SystemMenuEvtHandler
::OnCloseFrame
)
4841 EVT_CLOSE(wxWin32SystemMenuEvtHandler
::OnClose
)
4844 void wxWin32SystemMenuEvtHandler
::OnSystemMenu(wxCommandEvent
&WXUNUSED(event
))
4846 int border
= ((m_wnd
->GetWindowStyle() & wxRESIZE_BORDER
) &&
4847 !m_wnd
->IsMaximized()) ?
4848 RESIZEABLE_FRAME_BORDER_THICKNESS
:
4849 FRAME_BORDER_THICKNESS
;
4850 wxPoint pt
= m_wnd
->GetClientAreaOrigin();
4851 pt
.x
= -pt
.x
+ border
;
4852 pt
.y
= -pt
.y
+ border
+ FRAME_TITLEBAR_HEIGHT
;
4855 wxAcceleratorTable table
= *m_wnd
->GetAcceleratorTable();
4856 m_wnd
->SetAcceleratorTable(wxNullAcceleratorTable
);
4859 m_inputHnd
->PopupSystemMenu(m_wnd
, pt
);
4862 m_wnd
->SetAcceleratorTable(table
);
4866 void wxWin32SystemMenuEvtHandler
::OnCloseFrame(wxCommandEvent
&WXUNUSED(event
))
4868 m_wnd
->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK
,
4869 wxTOPLEVEL_BUTTON_CLOSE
);
4872 void wxWin32SystemMenuEvtHandler
::OnClose(wxCloseEvent
&event
)
4879 wxWin32FrameInputHandler
::wxWin32FrameInputHandler(wxInputHandler
*handler
)
4880 : wxStdFrameInputHandler(handler
)
4882 m_menuHandler
= new wxWin32SystemMenuEvtHandler(this);
4885 wxWin32FrameInputHandler
::~wxWin32FrameInputHandler()
4887 if ( m_menuHandler
)
4889 m_menuHandler
->Detach();
4890 delete m_menuHandler
;
4894 bool wxWin32FrameInputHandler
::HandleMouse(wxInputConsumer
*consumer
,
4895 const wxMouseEvent
& event
)
4897 if ( event
.LeftDClick() || event
.LeftDown() || event
.RightDown() )
4899 wxTopLevelWindow
*tlw
=
4900 wxStaticCast(consumer
->GetInputWindow(), wxTopLevelWindow
);
4902 long hit
= tlw
->HitTest(event
.GetPosition());
4904 if ( event
.LeftDClick() && hit
== wxHT_TOPLEVEL_TITLEBAR
)
4906 tlw
->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK
,
4907 tlw
->IsMaximized() ? wxTOPLEVEL_BUTTON_RESTORE
4908 : wxTOPLEVEL_BUTTON_MAXIMIZE
);
4911 else if ( tlw
->GetWindowStyle() & wxSYSTEM_MENU
)
4913 if ( (event
.LeftDown() && hit
== wxHT_TOPLEVEL_ICON
) ||
4914 (event
.RightDown() &&
4915 (hit
== wxHT_TOPLEVEL_TITLEBAR
||
4916 hit
== wxHT_TOPLEVEL_ICON
)) )
4918 PopupSystemMenu(tlw
, event
.GetPosition());
4924 return wxStdFrameInputHandler
::HandleMouse(consumer
, event
);
4927 void wxWin32FrameInputHandler
::PopupSystemMenu(wxTopLevelWindow
*window
,
4928 const wxPoint
& pos
) const
4930 wxMenu
*menu
= new wxMenu
;
4932 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4933 menu
->Append(wxID_RESTORE_FRAME
, _("&Restore"));
4934 menu
->Append(wxID_MOVE_FRAME
, _("&Move"));
4935 if ( window
->GetWindowStyle() & wxRESIZE_BORDER
)
4936 menu
->Append(wxID_RESIZE_FRAME
, _("&Size"));
4937 if ( wxSystemSettings
::HasFeature(wxSYS_CAN_ICONIZE_FRAME
) )
4938 menu
->Append(wxID_ICONIZE_FRAME
, _("Mi&nimize"));
4939 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4940 menu
->Append(wxID_MAXIMIZE_FRAME
, _("Ma&ximize"));
4941 menu
->AppendSeparator();
4942 menu
->Append(wxID_CLOSE_FRAME
, _("Close\tAlt-F4"));
4944 if ( window
->GetWindowStyle() & wxMAXIMIZE_BOX
)
4946 if ( window
->IsMaximized() )
4948 menu
->Enable(wxID_MAXIMIZE_FRAME
, false);
4949 menu
->Enable(wxID_MOVE_FRAME
, false);
4950 if ( window
->GetWindowStyle() & wxRESIZE_BORDER
)
4951 menu
->Enable(wxID_RESIZE_FRAME
, false);
4954 menu
->Enable(wxID_RESTORE_FRAME
, false);
4957 window
->PopupMenu(menu
, pos
);
4961 bool wxWin32FrameInputHandler
::HandleActivation(wxInputConsumer
*consumer
,
4964 if ( consumer
->GetInputWindow()->GetWindowStyle() & wxSYSTEM_MENU
)
4966 // always detach if active frame changed:
4967 m_menuHandler
->Detach();
4971 m_menuHandler
->Attach(consumer
);
4975 return wxStdFrameInputHandler
::HandleActivation(consumer
, activated
);