1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  16     #include "wx/button.h" 
  19     #include "wx/bmpbuttn.h" 
  20     #include "wx/settings.h" 
  21     #include "wx/dcscreen.h" 
  24 #include "wx/os2/private.h" 
  26 #define BUTTON_HEIGHT_FROM_CHAR_HEIGHT(cy) (11*EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy)/10) 
  29 // Should be at the very least less than winDEFAULT_BUTTON_MARGIN 
  31 #define FOCUS_MARGIN 3 
  34 #define BST_CHECKED 0x0001 
  37 IMPLEMENT_DYNAMIC_CLASS(wxButton
, wxControl
) 
  41 bool wxButton::Create( 
  44 , const wxString
&                   rsLabel
 
  49 , const wxValidator
&                rValidator
 
  51 , const wxString
&                   rsName
 
  56     SetValidator(rValidator
); 
  58     m_windowStyle 
= lStyle
; 
  59     pParent
->AddChild((wxButton 
*)this); 
  61         m_windowId 
= NewControlId(); 
  64     lStyle 
= WS_VISIBLE 
| WS_TABSTOP 
| BS_PUSHBUTTON
; 
  67     // OS/2 PM does not have Right/Left/Top/Bottom styles. 
  68     // We will have to define an additional style when we implement notebooks 
  69     // for a notebook page button 
  71     if (m_windowStyle 
& wxCLIP_SIBLINGS 
) 
  72         lStyle 
|= WS_CLIPSIBLINGS
; 
  74     // If the parent is a scrolled window the controls must 
  75     // have this style or they will overlap the scrollbars 
  78         if (pParent
->IsKindOf(CLASSINFO(wxScrolledWindow
)) || 
  79             pParent
->IsKindOf(CLASSINFO(wxGenericScrolledWindow
))) 
  80             lStyle 
|= WS_CLIPSIBLINGS
; 
  82     m_hWnd 
= (WXHWND
)::WinCreateWindow( GetHwndOf(pParent
)   // Parent handle 
  83                                        ,WC_BUTTON            
// A Button class window 
  84                                        ,(PSZ
)rsLabel
.c_str() // Button text 
  85                                        ,lStyle               
// Button style 
  86                                        ,0, 0, 0, 0           // Location and size 
  87                                        ,GetHwndOf(pParent
)   // Owner handle 
  88                                        ,HWND_TOP             
// Top of Z-Order 
  90                                        ,NULL                 
// No control data 
  91                                        ,NULL                 
// No Presentation parameters 
  99     // Subclass again for purposes of dialog editing mode 
 102     SetFont(pParent
->GetFont()); 
 109 } // end of wxButton::Create 
 111 wxButton::~wxButton() 
 113     wxPanel
*                        pPanel 
= wxDynamicCast(GetParent(), wxPanel
); 
 117         if (pPanel
->GetDefaultItem() == this) 
 120             // Don't leave the panel with invalid default item 
 122             pPanel
->SetDefaultItem(NULL
); 
 125 } // end of wxButton::~wxButton 
 127 // ---------------------------------------------------------------------------- 
 128 // size management including autosizing 
 129 // ---------------------------------------------------------------------------- 
 131 wxSize 
wxButton::DoGetBestSize() const 
 133     wxString                        rsLabel 
= wxGetWindowText(GetHWND()); 
 138     GetTextExtent( rsLabel
 
 143     wxGetCharSize( GetHWND() 
 150     // Add a margin - the button is wider than just its label 
 152     nWidthButton 
+= 3 * nWidthChar
; 
 155     // The button height is proportional to the height of the font used 
 157     int                             nHeightButton 
= BUTTON_HEIGHT_FROM_CHAR_HEIGHT(nHeightChar
); 
 160     // Need a little extra to make it look right 
 162     nHeightButton 
+= nHeightChar
/1.5; 
 164     wxSize                          vSize 
= GetDefaultSize(); 
 166     if (nWidthButton 
> vSize
.x
) 
 167         vSize
.x 
= nWidthButton
; 
 168     if (nHeightButton 
> vSize
.y
) 
 169         vSize
.y 
= nHeightButton
; 
 171 } // end of wxButton::DoGetBestSize 
 174 wxSize 
wxButton::GetDefaultSize() 
 176     static wxSize                   vSizeBtn
; 
 182         vDc
.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
)); 
 185         // The size of a standard button in the dialog units is 50x14, 
 186         // translate this to pixels 
 187         // NB1: the multipliers come from the Windows convention 
 188         // NB2: the extra +1/+2 were needed to get the size be the same as the 
 189         //      size of the buttons in the standard dialog - I don't know how 
 190         //      this happens, but on my system this size is 75x23 in pixels and 
 191         //      23*8 isn't even divisible by 14... Would be nice to understand 
 192         //      why these constants are needed though! 
 193         vSizeBtn
.x 
= (50 * (vDc
.GetCharWidth() + 1))/4; 
 194         vSizeBtn
.y 
= ((14 * vDc
.GetCharHeight()) + 2)/8; 
 197 } // end of wxButton::GetDefaultSize 
 199 void wxButton::Command ( 
 200   wxCommandEvent
&                   rEvent
 
 203     ProcessCommand (rEvent
); 
 204 } // end of wxButton::Command 
 206 // ---------------------------------------------------------------------------- 
 208 // ---------------------------------------------------------------------------- 
 210 bool wxButton::SendClickEvent() 
 212     wxCommandEvent                  
vEvent( wxEVT_COMMAND_BUTTON_CLICKED
 
 216     vEvent
.SetEventObject(this); 
 217     return ProcessCommand(vEvent
); 
 218 } // end of wxButton::SendClickEvent 
 220 void wxButton::SetDefault() 
 222     wxWindow
*                       pParent 
= GetParent(); 
 223     wxButton
*                       pBtnOldDefault 
= NULL
; 
 224     wxPanel
*                        pPanel 
= wxDynamicCast(pParent
, wxPanel
); 
 229         wxWindow
*                   pWinOldDefault 
= pParent
->SetDefaultItem(this); 
 231         pBtnOldDefault 
= wxDynamicCast(pWinOldDefault
, wxButton
); 
 233     if (pBtnOldDefault 
&& pBtnOldDefault 
!= this) 
 236         // Remove the BS_DEFPUSHBUTTON style from the other button 
 238         lStyle 
= ::WinQueryWindowULong(GetHwndOf(pBtnOldDefault
), QWL_STYLE
); 
 241         // Don't do it with the owner drawn buttons because it will reset 
 242         // BS_OWNERDRAW style bit too (BS_OWNERDRAW & BS_DEFPUSHBUTTON != 0)! 
 244         if ((lStyle 
& BS_USERBUTTON
) != BS_USERBUTTON
) 
 246             lStyle 
&= ~BS_DEFAULT
; 
 247             ::WinSetWindowULong(GetHwndOf(pBtnOldDefault
), QWL_STYLE
, lStyle
); 
 252             // Redraw the button - it will notice itself that it's not the 
 253             // default one any longer 
 255             pBtnOldDefault
->Refresh(); 
 260     // Set this button as the default 
 262     lStyle 
= ::WinQueryWindowULong(GetHwnd(), QWL_STYLE
); 
 263     if ((lStyle 
& BS_USERBUTTON
) != BS_USERBUTTON
) 
 265         lStyle 
!= BS_DEFAULT
; 
 266         ::WinSetWindowULong(GetHwnd(), QWL_STYLE
, lStyle
); 
 268 } // end of wxButton::SetDefault 
 270 // ---------------------------------------------------------------------------- 
 271 // event/message handlers 
 272 // ---------------------------------------------------------------------------- 
 274 bool wxButton::OS2Command( 
 279     bool                            bProcessed 
= FALSE
; 
 283         case BN_CLICKED
:            // normal buttons send this 
 284         case BN_DBLCLICKED
:         // owner-drawn ones also send this 
 285             bProcessed 
= SendClickEvent(); 
 289 } // end of wxButton::OS2Command 
 291 WXHBRUSH 
wxButton::OnCtlColor( 
 300     wxBrush
*                        pBackgroundBrush 
= wxTheBrushList
->FindOrCreateBrush( GetBackgroundColour() 
 304     return (WXHBRUSH
)pBackgroundBrush
->GetResourceHandle(); 
 305 } // end of wxButton::OnCtlColor 
 307 void wxButton::MakeOwnerDrawn() 
 311     lStyle 
= ::WinQueryWindowULong(GetHwnd(), QWL_STYLE
); 
 312     if ((lStyle 
& BS_USERBUTTON
) != BS_USERBUTTON
) 
 317         lStyle 
|= BS_USERBUTTON
; 
 318         ::WinSetWindowULong(GetHwnd(), QWL_STYLE
, lStyle
); 
 320 } // end of wxCButton::MakeOwnerDrawn 
 322 MRESULT 
wxButton::WindowProc( 
 329     // When we receive focus, we want to become the default button in our 
 332     if (uMsg 
== WM_SETFOCUS
) 
 337         // Let the default processign take place too 
 341     else if (uMsg 
== WM_BUTTON1DBLCLK
) 
 344         // Emulate a click event to force an owner-drawn button to change its 
 345         // appearance - without this, it won't do it 
 347         (void)wxControl::OS2WindowProc( WM_BUTTON1DOWN
 
 353         // And conitnue with processing the message normally as well 
 358     // Let the base class do all real processing 
 360     return (wxControl::OS2WindowProc( uMsg
 
 364 } // end of wxW indowProc