1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/os2/button.cpp 
   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" 
  15 #include "wx/button.h" 
  21     #include "wx/bmpbuttn.h" 
  22     #include "wx/settings.h" 
  23     #include "wx/dcscreen.h" 
  24     #include "wx/scrolwin.h" 
  25     #include "wx/toplevel.h" 
  28 #include "wx/stockitem.h" 
  29 #include "wx/os2/private.h" 
  31 #define BUTTON_HEIGHT_FROM_CHAR_HEIGHT(cy) (11*EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy)/10) 
  34 // Should be at the very least less than winDEFAULT_BUTTON_MARGIN 
  36 #define FOCUS_MARGIN 3 
  39 #define BST_CHECKED 0x0001 
  44 bool wxButton::Create( wxWindow
*          pParent
, 
  46                        const wxString
&    rsLbl
, 
  50                        const wxValidator
& rValidator
, 
  51                        const wxString
&    rsName
) 
  53     wxString 
rsLabel(rsLbl
); 
  54     if (rsLabel
.empty() && wxIsStockID(vId
)) 
  55         rsLabel 
= wxGetStockLabel(vId
); 
  57     wxString                        sLabel 
= ::wxPMTextToLabel(rsLabel
); 
  61     SetValidator(rValidator
); 
  63     m_windowStyle 
= lStyle
; 
  64     pParent
->AddChild((wxButton 
*)this); 
  66         m_windowId 
= NewControlId(); 
  69     lStyle 
= WS_VISIBLE 
| WS_TABSTOP 
| BS_PUSHBUTTON
; 
  72     // OS/2 PM does not have Right/Left/Top/Bottom styles. 
  73     // We will have to define an additional style when we implement notebooks 
  74     // for a notebook page button 
  76     if (m_windowStyle 
& wxCLIP_SIBLINGS 
) 
  77         lStyle 
|= WS_CLIPSIBLINGS
; 
  79     m_hWnd 
= (WXHWND
)::WinCreateWindow( GetHwndOf(pParent
)   // Parent handle 
  80                                        ,WC_BUTTON            
// A Button class window 
  81                                        ,sLabel
.c_str()  // Button text 
  82                                        ,lStyle               
// Button style 
  83                                        ,0, 0, 0, 0           // Location and size 
  84                                        ,GetHwndOf(pParent
)   // Owner handle 
  85                                        ,HWND_TOP             
// Top of Z-Order 
  87                                        ,NULL                 
// No control data 
  88                                        ,NULL                 
// No Presentation parameters 
  96     // Subclass again for purposes of dialog editing mode 
  99     wxFont
*                          pButtonFont 
= new wxFont( 8 
 104     SetFont(*pButtonFont
); 
 114 } // end of wxButton::Create 
 116 wxButton::~wxButton() 
 118     wxTopLevelWindow 
*tlw 
= wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow
); 
 122         if (tlw
->GetDefaultItem() == this) 
 125             // Don't leave the panel with invalid default item 
 127             tlw
->SetDefaultItem(NULL
); 
 130 } // end of wxButton::~wxButton 
 132 // ---------------------------------------------------------------------------- 
 133 // size management including autosizing 
 134 // ---------------------------------------------------------------------------- 
 136 wxSize 
wxButton::DoGetBestSize() const 
 138     wxString                        rsLabel 
= wxGetWindowText(GetHWND()); 
 142     wxFont                          vFont 
= (wxFont
)GetFont(); 
 144     GetTextExtent( rsLabel
 
 149     wxGetCharSize( GetHWND() 
 156     // Add a margin - the button is wider than just its label 
 158     nWidthButton 
+= 3 * nWidthChar
; 
 161     // The button height is proportional to the height of the font used 
 163     int                             nHeightButton 
= BUTTON_HEIGHT_FROM_CHAR_HEIGHT(nHeightChar
); 
 166     // Need a little extra to make it look right 
 168     nHeightButton 
+= (int)(nHeightChar
/1.5); 
 170     if (!HasFlag(wxBU_EXACTFIT
)) 
 172         wxSize                      vSize 
= GetDefaultSize(); 
 174         if (nWidthButton 
> vSize
.x
) 
 175             vSize
.x 
= nWidthButton
; 
 176         if (nHeightButton 
> vSize
.y
) 
 177             vSize
.y 
= nHeightButton
; 
 180     return wxSize( nWidthButton
 
 183 } // end of wxButton::DoGetBestSize 
 186 wxSize 
wxButton::GetDefaultSize() 
 188     static wxSize                   vSizeBtn
; 
 194         vDc
.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
)); 
 197         // The size of a standard button in the dialog units is 50x14, 
 198         // translate this to pixels 
 199         // NB1: the multipliers come from the Windows convention 
 200         // NB2: the extra +1/+2 were needed to get the size be the same as the 
 201         //      size of the buttons in the standard dialog - I don't know how 
 202         //      this happens, but on my system this size is 75x23 in pixels and 
 203         //      23*8 isn't even divisible by 14... Would be nice to understand 
 204         //      why these constants are needed though! 
 205         vSizeBtn
.x 
= (50 * (vDc
.GetCharWidth() + 1))/4; 
 206         vSizeBtn
.y 
= ((14 * vDc
.GetCharHeight()) + 2)/8; 
 209 } // end of wxButton::GetDefaultSize 
 211 void wxButton::Command ( 
 212   wxCommandEvent
&                   rEvent
 
 215     ProcessCommand (rEvent
); 
 216 } // end of wxButton::Command 
 218 // ---------------------------------------------------------------------------- 
 220 // ---------------------------------------------------------------------------- 
 222 bool wxButton::SendClickEvent() 
 224     wxCommandEvent                  
vEvent( wxEVT_COMMAND_BUTTON_CLICKED
 
 228     vEvent
.SetEventObject(this); 
 229     return ProcessCommand(vEvent
); 
 230 } // end of wxButton::SendClickEvent 
 232 wxWindow 
*wxButton::SetDefault() 
 235     // Set this one as the default button both for wxWidgets and Windows 
 237     wxWindow
* pWinOldDefault 
= wxButtonBase::SetDefault(); 
 239     SetDefaultStyle( wxDynamicCast(pWinOldDefault
, wxButton
), false); 
 240     SetDefaultStyle( this, true ); 
 242     return pWinOldDefault
; 
 243 } // end of wxButton::SetDefault 
 245 void wxButton::SetTmpDefault() 
 247     wxTopLevelWindow 
*tlw 
= wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow
); 
 249     wxCHECK_RET( tlw
, wxT("button without top level window?") ); 
 251     wxWindow
*                       pWinOldDefault 
= tlw
->GetDefaultItem(); 
 253     tlw
->SetTmpDefaultItem(this); 
 254     SetDefaultStyle( wxDynamicCast(pWinOldDefault
, wxButton
), false); 
 255     SetDefaultStyle( this, true ); 
 256 } // end of wxButton::SetTmpDefault 
 258 void wxButton::UnsetTmpDefault() 
 260     wxTopLevelWindow 
*tlw 
= wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow
); 
 262     wxCHECK_RET( tlw
, wxT("button without top level window?") ); 
 264     tlw
->SetTmpDefaultItem(NULL
); 
 266     wxWindow
*                       pWinOldDefault 
= tlw
->GetDefaultItem(); 
 268     SetDefaultStyle( this, false ); 
 269     SetDefaultStyle( wxDynamicCast(pWinOldDefault
, wxButton
), true ); 
 270 } // end of wxButton::UnsetTmpDefault 
 272 void wxButton::SetDefaultStyle( 
 279     // We may be called with NULL pointer -- simpler to do the check here than 
 280     // in the caller which does wxDynamicCast() 
 286     // First, let DefDlgProc() know about the new default button 
 290         if (!wxTheApp
->IsActive()) 
 294         // In OS/2 the dialog/panel doesn't really know it has a default 
 295         // button, the default button simply has that style.  We'll just 
 296         // simulate by setting focus to it 
 300     lStyle 
= ::WinQueryWindowULong(GetHwndOf(pBtn
), QWL_STYLE
); 
 301     if (!(lStyle 
& BS_DEFAULT
) == bOn
) 
 303         if ((lStyle 
& BS_USERBUTTON
) != BS_USERBUTTON
) 
 306                 lStyle 
|= BS_DEFAULT
; 
 308                 lStyle 
&= ~BS_DEFAULT
; 
 309             ::WinSetWindowULong(GetHwndOf(pBtn
), QWL_STYLE
, lStyle
); 
 314             // Redraw the button - it will notice itself that it's not the 
 315             // default one any longer 
 320 } // end of wxButton::UpdateDefaultStyle 
 322 // ---------------------------------------------------------------------------- 
 323 // event/message handlers 
 324 // ---------------------------------------------------------------------------- 
 326 bool wxButton::OS2Command(WXUINT uParam
, WXWORD 
WXUNUSED(wId
)) 
 328     bool bProcessed 
= false; 
 332         case BN_CLICKED
:            // normal buttons send this 
 333         case BN_DBLCLICKED
:         // owner-drawn ones also send this 
 334             bProcessed 
= SendClickEvent(); 
 339 } // end of wxButton::OS2Command 
 341 WXHBRUSH 
wxButton::OnCtlColor( WXHDC    
WXUNUSED(pDC
), 
 342                                WXHWND   
WXUNUSED(pWnd
), 
 343                                WXUINT   
WXUNUSED(nCtlColor
), 
 344                                WXUINT   
WXUNUSED(uMessage
), 
 345                                WXWPARAM 
WXUNUSED(wParam
), 
 346                                WXLPARAM 
WXUNUSED(lParam
) ) 
 348     wxBrush
* pBackgroundBrush 
= wxTheBrushList
->FindOrCreateBrush( GetBackgroundColour() 
 352     return (WXHBRUSH
)pBackgroundBrush
->GetResourceHandle(); 
 353 } // end of wxButton::OnCtlColor 
 355 void wxButton::MakeOwnerDrawn() 
 359     lStyle 
= ::WinQueryWindowULong(GetHwnd(), QWL_STYLE
); 
 360     if ((lStyle 
& BS_USERBUTTON
) != BS_USERBUTTON
) 
 365         lStyle 
|= BS_USERBUTTON
; 
 366         ::WinSetWindowULong(GetHwnd(), QWL_STYLE
, lStyle
); 
 368 } // end of wxButton::MakeOwnerDrawn 
 370 WXDWORD 
wxButton::OS2GetStyle( 
 372 , WXDWORD
*                          pdwExstyle
 
 376     // Buttons never have an external border, they draw their own one 
 378     WXDWORD                         dwStyle 
= wxControl::OS2GetStyle( (lStyle 
& ~wxBORDER_MASK
) | wxBORDER_NONE
 
 383     // We must use WS_CLIPSIBLINGS with the buttons or they would draw over 
 384     // each other in any resizable dialog which has more than one button in 
 387     dwStyle 
|= WS_CLIPSIBLINGS
; 
 389 } // end of wxButton::OS2GetStyle 
 391 MRESULT 
wxButton::WindowProc( WXUINT   uMsg
, 
 396     // When we receive focus, we want to temporary become the default button in 
 397     // our parent panel so that pressing "Enter" would activate us -- and when 
 398     // losing it we should restore the previous default button as well 
 400     if (uMsg 
== WM_SETFOCUS
) 
 402         if (SHORT1FROMMP(lParam
) == TRUE
) 
 408         // Let the default processign take place too 
 412     else if (uMsg 
== WM_BUTTON1DBLCLK
) 
 415         // Emulate a click event to force an owner-drawn button to change its 
 416         // appearance - without this, it won't do it 
 418         (void)wxControl::OS2WindowProc( WM_BUTTON1DOWN
 
 424         // And conitnue with processing the message normally as well 
 429     // Let the base class do all real processing 
 431     return (wxControl::OS2WindowProc( uMsg
 
 435 } // end of wxWindowProc