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" 
  17     #include "wx/button.h" 
  20     #include "wx/bmpbuttn.h" 
  21     #include "wx/settings.h" 
  22     #include "wx/dcscreen.h" 
  23     #include "wx/scrolwin.h" 
  26 #include "wx/os2/private.h" 
  28 #define BUTTON_HEIGHT_FROM_CHAR_HEIGHT(cy) (11*EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy)/10) 
  31 // Should be at the very least less than winDEFAULT_BUTTON_MARGIN 
  33 #define FOCUS_MARGIN 3 
  36 #define BST_CHECKED 0x0001 
  39 IMPLEMENT_DYNAMIC_CLASS(wxButton
, wxControl
) 
  43 bool wxButton::Create( 
  46 , const wxString
&                   rsLabel
 
  50 , const wxValidator
&                rValidator
 
  51 , const wxString
&                   rsName
 
  55     wxString                        sLabel 
= ::wxPMTextToLabel(rsLabel
); 
  59     SetValidator(rValidator
); 
  61     m_windowStyle 
= lStyle
; 
  62     pParent
->AddChild((wxButton 
*)this); 
  64         m_windowId 
= NewControlId(); 
  67     lStyle 
= WS_VISIBLE 
| WS_TABSTOP 
| BS_PUSHBUTTON
; 
  70     // OS/2 PM does not have Right/Left/Top/Bottom styles. 
  71     // We will have to define an additional style when we implement notebooks 
  72     // for a notebook page button 
  74     if (m_windowStyle 
& wxCLIP_SIBLINGS 
) 
  75         lStyle 
|= WS_CLIPSIBLINGS
; 
  77     m_hWnd 
= (WXHWND
)::WinCreateWindow( GetHwndOf(pParent
)   // Parent handle 
  78                                        ,WC_BUTTON            
// A Button class window 
  79                                        ,(PSZ
)sLabel
.c_str()  // Button text 
  80                                        ,lStyle               
// Button style 
  81                                        ,0, 0, 0, 0           // Location and size 
  82                                        ,GetHwndOf(pParent
)   // Owner handle 
  83                                        ,HWND_TOP             
// Top of Z-Order 
  85                                        ,NULL                 
// No control data 
  86                                        ,NULL                 
// No Presentation parameters 
  94     // Subclass again for purposes of dialog editing mode 
  97     wxFont
*                          pButtonFont 
= new wxFont( 8 
 102     SetFont(*pButtonFont
); 
 112 } // end of wxButton::Create 
 114 wxButton::~wxButton() 
 116     wxPanel
*                        pPanel 
= wxDynamicCast(GetParent(), wxPanel
); 
 120         if (pPanel
->GetDefaultItem() == this) 
 123             // Don't leave the panel with invalid default item 
 125             pPanel
->SetDefaultItem(NULL
); 
 128 } // end of wxButton::~wxButton 
 130 // ---------------------------------------------------------------------------- 
 131 // size management including autosizing 
 132 // ---------------------------------------------------------------------------- 
 134 wxSize 
wxButton::DoGetBestSize() const 
 136     wxString                        rsLabel 
= wxGetWindowText(GetHWND()); 
 141     GetTextExtent( rsLabel
 
 146     wxGetCharSize( GetHWND() 
 153     // Add a margin - the button is wider than just its label 
 155     nWidthButton 
+= 3 * nWidthChar
; 
 158     // The button height is proportional to the height of the font used 
 160     int                             nHeightButton 
= BUTTON_HEIGHT_FROM_CHAR_HEIGHT(nHeightChar
); 
 163     // Need a little extra to make it look right 
 165     nHeightButton 
+= (int)(nHeightChar
/1.5); 
 167     if (!HasFlag(wxBU_EXACTFIT
)) 
 169         wxSize                      vSize 
= GetDefaultSize(); 
 171         if (nWidthButton 
> vSize
.x
) 
 172             vSize
.x 
= nWidthButton
; 
 173         if (nHeightButton 
> vSize
.y
) 
 174             vSize
.y 
= nHeightButton
; 
 177     return wxSize( nWidthButton
 
 180 } // end of wxButton::DoGetBestSize 
 183 wxSize 
wxButton::GetDefaultSize() 
 185     static wxSize                   vSizeBtn
; 
 191         vDc
.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
)); 
 194         // The size of a standard button in the dialog units is 50x14, 
 195         // translate this to pixels 
 196         // NB1: the multipliers come from the Windows convention 
 197         // NB2: the extra +1/+2 were needed to get the size be the same as the 
 198         //      size of the buttons in the standard dialog - I don't know how 
 199         //      this happens, but on my system this size is 75x23 in pixels and 
 200         //      23*8 isn't even divisible by 14... Would be nice to understand 
 201         //      why these constants are needed though! 
 202         vSizeBtn
.x 
= (50 * (vDc
.GetCharWidth() + 1))/4; 
 203         vSizeBtn
.y 
= ((14 * vDc
.GetCharHeight()) + 2)/8; 
 206 } // end of wxButton::GetDefaultSize 
 208 void wxButton::Command ( 
 209   wxCommandEvent
&                   rEvent
 
 212     ProcessCommand (rEvent
); 
 213 } // end of wxButton::Command 
 215 // ---------------------------------------------------------------------------- 
 217 // ---------------------------------------------------------------------------- 
 219 bool wxButton::SendClickEvent() 
 221     wxCommandEvent                  
vEvent( wxEVT_COMMAND_BUTTON_CLICKED
 
 225     vEvent
.SetEventObject(this); 
 226     return ProcessCommand(vEvent
); 
 227 } // end of wxButton::SendClickEvent 
 229 void wxButton::SetDefault() 
 231     wxWindow
*                       pParent 
= GetParent(); 
 233     wxCHECK_RET( pParent
, _T("button without parent?") ); 
 236     // Set this one as the default button both for wxWidgets and Windows 
 238     wxWindow
*                       pWinOldDefault 
= pParent
->SetDefaultItem(this); 
 240     SetDefaultStyle( wxDynamicCast(pWinOldDefault
, wxButton
) 
 243     SetDefaultStyle( this 
 246 } // end of wxButton::SetDefault 
 248 void wxButton::SetTmpDefault() 
 250     wxWindow
*                       pParent 
= GetParent(); 
 252     wxCHECK_RET( pParent
, _T("button without parent?") ); 
 254     wxWindow
*                       pWinOldDefault 
= pParent
->GetDefaultItem(); 
 256     pParent
->SetTmpDefaultItem(this); 
 257     SetDefaultStyle( wxDynamicCast(pWinOldDefault
, wxButton
) 
 260     SetDefaultStyle( this 
 263 } // end of wxButton::SetTmpDefault 
 265 void wxButton::UnsetTmpDefault() 
 267     wxWindow
*                       pParent 
= GetParent(); 
 269     wxCHECK_RET( pParent
, _T("button without parent?") ); 
 271     pParent
->SetTmpDefaultItem(NULL
); 
 273     wxWindow
*                       pWinOldDefault 
= pParent
->GetDefaultItem(); 
 275     SetDefaultStyle( this 
 278     SetDefaultStyle( wxDynamicCast(pWinOldDefault
, wxButton
) 
 281 } // end of wxButton::UnsetTmpDefault 
 283 void wxButton::SetDefaultStyle( 
 290     // We may be called with NULL pointer -- simpler to do the check here than 
 291     // in the caller which does wxDynamicCast() 
 297     // First, let DefDlgProc() know about the new default button 
 301         if (!wxTheApp
->IsActive()) 
 305         // In OS/2 the dialog/panel doesn't really know it has a default 
 306         // button, the default button simply has that style.  We'll just 
 307         // simulate by setting focus to it 
 311     lStyle 
= ::WinQueryWindowULong(GetHwndOf(pBtn
), QWL_STYLE
); 
 312     if (!(lStyle 
& BS_DEFAULT
) == bOn
) 
 314         if ((lStyle 
& BS_USERBUTTON
) != BS_USERBUTTON
) 
 317                 lStyle 
|= BS_DEFAULT
; 
 319                 lStyle 
&= ~BS_DEFAULT
; 
 320             ::WinSetWindowULong(GetHwndOf(pBtn
), QWL_STYLE
, lStyle
); 
 325             // Redraw the button - it will notice itself that it's not the 
 326             // default one any longer 
 331 } // end of wxButton::UpdateDefaultStyle 
 333 // ---------------------------------------------------------------------------- 
 334 // event/message handlers 
 335 // ---------------------------------------------------------------------------- 
 337 bool wxButton::OS2Command( 
 342     bool                            bProcessed 
= FALSE
; 
 346         case BN_CLICKED
:            // normal buttons send this 
 347         case BN_DBLCLICKED
:         // owner-drawn ones also send this 
 348             bProcessed 
= SendClickEvent(); 
 352 } // end of wxButton::OS2Command 
 354 WXHBRUSH 
wxButton::OnCtlColor( 
 363     wxBrush
*                        pBackgroundBrush 
= wxTheBrushList
->FindOrCreateBrush( GetBackgroundColour() 
 367     return (WXHBRUSH
)pBackgroundBrush
->GetResourceHandle(); 
 368 } // end of wxButton::OnCtlColor 
 370 void wxButton::MakeOwnerDrawn() 
 374     lStyle 
= ::WinQueryWindowULong(GetHwnd(), QWL_STYLE
); 
 375     if ((lStyle 
& BS_USERBUTTON
) != BS_USERBUTTON
) 
 380         lStyle 
|= BS_USERBUTTON
; 
 381         ::WinSetWindowULong(GetHwnd(), QWL_STYLE
, lStyle
); 
 383 } // end of wxButton::MakeOwnerDrawn 
 385 WXDWORD 
wxButton::OS2GetStyle( 
 387 , WXDWORD
*                          pdwExstyle
 
 391     // Buttons never have an external border, they draw their own one 
 393     WXDWORD                         dwStyle 
= wxControl::OS2GetStyle( (lStyle 
& ~wxBORDER_MASK
) | wxBORDER_NONE
 
 398     // We must use WS_CLIPSIBLINGS with the buttons or they would draw over 
 399     // each other in any resizeable dialog which has more than one button in 
 402     dwStyle 
|= WS_CLIPSIBLINGS
; 
 404 } // end of wxButton::OS2GetStyle 
 406 MRESULT 
wxButton::WindowProc( 
 413     // When we receive focus, we want to temporary become the default button in 
 414     // our parent panel so that pressing "Enter" would activate us -- and when 
 415     // losing it we should restore the previous default button as well 
 417     if (uMsg 
== WM_SETFOCUS
) 
 419         if (SHORT1FROMMP(lParam
) == TRUE
) 
 425         // Let the default processign take place too 
 429     else if (uMsg 
== WM_BUTTON1DBLCLK
) 
 432         // Emulate a click event to force an owner-drawn button to change its 
 433         // appearance - without this, it won't do it 
 435         (void)wxControl::OS2WindowProc( WM_BUTTON1DOWN
 
 441         // And conitnue with processing the message normally as well 
 446     // Let the base class do all real processing 
 448     return (wxControl::OS2WindowProc( uMsg
 
 452 } // end of wxWindowProc