1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/msw/bmpbuttn.cpp
3 // Purpose:     wxBitmapButton
4 // Author:      Julian Smart
5 // Modified by:
6 // Created:     04/01/98
7 // RCS-ID:      $Id: bmpbuttn.cpp 42816 2006-10-31 08:50:17Z RD $
8 // Copyright:   (c) Julian Smart
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11 
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14 
15 #ifdef __BORLANDC__
16     #pragma hdrstop
17 #endif
18 
19 #if wxUSE_BMPBUTTON
20 
21 #include "wx/bmpbuttn.h"
22 
23 #ifndef WX_PRECOMP
24     #include "wx/log.h"
25     #include "wx/dcmemory.h"
26     #include "wx/image.h"
27 #endif
28 
29 #include "wx/msw/private.h"
30 
31 #include "wx/msw/uxtheme.h"
32 
33 #if wxUSE_UXTHEME
34     // no need to include tmschema.h
35     #ifndef BP_PUSHBUTTON
36         #define BP_PUSHBUTTON 1
37 
38         #define PBS_NORMAL    1
39         #define PBS_HOT       2
40         #define PBS_PRESSED   3
41         #define PBS_DISABLED  4
42         #define PBS_DEFAULTED 5
43 
44         #define TMT_CONTENTMARGINS 3602
45     #endif
46 #endif // wxUSE_UXTHEME
47 
48 #ifndef ODS_NOFOCUSRECT
49     #define ODS_NOFOCUSRECT     0x0200
50 #endif
51 
52 // ----------------------------------------------------------------------------
53 // macros
54 // ----------------------------------------------------------------------------
55 
56 #if wxUSE_EXTENDED_RTTI
57 
58 WX_DEFINE_FLAGS( wxBitmapButtonStyle )
59 
wxBEGIN_FLAGS(wxBitmapButtonStyle)60 wxBEGIN_FLAGS( wxBitmapButtonStyle )
61     // new style border flags, we put them first to
62     // use them for streaming out
63     wxFLAGS_MEMBER(wxBORDER_SIMPLE)
64     wxFLAGS_MEMBER(wxBORDER_SUNKEN)
65     wxFLAGS_MEMBER(wxBORDER_DOUBLE)
66     wxFLAGS_MEMBER(wxBORDER_RAISED)
67     wxFLAGS_MEMBER(wxBORDER_STATIC)
68     wxFLAGS_MEMBER(wxBORDER_NONE)
69 
70     // old style border flags
71     wxFLAGS_MEMBER(wxSIMPLE_BORDER)
72     wxFLAGS_MEMBER(wxSUNKEN_BORDER)
73     wxFLAGS_MEMBER(wxDOUBLE_BORDER)
74     wxFLAGS_MEMBER(wxRAISED_BORDER)
75     wxFLAGS_MEMBER(wxSTATIC_BORDER)
76     wxFLAGS_MEMBER(wxBORDER)
77 
78     // standard window styles
79     wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
80     wxFLAGS_MEMBER(wxCLIP_CHILDREN)
81     wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
82     wxFLAGS_MEMBER(wxWANTS_CHARS)
83     wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
84     wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
85     wxFLAGS_MEMBER(wxVSCROLL)
86     wxFLAGS_MEMBER(wxHSCROLL)
87 
88     wxFLAGS_MEMBER(wxBU_AUTODRAW)
89     wxFLAGS_MEMBER(wxBU_LEFT)
90     wxFLAGS_MEMBER(wxBU_RIGHT)
91     wxFLAGS_MEMBER(wxBU_TOP)
92     wxFLAGS_MEMBER(wxBU_BOTTOM)
93 wxEND_FLAGS( wxBitmapButtonStyle )
94 
95 IMPLEMENT_DYNAMIC_CLASS_XTI(wxBitmapButton, wxButton,"wx/bmpbuttn.h")
96 
97 wxBEGIN_PROPERTIES_TABLE(wxBitmapButton)
98     wxPROPERTY_FLAGS( WindowStyle , wxBitmapButtonStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
99 wxEND_PROPERTIES_TABLE()
100 
101 wxBEGIN_HANDLERS_TABLE(wxBitmapButton)
102 wxEND_HANDLERS_TABLE()
103 
104 wxCONSTRUCTOR_5( wxBitmapButton , wxWindow* , Parent , wxWindowID , Id , wxBitmap , Bitmap , wxPoint , Position , wxSize , Size )
105 
106 #else
107 IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton, wxButton)
108 #endif
109 
110 BEGIN_EVENT_TABLE(wxBitmapButton, wxBitmapButtonBase)
111     EVT_SYS_COLOUR_CHANGED(wxBitmapButton::OnSysColourChanged)
112     EVT_ENTER_WINDOW(wxBitmapButton::OnMouseEnterOrLeave)
113     EVT_LEAVE_WINDOW(wxBitmapButton::OnMouseEnterOrLeave)
114 END_EVENT_TABLE()
115 
116 /*
117 TODO PROPERTIES :
118 
119 long "style" , wxBU_AUTODRAW
120 bool "default" , 0
121 bitmap "selected" ,
122 bitmap "focus" ,
123 bitmap "disabled" ,
124 */
125 
126 bool wxBitmapButton::Create(wxWindow *parent, wxWindowID id,
127     const wxBitmap& bitmap,
128     const wxPoint& pos,
129     const wxSize& size, long style,
130     const wxValidator& wxVALIDATOR_PARAM(validator),
131     const wxString& name)
132 {
133     m_bmpNormal = bitmap;
134     SetName(name);
135 
136 #if wxUSE_VALIDATORS
137     SetValidator(validator);
138 #endif // wxUSE_VALIDATORS
139 
140     parent->AddChild(this);
141 
142     m_windowStyle = style;
143 
144     if ( style & wxBU_AUTODRAW )
145     {
146         m_marginX =
147         m_marginY = 4;
148     }
149 
150     if (id == wxID_ANY)
151         m_windowId = NewControlId();
152     else
153         m_windowId = id;
154 
155     long msStyle = WS_VISIBLE | WS_TABSTOP | WS_CHILD | BS_OWNERDRAW ;
156 
157     if ( m_windowStyle & wxCLIP_SIBLINGS )
158         msStyle |= WS_CLIPSIBLINGS;
159 
160 #ifdef __WIN32__
161     if(m_windowStyle & wxBU_LEFT)
162         msStyle |= BS_LEFT;
163     if(m_windowStyle & wxBU_RIGHT)
164         msStyle |= BS_RIGHT;
165     if(m_windowStyle & wxBU_TOP)
166         msStyle |= BS_TOP;
167     if(m_windowStyle & wxBU_BOTTOM)
168         msStyle |= BS_BOTTOM;
169 #endif
170 
171     m_hWnd = (WXHWND) CreateWindowEx(
172                     0,
173                     wxT("BUTTON"),
174                     wxEmptyString,
175                     msStyle,
176                     0, 0, 0, 0,
177                     GetWinHwnd(parent),
178                     (HMENU)m_windowId,
179                     wxGetInstance(),
180                     NULL
181                    );
182 
183     // Subclass again for purposes of dialog editing mode
184     SubclassWin(m_hWnd);
185 
186     SetPosition(pos);
187     SetInitialSize(size);
188 
189     return true;
190 }
191 
SetBackgroundColour(const wxColour & colour)192 bool wxBitmapButton::SetBackgroundColour(const wxColour& colour)
193 {
194     if ( !wxBitmapButtonBase::SetBackgroundColour(colour) )
195     {
196         // didn't change
197         return false;
198     }
199 
200     // invalidate the brush, it will be recreated the next time it's needed
201     m_brushDisabled = wxNullBrush;
202 
203     return true;
204 }
205 
OnSysColourChanged(wxSysColourChangedEvent & event)206 void wxBitmapButton::OnSysColourChanged(wxSysColourChangedEvent& event)
207 {
208     m_brushDisabled = wxNullBrush;
209 
210     if ( !IsEnabled() )
211     {
212         // this change affects our current state
213         Refresh();
214     }
215 
216     event.Skip();
217 }
218 
OnMouseEnterOrLeave(wxMouseEvent & event)219 void wxBitmapButton::OnMouseEnterOrLeave(wxMouseEvent& event)
220 {
221     if ( IsEnabled() && m_bmpHover.Ok() )
222         Refresh();
223 
224     event.Skip();
225 }
226 
OnSetBitmap()227 void wxBitmapButton::OnSetBitmap()
228 {
229     // if the focus bitmap is specified but hover one isn't, use the focus
230     // bitmap for hovering as well if this is consistent with the current
231     // Windows version look and feel
232     //
233     // rationale: this is compatible with the old wxGTK behaviour and also
234     // makes it much easier to do "the right thing" for all platforms (some of
235     // them, such as Windows XP, have "hot" buttons while others don't)
236     if ( !m_bmpHover.Ok() &&
237             m_bmpFocus.Ok() &&
238                 wxUxThemeEngine::GetIfActive() )
239     {
240         m_bmpHover = m_bmpFocus;
241     }
242 
243     // this will redraw us
244     wxBitmapButtonBase::OnSetBitmap();
245 }
246 
247 #if wxUSE_UXTHEME
248 static
MSWDrawXPBackground(wxButton * button,WXDRAWITEMSTRUCT * wxdis)249 void MSWDrawXPBackground(wxButton *button, WXDRAWITEMSTRUCT *wxdis)
250 {
251     LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)wxdis;
252     HDC hdc = lpDIS->hDC;
253     UINT state = lpDIS->itemState;
254     RECT rectBtn;
255     CopyRect(&rectBtn, &lpDIS->rcItem);
256 
257     wxUxThemeHandle theme(button, L"BUTTON");
258     int iState;
259 
260     if ( state & ODS_SELECTED )
261     {
262         iState = PBS_PRESSED;
263     }
264     else if ( button->HasCapture() || button->IsMouseInWindow() )
265     {
266         iState = PBS_HOT;
267     }
268     else if ( state & ODS_FOCUS )
269     {
270         iState = PBS_DEFAULTED;
271     }
272     else if ( state & ODS_DISABLED )
273     {
274         iState = PBS_DISABLED;
275     }
276     else
277     {
278         iState = PBS_NORMAL;
279     }
280 
281     // draw parent background if needed
282     if ( wxUxThemeEngine::Get()->IsThemeBackgroundPartiallyTransparent(theme,
283                                                                        BP_PUSHBUTTON,
284                                                                        iState) )
285     {
286         wxUxThemeEngine::Get()->DrawThemeParentBackground(GetHwndOf(button), hdc, &rectBtn);
287     }
288 
289     // draw background
290     wxUxThemeEngine::Get()->DrawThemeBackground(theme, hdc, BP_PUSHBUTTON, iState,
291                                                 &rectBtn, NULL);
292 
293     // calculate content area margins
294     MARGINS margins;
295     wxUxThemeEngine::Get()->GetThemeMargins(theme, hdc, BP_PUSHBUTTON, iState,
296                                             TMT_CONTENTMARGINS, &rectBtn, &margins);
297     RECT rectClient;
298     ::CopyRect(&rectClient, &rectBtn);
299     ::InflateRect(&rectClient, -margins.cxLeftWidth, -margins.cyTopHeight);
300 
301     // if focused and !nofocus rect
302     if ( (state & ODS_FOCUS) && !(state & ODS_NOFOCUSRECT) )
303     {
304         DrawFocusRect(hdc, &rectClient);
305     }
306 
307     if ( button->UseBgCol() )
308     {
309         COLORREF colBg = wxColourToRGB(button->GetBackgroundColour());
310         HBRUSH hbrushBackground = ::CreateSolidBrush(colBg);
311 
312         // don't overwrite the focus rect
313         ::InflateRect(&rectClient, -1, -1);
314         FillRect(hdc, &rectClient, hbrushBackground);
315         ::DeleteObject(hbrushBackground);
316     }
317 }
318 #endif // wxUSE_UXTHEME
319 
320 // VZ: should be at the very least less than wxDEFAULT_BUTTON_MARGIN
321 #define FOCUS_MARGIN 3
322 
MSWOnDraw(WXDRAWITEMSTRUCT * item)323 bool wxBitmapButton::MSWOnDraw(WXDRAWITEMSTRUCT *item)
324 {
325 #ifndef __WXWINCE__
326     long style = GetWindowLong((HWND) GetHWND(), GWL_STYLE);
327     if (style & BS_BITMAP)
328     {
329         // Let default procedure draw the bitmap, which is defined
330         // in the Windows resource.
331         return false;
332     }
333 #endif
334 
335     LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT) item;
336     HDC hDC                = lpDIS->hDC;
337     UINT state             = lpDIS->itemState;
338     bool isSelected        = (state & ODS_SELECTED) != 0;
339     bool autoDraw          = (GetWindowStyleFlag() & wxBU_AUTODRAW) != 0;
340 
341 
342     // choose the bitmap to use depending on the button state
343     wxBitmap *bitmap;
344 
345     if ( isSelected && m_bmpSelected.Ok() )
346         bitmap = &m_bmpSelected;
347     else if ( m_bmpHover.Ok() && IsMouseInWindow() )
348         bitmap = &m_bmpHover;
349     else if ((state & ODS_FOCUS) && m_bmpFocus.Ok())
350         bitmap = &m_bmpFocus;
351     else if ((state & ODS_DISABLED) && m_bmpDisabled.Ok())
352         bitmap = &m_bmpDisabled;
353     else
354         bitmap = &m_bmpNormal;
355 
356     if ( !bitmap->Ok() )
357         return false;
358 
359     // centre the bitmap in the control area
360     int x      = lpDIS->rcItem.left;
361     int y      = lpDIS->rcItem.top;
362     int width  = lpDIS->rcItem.right - x;
363     int height = lpDIS->rcItem.bottom - y;
364     int wBmp   = bitmap->GetWidth();
365     int hBmp   = bitmap->GetHeight();
366 
367 #if wxUSE_UXTHEME
368     if ( autoDraw && wxUxThemeEngine::GetIfActive() )
369     {
370         MSWDrawXPBackground(this, item);
371         wxUxThemeHandle theme(this, L"BUTTON");
372 
373         // calculate content area margins
374         // assuming here that each state is the same size
375         MARGINS margins;
376         wxUxThemeEngine::Get()->GetThemeMargins(theme, NULL,
377                                                 BP_PUSHBUTTON, PBS_NORMAL,
378                                                 TMT_CONTENTMARGINS, NULL,
379                                                 &margins);
380         int marginX = margins.cxLeftWidth + 1;
381         int marginY = margins.cyTopHeight + 1;
382         int x1,y1;
383 
384         if ( m_windowStyle & wxBU_LEFT )
385         {
386             x1 = x + marginX;
387         }
388         else if ( m_windowStyle & wxBU_RIGHT )
389         {
390             x1 = x + (width - wBmp) - marginX;
391         }
392         else
393         {
394             x1 = x + (width - wBmp) / 2;
395         }
396 
397         if ( m_windowStyle & wxBU_TOP )
398         {
399             y1 = y + marginY;
400         }
401         else if ( m_windowStyle & wxBU_BOTTOM )
402         {
403             y1 = y + (height - hBmp) - marginY;
404         }
405         else
406         {
407             y1 = y + (height - hBmp) / 2;
408         }
409 
410         // draw the bitmap
411         wxDCTemp dst((WXHDC)hDC);
412         dst.DrawBitmap(*bitmap, x1, y1, true);
413 
414         return true;
415     }
416 #endif // wxUSE_UXTHEME
417 
418     int x1,y1;
419 
420     if(m_windowStyle & wxBU_LEFT)
421         x1 = x + (FOCUS_MARGIN+1);
422     else if(m_windowStyle & wxBU_RIGHT)
423         x1 = x + (width - wBmp) - (FOCUS_MARGIN+1);
424     else
425         x1 = x + (width - wBmp) / 2;
426 
427     if(m_windowStyle & wxBU_TOP)
428         y1 = y + (FOCUS_MARGIN+1);
429     else if(m_windowStyle & wxBU_BOTTOM)
430         y1 = y + (height - hBmp) - (FOCUS_MARGIN+1);
431     else
432         y1 = y + (height - hBmp) / 2;
433 
434     if ( isSelected && autoDraw )
435     {
436         x1++;
437         y1++;
438     }
439 
440     // draw the face, if auto-drawing
441     if ( autoDraw )
442     {
443         DrawFace((WXHDC) hDC,
444                  lpDIS->rcItem.left, lpDIS->rcItem.top,
445                  lpDIS->rcItem.right, lpDIS->rcItem.bottom,
446                  isSelected);
447     }
448 
449     // draw the bitmap
450     wxDCTemp dst((WXHDC)hDC);
451     dst.DrawBitmap(*bitmap, x1, y1, true);
452 
453     // draw focus / disabled state, if auto-drawing
454     if ( (state & ODS_DISABLED) && autoDraw )
455     {
456         DrawButtonDisable((WXHDC) hDC,
457                           lpDIS->rcItem.left, lpDIS->rcItem.top,
458                           lpDIS->rcItem.right, lpDIS->rcItem.bottom,
459                           true);
460     }
461     else if ( (state & ODS_FOCUS) && autoDraw )
462     {
463         DrawButtonFocus((WXHDC) hDC,
464                         lpDIS->rcItem.left,
465                         lpDIS->rcItem.top,
466                         lpDIS->rcItem.right,
467                         lpDIS->rcItem.bottom,
468                         isSelected);
469     }
470 
471     return true;
472 }
473 
474 // GRG Feb/2000, support for bmp buttons with Win95/98 standard LNF
475 
DrawFace(WXHDC dc,int left,int top,int right,int bottom,bool sel)476 void wxBitmapButton::DrawFace( WXHDC dc, int left, int top,
477     int right, int bottom, bool sel )
478 {
479     HPEN oldp;
480     HPEN penHiLight;
481     HPEN penLight;
482     HPEN penShadow;
483     HPEN penDkShadow;
484     HBRUSH brushFace;
485 
486     // create needed pens and brush
487     penHiLight  = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DHILIGHT));
488     penLight    = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DLIGHT));
489     penShadow   = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DSHADOW));
490     penDkShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DDKSHADOW));
491     brushFace   = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
492 
493     // draw the rectangle
494     RECT rect;
495     rect.left   = left;
496     rect.right  = right;
497     rect.top    = top;
498     rect.bottom = bottom;
499     FillRect((HDC) dc, &rect, brushFace);
500 
501     // draw the border
502     oldp = (HPEN) SelectObject( (HDC) dc, sel? penDkShadow : penHiLight);
503 
504     wxDrawLine((HDC) dc, left, top, right-1, top);
505     wxDrawLine((HDC) dc, left, top+1, left, bottom-1);
506 
507     SelectObject( (HDC) dc, sel? penShadow : penLight);
508     wxDrawLine((HDC) dc, left+1, top+1, right-2, top+1);
509     wxDrawLine((HDC) dc, left+1, top+2, left+1, bottom-2);
510 
511     SelectObject( (HDC) dc, sel? penLight : penShadow);
512     wxDrawLine((HDC) dc, left+1, bottom-2, right-1, bottom-2);
513     wxDrawLine((HDC) dc, right-2, bottom-3, right-2, top);
514 
515     SelectObject( (HDC) dc, sel? penHiLight : penDkShadow);
516     wxDrawLine((HDC) dc, left, bottom-1, right+2, bottom-1);
517     wxDrawLine((HDC) dc, right-1, bottom-2, right-1, top-1);
518 
519     // delete allocated resources
520     SelectObject((HDC) dc,oldp);
521     DeleteObject(penHiLight);
522     DeleteObject(penLight);
523     DeleteObject(penShadow);
524     DeleteObject(penDkShadow);
525     DeleteObject(brushFace);
526 }
527 
DrawButtonFocus(WXHDC dc,int left,int top,int right,int bottom,bool WXUNUSED (sel))528 void wxBitmapButton::DrawButtonFocus( WXHDC dc, int left, int top, int right,
529     int bottom, bool WXUNUSED(sel) )
530 {
531     RECT rect;
532     rect.left = left;
533     rect.top = top;
534     rect.right = right;
535     rect.bottom = bottom;
536     InflateRect( &rect, - FOCUS_MARGIN, - FOCUS_MARGIN );
537 
538     // GRG: the focus rectangle should not move when the button is pushed!
539 /*
540     if ( sel )
541         OffsetRect( &rect, 1, 1 );
542 */
543 
544     DrawFocusRect( (HDC) dc, &rect );
545 }
546 
547 void
DrawButtonDisable(WXHDC dc,int left,int top,int right,int bottom,bool with_marg)548 wxBitmapButton::DrawButtonDisable( WXHDC dc,
549                                    int left, int top, int right, int bottom,
550                                    bool with_marg )
551 {
552     if ( !m_brushDisabled.Ok() )
553     {
554         // draw a bitmap with two black and two background colour pixels
555         wxBitmap bmp(2, 2);
556         wxMemoryDC dc;
557         dc.SelectObject(bmp);
558         dc.SetPen(*wxBLACK_PEN);
559         dc.DrawPoint(0, 0);
560         dc.DrawPoint(1, 1);
561         dc.SetPen(GetBackgroundColour());
562         dc.DrawPoint(0, 1);
563         dc.DrawPoint(1, 0);
564 
565         m_brushDisabled = wxBrush(bmp);
566     }
567 
568     SelectInHDC selectBrush((HDC)dc, GetHbrushOf(m_brushDisabled));
569 
570     // ROP for "dest |= pattern" operation -- as it doesn't have a standard
571     // name, give it our own
572     static const DWORD PATTERNPAINT = 0xFA0089UL;
573 
574     if ( with_marg )
575     {
576         left += m_marginX;
577         top += m_marginY;
578         right -= 2 * m_marginX;
579         bottom -= 2 * m_marginY;
580     }
581 
582     ::PatBlt( (HDC) dc, left, top, right, bottom, PATTERNPAINT);
583 }
584 
SetDefault()585 void wxBitmapButton::SetDefault()
586 {
587     wxButton::SetDefault();
588 }
589 
DoGetBestSize() const590 wxSize wxBitmapButton::DoGetBestSize() const
591 {
592     if ( m_bmpNormal.Ok() )
593     {
594         int width = m_bmpNormal.GetWidth(),
595             height = m_bmpNormal.GetHeight();
596         int marginH = 0,
597             marginV = 0;
598 
599 #if wxUSE_UXTHEME
600         if ( wxUxThemeEngine::GetIfActive() )
601         {
602             wxUxThemeHandle theme((wxBitmapButton *)this, L"BUTTON");
603 
604             MARGINS margins;
605             wxUxThemeEngine::Get()->GetThemeMargins(theme, NULL,
606                                                     BP_PUSHBUTTON, PBS_NORMAL,
607                                                     TMT_CONTENTMARGINS, NULL,
608                                                     &margins);
609 
610             // XP doesn't draw themed buttons correctly when the client area is
611             // smaller than 8x8 - enforce this minimum size for small bitmaps
612             if ( width < 8 )
613                 width = 8;
614             if ( height < 8 )
615                 height = 8;
616 
617             // don't add margins for the borderless buttons, they don't need
618             // them and it just makes them appear larger than needed
619             if ( !HasFlag(wxBORDER_NONE) )
620             {
621                 // we need 2 extra pixels for the focus rectangle, without them
622                 // it's overwritten by the bitmap itself
623                 marginH = margins.cxLeftWidth + margins.cxRightWidth + 2;
624                 marginV = margins.cyTopHeight + margins.cyBottomHeight + 2;
625             }
626         }
627         else
628 #endif // wxUSE_UXTHEME
629         {
630             if ( !HasFlag(wxBORDER_NONE) )
631             {
632                 marginH = 2*m_marginX;
633                 marginV = 2*m_marginY;
634             }
635         }
636 
637         wxSize best(width + marginH, height + marginV);
638         CacheBestSize(best);
639         return best;
640     }
641 
642     // no idea what our best size should be, defer to the base class
643     return wxBitmapButtonBase::DoGetBestSize();
644 }
645 
646 #endif // wxUSE_BMPBUTTON
647