1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/msw/bmpbuttn.cpp 
   3 // Purpose:     wxBitmapButton 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  13 #pragma implementation "bmpbuttn.h" 
  16 // For compilers that support precompilation, includes "wx.h". 
  17 #include "wx/wxprec.h" 
  26     #include "wx/bmpbuttn.h" 
  28     #include "wx/dcmemory.h" 
  31 #include "wx/msw/private.h" 
  33 // ---------------------------------------------------------------------------- 
  35 // ---------------------------------------------------------------------------- 
  37 #if wxUSE_EXTENDED_RTTI 
  39 WX_DEFINE_FLAGS( wxBitmapButtonStyle 
) 
  41 wxBEGIN_FLAGS( wxBitmapButtonStyle 
) 
  42     // new style border flags, we put them first to 
  43     // use them for streaming out 
  44     wxFLAGS_MEMBER(wxBORDER_SIMPLE
) 
  45     wxFLAGS_MEMBER(wxBORDER_SUNKEN
) 
  46     wxFLAGS_MEMBER(wxBORDER_DOUBLE
) 
  47     wxFLAGS_MEMBER(wxBORDER_RAISED
) 
  48     wxFLAGS_MEMBER(wxBORDER_STATIC
) 
  49     wxFLAGS_MEMBER(wxBORDER_NONE
) 
  51     // old style border flags 
  52     wxFLAGS_MEMBER(wxSIMPLE_BORDER
) 
  53     wxFLAGS_MEMBER(wxSUNKEN_BORDER
) 
  54     wxFLAGS_MEMBER(wxDOUBLE_BORDER
) 
  55     wxFLAGS_MEMBER(wxRAISED_BORDER
) 
  56     wxFLAGS_MEMBER(wxSTATIC_BORDER
) 
  57     wxFLAGS_MEMBER(wxBORDER
) 
  59     // standard window styles 
  60     wxFLAGS_MEMBER(wxTAB_TRAVERSAL
) 
  61     wxFLAGS_MEMBER(wxCLIP_CHILDREN
) 
  62     wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
) 
  63     wxFLAGS_MEMBER(wxWANTS_CHARS
) 
  64     wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
) 
  65     wxFLAGS_MEMBER(wxALWAYS_SHOW_SB 
) 
  66     wxFLAGS_MEMBER(wxVSCROLL
) 
  67     wxFLAGS_MEMBER(wxHSCROLL
) 
  69     wxFLAGS_MEMBER(wxBU_AUTODRAW
) 
  70     wxFLAGS_MEMBER(wxBU_LEFT
) 
  71     wxFLAGS_MEMBER(wxBU_RIGHT
) 
  72     wxFLAGS_MEMBER(wxBU_TOP
) 
  73     wxFLAGS_MEMBER(wxBU_BOTTOM
) 
  74 wxEND_FLAGS( wxBitmapButtonStyle 
) 
  76 IMPLEMENT_DYNAMIC_CLASS_XTI(wxBitmapButton
, wxButton
,"wx/bmpbuttn.h") 
  78 wxBEGIN_PROPERTIES_TABLE(wxBitmapButton
) 
  79     wxPROPERTY_FLAGS( WindowStyle 
, wxBitmapButtonStyle 
, long , SetWindowStyleFlag 
, GetWindowStyleFlag 
, , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style 
  80 wxEND_PROPERTIES_TABLE() 
  82 wxBEGIN_HANDLERS_TABLE(wxBitmapButton
) 
  83 wxEND_HANDLERS_TABLE() 
  85 wxCONSTRUCTOR_5( wxBitmapButton 
, wxWindow
* , Parent 
, wxWindowID 
, Id 
, wxBitmap 
, Bitmap 
, wxPoint 
, Position 
, wxSize 
, Size 
) 
  88 IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton
, wxButton
) 
  94 long "style" , wxBU_AUTODRAW 
 101 #define BUTTON_HEIGHT_FACTOR (EDIT_CONTROL_FACTOR * 1.1) 
 103 bool wxBitmapButton::Create(wxWindow 
*parent
, wxWindowID id
, 
 104     const wxBitmap
& bitmap
, 
 106     const wxSize
& size
, long style
, 
 107     const wxValidator
& wxVALIDATOR_PARAM(validator
), 
 108     const wxString
& name
) 
 110     m_bmpNormal 
= bitmap
; 
 114     SetValidator(validator
); 
 115 #endif // wxUSE_VALIDATORS 
 117     parent
->AddChild(this); 
 119     m_backgroundColour 
= parent
->GetBackgroundColour(); 
 120     m_foregroundColour 
= parent
->GetForegroundColour(); 
 121     m_windowStyle 
= style
; 
 123     if ( style 
& wxBU_AUTODRAW 
) 
 125         m_marginX 
= wxDEFAULT_BUTTON_MARGIN
; 
 126         m_marginY 
= wxDEFAULT_BUTTON_MARGIN
; 
 135         m_windowId 
= NewControlId(); 
 141         wxSize newSize 
= DoGetBestSize(); 
 148     long msStyle 
= WS_VISIBLE 
| WS_TABSTOP 
| WS_CHILD 
| BS_OWNERDRAW 
; 
 150     if ( m_windowStyle 
& wxCLIP_SIBLINGS 
) 
 151         msStyle 
|= WS_CLIPSIBLINGS
; 
 154     if(m_windowStyle 
& wxBU_LEFT
) 
 156     if(m_windowStyle 
& wxBU_RIGHT
) 
 158     if(m_windowStyle 
& wxBU_TOP
) 
 160     if(m_windowStyle 
& wxBU_BOTTOM
) 
 161         msStyle 
|= BS_BOTTOM
; 
 164     m_hWnd 
= (WXHWND
) CreateWindowEx( 
 176     // Subclass again for purposes of dialog editing mode 
 179     SetFont(parent
->GetFont()); 
 181     SetSize(x
, y
, width
, height
); 
 186 // VZ: should be at the very least less than wxDEFAULT_BUTTON_MARGIN 
 187 #define FOCUS_MARGIN 3 
 189 bool wxBitmapButton::MSWOnDraw(WXDRAWITEMSTRUCT 
*item
) 
 192     long style 
= GetWindowLong((HWND
) GetHWND(), GWL_STYLE
); 
 193     if (style 
& BS_BITMAP
) 
 195         // Let default procedure draw the bitmap, which is defined 
 196         // in the Windows resource. 
 201     LPDRAWITEMSTRUCT lpDIS 
= (LPDRAWITEMSTRUCT
) item
; 
 202     HDC hDC                
= lpDIS
->hDC
; 
 203     UINT state             
= lpDIS
->itemState
; 
 204     bool isSelected        
= (state 
& ODS_SELECTED
) != 0; 
 205     bool autoDraw          
= (GetWindowStyleFlag() & wxBU_AUTODRAW
) != 0; 
 208     // choose the bitmap to use depending on the button state 
 211     if ( isSelected 
&& m_bmpSelected
.Ok() ) 
 212         bitmap 
= &m_bmpSelected
; 
 213     else if ((state 
& ODS_FOCUS
) && m_bmpFocus
.Ok()) 
 214         bitmap 
= &m_bmpFocus
; 
 215     else if ((state 
& ODS_DISABLED
) && m_bmpDisabled
.Ok()) 
 216         bitmap 
= &m_bmpDisabled
; 
 218         bitmap 
= &m_bmpNormal
; 
 223     // centre the bitmap in the control area 
 224     int x      
= lpDIS
->rcItem
.left
; 
 225     int y      
= lpDIS
->rcItem
.top
; 
 226     int width  
= lpDIS
->rcItem
.right 
- x
; 
 227     int height 
= lpDIS
->rcItem
.bottom 
- y
; 
 228     int wBmp   
= bitmap
->GetWidth(); 
 229     int hBmp   
= bitmap
->GetHeight(); 
 233     if(m_windowStyle 
& wxBU_LEFT
) 
 234         x1 
= x 
+ (FOCUS_MARGIN
+1); 
 235     else if(m_windowStyle 
& wxBU_RIGHT
) 
 236         x1 
= x 
+ (width 
- wBmp
) - (FOCUS_MARGIN
+1); 
 238         x1 
= x 
+ (width 
- wBmp
) / 2; 
 240     if(m_windowStyle 
& wxBU_TOP
) 
 241         y1 
= y 
+ (FOCUS_MARGIN
+1); 
 242     else if(m_windowStyle 
& wxBU_BOTTOM
) 
 243         y1 
= y 
+ (height 
- hBmp
) - (FOCUS_MARGIN
+1); 
 245         y1 
= y 
+ (height 
- hBmp
) / 2; 
 247     if ( isSelected 
&& autoDraw 
) 
 253     // draw the face, if auto-drawing 
 256         DrawFace((WXHDC
) hDC
, 
 257                  lpDIS
->rcItem
.left
, lpDIS
->rcItem
.top
, 
 258                  lpDIS
->rcItem
.right
, lpDIS
->rcItem
.bottom
, 
 264     dst
.SetHDC((WXHDC
) hDC
, false); 
 265     dst
.DrawBitmap(*bitmap
, x1
, y1
, true); 
 267     // draw focus / disabled state, if auto-drawing 
 268     if ( (state 
& ODS_DISABLED
) && autoDraw 
) 
 270         DrawButtonDisable((WXHDC
) hDC
, 
 271                           lpDIS
->rcItem
.left
, lpDIS
->rcItem
.top
, 
 272                           lpDIS
->rcItem
.right
, lpDIS
->rcItem
.bottom
, 
 275     else if ( (state 
& ODS_FOCUS
) && autoDraw 
) 
 277         DrawButtonFocus((WXHDC
) hDC
, 
 281                         lpDIS
->rcItem
.bottom
, 
 288 // GRG Feb/2000, support for bmp buttons with Win95/98 standard LNF 
 290 #if defined(__WIN95__) 
 292 void wxBitmapButton::DrawFace( WXHDC dc
, int left
, int top
, 
 293     int right
, int bottom
, bool sel 
) 
 302     // create needed pens and brush 
 303     penHiLight  
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DHILIGHT
)); 
 304     penLight    
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DLIGHT
)); 
 305     penShadow   
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DSHADOW
)); 
 306     penDkShadow 
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DDKSHADOW
)); 
 307     // brushFace   = CreateSolidBrush(GetSysColor(COLOR_BTNFACE)); 
 308     // Taking the background colour fits in better with 
 309     // Windows XP themes. 
 310     brushFace   
= CreateSolidBrush(m_backgroundColour
.m_pixel
); 
 312     // draw the rectangle 
 317     rect
.bottom 
= bottom
; 
 318     FillRect((HDC
) dc
, &rect
, brushFace
); 
 321     oldp 
= (HPEN
) SelectObject( (HDC
) dc
, sel
? penDkShadow 
: penHiLight
); 
 323     wxDrawLine((HDC
) dc
, left
, top
, right
-1, top
); 
 324     wxDrawLine((HDC
) dc
, left
, top
+1, left
, bottom
-1); 
 326     SelectObject( (HDC
) dc
, sel
? penShadow 
: penLight
); 
 327     wxDrawLine((HDC
) dc
, left
+1, top
+1, right
-2, top
+1); 
 328     wxDrawLine((HDC
) dc
, left
+1, top
+2, left
+1, bottom
-2); 
 330     SelectObject( (HDC
) dc
, sel
? penLight 
: penShadow
); 
 331     wxDrawLine((HDC
) dc
, left
+1, bottom
-2, right
-1, bottom
-2); 
 332     wxDrawLine((HDC
) dc
, right
-2, bottom
-3, right
-2, top
); 
 334     SelectObject( (HDC
) dc
, sel
? penHiLight 
: penDkShadow
); 
 335     wxDrawLine((HDC
) dc
, left
, bottom
-1, right
+2, bottom
-1); 
 336     wxDrawLine((HDC
) dc
, right
-1, bottom
-2, right
-1, top
-1); 
 338     // delete allocated resources 
 339     SelectObject((HDC
) dc
,oldp
); 
 340     DeleteObject(penHiLight
); 
 341     DeleteObject(penLight
); 
 342     DeleteObject(penShadow
); 
 343     DeleteObject(penDkShadow
); 
 344     DeleteObject(brushFace
); 
 349 void wxBitmapButton::DrawFace( WXHDC dc
, int left
, int top
, 
 350     int right
, int bottom
, bool sel 
) 
 358     // create needed pens and brush 
 359     penBorder 
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_WINDOWFRAME
)); 
 360     penShadow 
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_BTNSHADOW
)); 
 361     penLight  
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_BTNHIGHLIGHT
)); 
 362     brushFace 
= CreateSolidBrush(COLOR_BTNFACE
); 
 364     // draw the rectangle 
 369     rect
.bottom 
= bottom
; 
 370     FillRect((HDC
) dc
, &rect
, brushFace
); 
 373     oldp 
= (HPEN
) SelectObject( (HDC
) dc
, penBorder
); 
 374     MoveToEx((HDC
) dc
,left
+1,top
,NULL
);LineTo((HDC
) dc
,right
-1,top
); 
 375     MoveToEx((HDC
) dc
,left
,top
+1,NULL
);LineTo((HDC
) dc
,left
,bottom
-1); 
 376     MoveToEx((HDC
) dc
,left
+1,bottom
-1,NULL
);LineTo((HDC
) dc
,right
-1,bottom
-1); 
 377     MoveToEx((HDC
) dc
,right
-1,top
+1,NULL
);LineTo((HDC
) dc
,right
-1,bottom
-1); 
 379     SelectObject( (HDC
) dc
, penShadow
); 
 382         MoveToEx((HDC
) dc
,left
+1    ,bottom
-2   ,NULL
); 
 383         LineTo((HDC
) dc
,  left
+1    ,top
+1); 
 384         LineTo((HDC
) dc
,  right
-2   ,top
+1); 
 388         MoveToEx((HDC
) dc
,left
+1    ,bottom
-2   ,NULL
); 
 389         LineTo((HDC
) dc
,  right
-2   ,bottom
-2); 
 390         LineTo((HDC
) dc
,  right
-2   ,top
); 
 392         MoveToEx((HDC
) dc
,left
+2    ,bottom
-3   ,NULL
); 
 393         LineTo((HDC
) dc
,  right
-3   ,bottom
-3); 
 394         LineTo((HDC
) dc
,  right
-3   ,top
+1); 
 396         SelectObject( (HDC
) dc
, penLight
); 
 398         MoveToEx((HDC
) dc
,left
+1    ,bottom
-2   ,NULL
); 
 399         LineTo((HDC
) dc
,  left
+1    ,top
+1); 
 400         LineTo((HDC
) dc
,  right
-2   ,top
+1); 
 403     // delete allocated resources 
 404     SelectObject((HDC
) dc
,oldp
); 
 405     DeleteObject(penBorder
); 
 406     DeleteObject(penLight
); 
 407     DeleteObject(penShadow
); 
 408     DeleteObject(brushFace
); 
 411 #endif // defined(__WIN95__) 
 414 void wxBitmapButton::DrawButtonFocus( WXHDC dc
, int left
, int top
, int right
, 
 415     int bottom
, bool WXUNUSED(sel
) ) 
 421     rect
.bottom 
= bottom
; 
 422     InflateRect( &rect
, - FOCUS_MARGIN
, - FOCUS_MARGIN 
); 
 424     // GRG: the focus rectangle should not move when the button is pushed! 
 427         OffsetRect( &rect, 1, 1 ); 
 430     DrawFocusRect( (HDC
) dc
, &rect 
); 
 433 extern HBRUSH wxDisableButtonBrush
; 
 434 void wxBitmapButton::DrawButtonDisable( WXHDC dc
, int left
, int top
, int right
, 
 435     int bottom
, bool with_marg 
) 
 437     HBRUSH  old 
= (HBRUSH
) SelectObject( (HDC
) dc
, wxDisableButtonBrush 
); 
 439     // ROP for "dest |= pattern" operation -- as it doesn't have a standard 
 440     // name, give it our own 
 441     static const DWORD PATTERNPAINT 
= 0xFA0089UL
; 
 447         right 
-= 2 * m_marginX
; 
 448         bottom 
-= 2 * m_marginY
; 
 451     ::PatBlt( (HDC
) dc
, left
, top
, right
, bottom
, PATTERNPAINT
); 
 453     ::SelectObject( (HDC
) dc
, old 
); 
 456 void wxBitmapButton::SetDefault() 
 458     wxButton::SetDefault(); 
 461 wxSize 
wxBitmapButton::DoGetBestSize() const 
 464     if (m_bmpNormal
.Ok()) 
 466         best
.x 
= m_bmpNormal
.GetWidth() + 2*m_marginX
; 
 467         best
.y 
= m_bmpNormal
.GetHeight() + 2*m_marginY
; 
 470     // all buttons have at least the standard size unless the user explicitly 
 471     // wants them to be of smaller size and used wxBU_EXACTFIT style when 
 472     // creating the button 
 473     if ( !HasFlag(wxBU_EXACTFIT
) ) 
 475         wxSize sz 
= GetDefaultSize(); 
 485 #endif // wxUSE_BMPBUTTON