1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/os2/spinctrl.cpp 
   3 // Purpose:     wxSpinCtrl class implementation for OS/2 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // for compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  30 #include "wx/spinctrl.h" 
  31 #include "wx/os2/private.h" 
  33 // ---------------------------------------------------------------------------- 
  35 // ---------------------------------------------------------------------------- 
  37 extern void  wxAssociateWinWithHandle( HWND         hWnd
 
  40 static WXFARPROC fnWndProcSpinCtrl 
= (WXFARPROC
)NULL
; 
  41 wxArraySpins                        
wxSpinCtrl::m_svAllSpins
; 
  43 IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl
, wxControl
) 
  45 BEGIN_EVENT_TABLE(wxSpinCtrl
, wxSpinButton
) 
  46     EVT_CHAR(wxSpinCtrl::OnChar
) 
  47     EVT_SPIN(wxID_ANY
, wxSpinCtrl::OnSpinChange
) 
  48     EVT_SET_FOCUS(wxSpinCtrl::OnSetFocus
) 
  50 // ---------------------------------------------------------------------------- 
  52 // ---------------------------------------------------------------------------- 
  54 // the margin between the up-down control and its buddy 
  55 static const int MARGIN_BETWEEN 
= 5; 
  57 // ============================================================================ 
  59 // ============================================================================ 
  60 MRESULT EXPENTRY 
wxSpinCtrlWndProc( 
  67     wxSpinCtrl
*                    pSpin 
= (wxSpinCtrl 
*)::WinQueryWindowULong( hWnd
 
  72     // Forward some messages (the key ones only so far) to the spin ctrl 
  77             pSpin
->OS2WindowProc( uMessage
 
  83             // The control may have been deleted at this point, so check. 
  85             if (!(::WinIsWindow(vHabmain
, hWnd
) && ((wxSpinCtrl 
*)::WinQueryWindowULong( hWnd
 
  93     return (fnWndProcSpinCtrl( hWnd
 
  99 } // end of wxSpinCtrlWndProc 
 101 wxSpinCtrl::~wxSpinCtrl() 
 103     m_svAllSpins
.Remove(this); 
 105     // This removes spurious memory leak reporting 
 106     if (m_svAllSpins
.GetCount() == 0) 
 107         m_svAllSpins
.Clear(); 
 108 } // end of wxSpinCtrl::~wxSpinCtrl 
 110 // ---------------------------------------------------------------------------- 
 112 // ---------------------------------------------------------------------------- 
 114 bool wxSpinCtrl::Create( wxWindow
*       pParent
, 
 116                          const wxString
& WXUNUSED(rsValue
), 
 123                          const wxString
& rsName 
) 
 126         m_windowId 
= NewControlId(); 
 131         m_backgroundColour 
= pParent
->GetBackgroundColour(); 
 132         m_foregroundColour 
= pParent
->GetForegroundColour(); 
 136     m_windowStyle      
= lStyle
; 
 140     lSstyle 
= WS_VISIBLE      
| 
 142               SPBS_MASTER     
| // We use only single field spin buttons 
 143               SPBS_NUMERICONLY
; // We default to numeric data 
 145     if (m_windowStyle 
& wxCLIP_SIBLINGS 
) 
 146         lSstyle 
|= WS_CLIPSIBLINGS
; 
 150     vCtrlData
.cbSize 
= sizeof(SPBCDATA
); 
 151     vCtrlData
.ulTextLimit 
= 10L; 
 152     vCtrlData
.lLowerLimit 
= 0L; 
 153     vCtrlData
.lUpperLimit 
= 100L; 
 154     vCtrlData
.idMasterSpb 
= vId
; 
 155     vCtrlData
.pHWXCtlData 
= NULL
; 
 157     m_hWnd 
= (WXHWND
)::WinCreateWindow( GetWinHwnd(pParent
) 
 172     m_hWndBuddy 
= m_hWnd
; // One in the same for OS/2 
 174         pParent
->AddChild((wxSpinButton 
*)this); 
 176     SetFont(*wxSMALL_FONT
); 
 179     SetSize( rPos
.x
, rPos
.y
, rSize
.x
, rSize
.y 
); 
 181     SetRange(nMin
, nMax
); 
 185     // For OS/2 we'll just set our handle into our long data 
 187     wxAssociateWinWithHandle( m_hWnd
 
 190     ::WinSetWindowULong(GetHwnd(), QWL_USER
, (LONG
)this); 
 191     fnWndProcSpinCtrl 
= (WXFARPROC
)::WinSubclassWindow(m_hWnd
, (PFNWP
)wxSpinCtrlWndProc
); 
 192     m_svAllSpins
.Add(this); 
 194 } // end of wxSpinCtrl::Create 
 196 wxSize 
wxSpinCtrl::DoGetBestSize() const 
 198     wxSize                          vSizeBtn 
= wxSpinButton::DoGetBestSize(); 
 200     wxFont                          vFont 
= (wxFont
)GetFont(); 
 202     vSizeBtn
.x 
+= DEFAULT_ITEM_WIDTH 
+ MARGIN_BETWEEN
; 
 204     wxGetCharSize( GetHWND() 
 209     nHeight 
= EDIT_HEIGHT_FROM_CHAR_HEIGHT(nHeight
)+4; 
 211     if (vSizeBtn
.y 
< nHeight
) 
 214         // Make the text tall enough 
 216         vSizeBtn
.y 
= nHeight
; 
 219 } // end of wxSpinCtrl::DoGetBestSize 
 221 void wxSpinCtrl::DoGetPosition( 
 226     wxSpinButton::DoGetPosition( pnX
,pnY 
); 
 227 } // end of wxpinCtrl::DoGetPosition 
 229 void wxSpinCtrl::DoGetSize( 
 236     ::WinQueryWindowRect(GetHwnd(), &vSpinrect
); 
 239         *pnWidth 
= vSpinrect
.xRight 
- vSpinrect
.xLeft
; 
 241         *pnHeight 
= vSpinrect
.yTop 
- vSpinrect
.yBottom
; 
 242 } // end of wxSpinCtrl::DoGetSize 
 244 void wxSpinCtrl::DoMoveWindow( 
 251     wxWindowOS2
*                    pParent 
= (wxWindowOS2
*)GetParent(); 
 255         int                         nOS2Height 
= GetOS2ParentHeight(pParent
); 
 257         nY 
= nOS2Height 
- (nY 
+ nHeight
); 
 263         ::WinQueryWindowRect(HWND_DESKTOP
, &vRect
); 
 264         nY 
= vRect
.yTop 
- (nY 
+ nHeight
); 
 266     ::WinSetWindowPos( GetHwnd() 
 272                       ,SWP_SIZE 
| SWP_MOVE 
| SWP_ZORDER 
| SWP_SHOW
 
 274 } // end of wxSpinCtrl::DoMoveWindow 
 276 bool wxSpinCtrl::Enable( 
 280     if (!wxControl::Enable(bEnable
)) 
 284     ::WinEnableWindow(GetHwnd(), bEnable
); 
 286 } // end of wxSpinCtrl::Enable 
 288 wxSpinCtrl
* wxSpinCtrl::GetSpinForTextCtrl( 
 292     wxSpinCtrl
*                     pSpin 
= (wxSpinCtrl 
*)::WinQueryWindowULong( (HWND
)hWndBuddy
 
 295     int                             i 
= m_svAllSpins
.Index(pSpin
); 
 297     if (i 
== wxNOT_FOUND
) 
 301     wxASSERT_MSG( pSpin
->m_hWndBuddy 
== hWndBuddy
, 
 302                   wxT("wxSpinCtrl has incorrect buddy HWND!") ); 
 305 } // end of wxSpinCtrl::GetSpinForTextCtrl 
 307 int wxSpinCtrl::GetValue() const 
 312     ::WinSendMsg( GetHwnd() 
 315                  ,MPFROM2SHORT( (USHORT
)10 
 321 } // end of wxSpinCtrl::GetValue 
 323 void wxSpinCtrl::OnChar ( 
 327     switch (rEvent
.GetKeyCode()) 
 331                 wxCommandEvent              
vEvent( wxEVT_COMMAND_TEXT_ENTER
 
 334                 wxString                    sVal 
= wxGetWindowText(m_hWndBuddy
); 
 336                 InitCommandEvent(vEvent
); 
 337                 vEvent
.SetString(sVal
); 
 338                 vEvent
.SetInt(GetValue()); 
 339                 if (HandleWindowEvent(vEvent
)) 
 346             // Always produce navigation event - even if we process TAB 
 347             // ourselves the fact that we got here means that the user code 
 348             // decided to skip processing of this TAB - probably to let it 
 349             // do its default job. 
 352                 wxNavigationKeyEvent        vEventNav
; 
 354                 vEventNav
.SetDirection(!rEvent
.ShiftDown()); 
 355                 vEventNav
.SetWindowChange(rEvent
.ControlDown()); 
 356                 vEventNav
.SetEventObject(this); 
 357                 if (GetParent()->HandleWindowEvent(vEventNav
)) 
 364     // No, we didn't process it 
 367 } // end of wxSpinCtrl::OnChar 
 369 void wxSpinCtrl::OnSpinChange( 
 370   wxSpinEvent
&                      rEventSpin
 
 373     wxCommandEvent                  
vEvent( wxEVT_COMMAND_SPINCTRL_UPDATED
 
 377     vEvent
.SetEventObject(this); 
 378     vEvent
.SetInt(rEventSpin
.GetPosition()); 
 379     (void)HandleWindowEvent(vEvent
); 
 380     if (rEventSpin
.GetSkipped()) 
 384 } // end of wxSpinCtrl::OnSpinChange 
 386 void wxSpinCtrl::OnSetFocus ( 
 391     // When we get focus, give it to our buddy window as it needs it more than 
 394     ::WinSetFocus(HWND_DESKTOP
, (HWND
)m_hWndBuddy
); 
 396 } // end of wxSpinCtrl::OnSetFocus 
 398 bool wxSpinCtrl::ProcessTextCommand( WXWORD wCmd
, 
 399                                      WXWORD 
WXUNUSED(wId
) ) 
 405             wxCommandEvent 
vEvent( wxEVT_COMMAND_TEXT_UPDATED
, GetId() ); 
 406             vEvent
.SetEventObject(this); 
 408             wxString sVal 
= wxGetWindowText(m_hWndBuddy
); 
 410             vEvent
.SetString(sVal
); 
 411             vEvent
.SetInt(GetValue()); 
 412             return (HandleWindowEvent(vEvent
)); 
 418             wxFocusEvent 
vEvent( wCmd 
== EN_KILLFOCUS 
? wxEVT_KILL_FOCUS 
: wxEVT_SET_FOCUS
 
 422             vEvent
.SetEventObject(this); 
 423             return(HandleWindowEvent(vEvent
)); 
 433 } // end of wxSpinCtrl::ProcessTextCommand 
 435 void wxSpinCtrl::SetFocus() 
 437     ::WinSetFocus(HWND_DESKTOP
, GetHwnd()); 
 438 } // end of wxSpinCtrl::SetFocus 
 440 bool wxSpinCtrl::SetFont( 
 444     if (!wxWindowBase::SetFont(rFont
)) 
 454 } // end of wxSpinCtrl::SetFont 
 456 void wxSpinCtrl::SetValue( 
 457   const wxString
&                   rsText
 
 462     lVal 
= atol(rsText
.c_str()); 
 463     wxSpinButton::SetValue(lVal
); 
 464 } // end of wxSpinCtrl::SetValue 
 466 bool wxSpinCtrl::Show( 
 470     if (!wxControl::Show(bShow
)) 
 475 } // end of wxSpinCtrl::Show 
 477 void wxSpinCtrl::SetSelection ( 
 483     // If from and to are both -1, it means (in wxWidgets) that all text should 
 484     // be selected - translate into Windows convention 
 486     if ((lFrom 
== -1) && (lTo 
== -1)) 
 490     ::WinSendMsg(m_hWnd
, EM_SETSEL
, MPFROM2SHORT((USHORT
)lFrom
, (USHORT
)lTo
), (MPARAM
)0); 
 491 } // end of wxSpinCtrl::SetSelection 
 493 #endif //wxUSE_SPINCTRL