1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        msw/spinctrl.cpp 
   3 // Purpose:     wxSpinCtrl class implementation for Win32 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  18     #pragma implementation "spinctrlbase.h" 
  19     #pragma implementation "spinctrl.h" 
  22 // ---------------------------------------------------------------------------- 
  24 // ---------------------------------------------------------------------------- 
  26 // for compilers that support precompilation, includes "wx.h". 
  27 #include "wx/wxprec.h" 
  36 #include "wx/spinctrl.h" 
  37 #include "wx/os2/private.h" 
  39 // ---------------------------------------------------------------------------- 
  41 // ---------------------------------------------------------------------------- 
  43 extern void  wxAssociateWinWithHandle( HWND         hWnd
 
  46 static WXFARPROC fnWndProcSpinCtrl 
= (WXFARPROC
)NULL
; 
  47 wxArraySpins                        
wxSpinCtrl::m_svAllSpins
; 
  49 IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl
, wxControl
) 
  51 BEGIN_EVENT_TABLE(wxSpinCtrl
, wxSpinButton
) 
  52     EVT_SPIN(-1, wxSpinCtrl::OnSpinChange
) 
  54 // ---------------------------------------------------------------------------- 
  56 // ---------------------------------------------------------------------------- 
  58 // the margin between the up-down control and its buddy 
  59 static const int MARGIN_BETWEEN 
= 5; 
  61 // ============================================================================ 
  63 // ============================================================================ 
  64 MRESULT EXPENTRY 
wxSpinCtrlWndProc( 
  71     wxSpinCtrl
*                    pSpin 
= (wxSpinCtrl 
*)::WinQueryWindowULong( hWnd
 
  74     bool                            bProccesed 
= FALSE
; 
  75     MRESULT                         rc 
= (MRESULT
)0; 
  77     // Forward some messages (the key ones only so far) to the spin ctrl 
  82             pSpin
->OS2WindowProc( uMessage
 
  88             // The control may have been deleted at this point, so check. 
  90             if (!(::WinIsWindow(vHabmain
, hWnd
) && ((wxSpinCtrl 
*)::WinQueryWindowULong( hWnd
 
  98     return (fnWndProcSpinCtrl( hWnd
 
 104 } // end of wxSpinCtrlWndProc 
 106 wxSpinCtrl::~wxSpinCtrl() 
 108     m_svAllSpins
.Remove(this); 
 110     // This removes spurious memory leak reporting 
 111     if (m_svAllSpins
.GetCount() == 0) 
 112         m_svAllSpins
.Clear(); 
 113 } // end of wxSpinCtrl::~wxSpinCtrl 
 115 // ---------------------------------------------------------------------------- 
 117 // ---------------------------------------------------------------------------- 
 119 bool wxSpinCtrl::Create( 
 122 , const wxString
&                   rsValue
 
 123 , const wxPoint
&                    rPos
 
 124 , const wxSize
&                     rSize
 
 129 , const wxString
&                   rsName
 
 135         m_windowId 
= NewControlId(); 
 138     m_backgroundColour 
= pParent
->GetBackgroundColour(); 
 139     m_foregroundColour 
= pParent
->GetForegroundColour(); 
 142     m_windowStyle      
= lStyle
; 
 146     lSstyle 
= WS_VISIBLE      
| 
 148               SPBS_MASTER     
| // We use only single field spin buttons 
 149               SPBS_NUMERICONLY
; // We default to numeric data 
 151     if (m_windowStyle 
& wxCLIP_SIBLINGS 
) 
 152         lSstyle 
|= WS_CLIPSIBLINGS
; 
 156     vCtrlData
.cbSize 
= sizeof(SPBCDATA
); 
 157     vCtrlData
.ulTextLimit 
= 10L; 
 158     vCtrlData
.lLowerLimit 
= 0L; 
 159     vCtrlData
.lUpperLimit 
= 100L; 
 160     vCtrlData
.idMasterSpb 
= vId
; 
 161     vCtrlData
.pHWXCtlData 
= NULL
; 
 163     m_hWnd 
= (WXHWND
)::WinCreateWindow( GetWinHwnd(pParent
) 
 178     m_hWndBuddy 
= m_hWnd
; // One in the same for OS/2 
 180         pParent
->AddChild((wxSpinButton 
*)this); 
 181     wxFont
*                          pTextFont 
= new wxFont( 10 
 187     ::WinQueryWindowPos(m_hWnd
, &vSwp
); 
 196     SetRange(nMin
, nMax
); 
 200     // For OS/2 we'll just set our handle into our long data 
 202     wxAssociateWinWithHandle( m_hWnd
 
 205     ::WinSetWindowULong(GetHwnd(), QWL_USER
, (LONG
)this); 
 206     fnWndProcSpinCtrl 
= (WXFARPROC
)::WinSubclassWindow(m_hWnd
, (PFNWP
)wxSpinCtrlWndProc
); 
 207     m_svAllSpins
.Add(this); 
 210 } // end of wxSpinCtrl::Create 
 212 wxSize 
wxSpinCtrl::DoGetBestSize() const 
 214     wxSize                          vSizeBtn 
= wxSpinButton::DoGetBestSize(); 
 217     vSizeBtn
.x 
+= DEFAULT_ITEM_WIDTH 
+ MARGIN_BETWEEN
; 
 219     wxGetCharSize( GetHWND() 
 224     nHeight 
= EDIT_HEIGHT_FROM_CHAR_HEIGHT(nHeight
); 
 226     if (vSizeBtn
.y 
< nHeight
) 
 229         // Make the text tall enough 
 231         vSizeBtn
.y 
= nHeight
; 
 234 } // end of wxSpinCtrl::DoGetBestSize 
 236 void wxSpinCtrl::DoGetPosition( 
 241     WXHWND                          hWnd 
= GetHWND(); 
 243     wxConstCast(this, wxSpinCtrl
)->m_hWnd 
= m_hWndBuddy
; 
 244     wxSpinButton::DoGetPosition( pnX
 
 247     wxConstCast(this, wxSpinCtrl
)->m_hWnd 
= hWnd
; 
 248 } // end of wxpinCtrl::DoGetPosition 
 250 void wxSpinCtrl::DoGetSize( 
 257     ::WinQueryWindowRect(GetHwnd(), &vSpinrect
); 
 260         *pnWidth 
= vSpinrect
.xRight 
- vSpinrect
.xLeft
; 
 262         *pnHeight 
= vSpinrect
.yTop 
- vSpinrect
.yBottom
; 
 263 } // end of wxSpinCtrl::DoGetSize 
 265 void wxSpinCtrl::DoMoveWindow( 
 272     wxWindowOS2
*                    pParent 
= (wxWindowOS2
*)GetParent(); 
 276         int                         nOS2Height 
= GetOS2ParentHeight(pParent
); 
 278         nY 
= nOS2Height 
- (nY 
+ nHeight
); 
 284         ::WinQueryWindowRect(HWND_DESKTOP
, &vRect
); 
 285         nY 
= vRect
.yTop 
- (nY 
+ nHeight
); 
 287     ::WinSetWindowPos( GetHwnd() 
 293                       ,SWP_SIZE 
| SWP_MOVE 
| SWP_ZORDER 
| SWP_SHOW
 
 295 } // end of wxSpinCtrl::DoMoveWindow 
 297 bool wxSpinCtrl::Enable( 
 301     if (!wxControl::Enable(bEnable
)) 
 305     ::WinEnableWindow(GetHwnd(), bEnable
); 
 307 } // end of wxSpinCtrl::Enable 
 309 wxSpinCtrl
* wxSpinCtrl::GetSpinForTextCtrl( 
 313     wxSpinCtrl
*                     pSpin 
= (wxSpinCtrl 
*)::WinQueryWindowULong( (HWND
)hWndBuddy
 
 316     int                             i 
= m_svAllSpins
.Index(pSpin
); 
 318     if (i 
== wxNOT_FOUND
) 
 322     wxASSERT_MSG( pSpin
->m_hWndBuddy 
== hWndBuddy
, 
 323                   _T("wxSpinCtrl has incorrect buddy HWND!") ); 
 326 } // end of wxSpinCtrl::GetSpinForTextCtrl 
 328 int wxSpinCtrl::GetValue() const 
 333     ::WinSendMsg( GetHwnd() 
 336                  ,MPFROM2SHORT( (USHORT
)10 
 342 } // end of wxSpinCtrl::GetValue 
 344 void wxSpinCtrl::OnChar ( 
 348     switch (rEvent
.KeyCode()) 
 352                 wxCommandEvent              
vEvent( wxEVT_COMMAND_TEXT_ENTER
 
 355                 wxString                    sVal 
= wxGetWindowText(m_hWndBuddy
); 
 357                 InitCommandEvent(vEvent
); 
 358                 vEvent
.SetString((char*)sVal
.c_str()); 
 359                 vEvent
.SetInt(GetValue()); 
 360                 if (GetEventHandler()->ProcessEvent(vEvent
)) 
 367             // Always produce navigation event - even if we process TAB 
 368             // ourselves the fact that we got here means that the user code 
 369             // decided to skip processing of this TAB - probably to let it 
 370             // do its default job. 
 373                 wxNavigationKeyEvent        vEventNav
; 
 375                 vEventNav
.SetDirection(!rEvent
.ShiftDown()); 
 376                 vEventNav
.SetWindowChange(rEvent
.ControlDown()); 
 377                 vEventNav
.SetEventObject(this); 
 378                 if (GetParent()->GetEventHandler()->ProcessEvent(vEventNav
)) 
 385     // No, we didn't process it 
 388 } // end of wxSpinCtrl::OnChar 
 390 void wxSpinCtrl::OnSpinChange( 
 391   wxSpinEvent
&                      rEventSpin
 
 394     wxCommandEvent                  
vEvent( wxEVT_COMMAND_SPINCTRL_UPDATED
 
 398     vEvent
.SetEventObject(this); 
 399     vEvent
.SetInt(rEventSpin
.GetPosition()); 
 400     (void)GetEventHandler()->ProcessEvent(vEvent
); 
 401     if (rEventSpin
.GetSkipped()) 
 405 } // end of wxSpinCtrl::OnSpinChange 
 407 bool wxSpinCtrl::ProcessTextCommand( 
 416             wxCommandEvent          
vEvent( wxEVT_COMMAND_TEXT_UPDATED
 
 419             vEvent
.SetEventObject(this); 
 421             wxString                sVal 
= wxGetWindowText(m_hWndBuddy
); 
 423             vEvent
.SetString((char*)sVal
.c_str()); 
 424             vEvent
.SetInt(GetValue()); 
 425             return (GetEventHandler()->ProcessEvent(vEvent
)); 
 431             wxFocusEvent                
vEvent( wCmd 
== EN_KILLFOCUS 
? wxEVT_KILL_FOCUS 
: wxEVT_SET_FOCUS
 
 435             vEvent
.SetEventObject(this); 
 436             return(GetEventHandler()->ProcessEvent(vEvent
)); 
 446 } // end of wxSpinCtrl::ProcessTextCommand 
 448 void wxSpinCtrl::SetFocus() 
 450     ::WinSetFocus(HWND_DESKTOP
, GetHwnd()); 
 451 } // end of wxSpinCtrl::SetFocus 
 453 bool wxSpinCtrl::SetFont( 
 457     if (!wxWindowBase::SetFont(rFont
)) 
 463     WXHANDLE                        hFont 
= GetFont().GetResourceHandle(); 
 468 } // end of wxSpinCtrl::SetFont 
 470 void wxSpinCtrl::SetValue( 
 471   const wxString
&                   rsText
 
 476     lVal 
= atol(rsText
.c_str()); 
 477     wxSpinButton::SetValue(lVal
); 
 478 } // end of wxSpinCtrl::SetValue 
 480 bool wxSpinCtrl::Show( 
 484     if (!wxControl::Show(bShow
)) 
 489 } // end of wxSpinCtrl::Show 
 491 void wxSpinCtrl::SetSelection ( 
 497     // If from and to are both -1, it means (in wxWindows) that all text should 
 498     // be selected - translate into Windows convention 
 500     if ((lFrom 
== -1) && (lTo 
== -1)) 
 504     ::WinSendMsg(m_hWnd
, EM_SETSEL
, MPFROM2SHORT((USHORT
)lFrom
, (USHORT
)lTo
), (MPARAM
)0); 
 505 } // end of wxSpinCtrl::SetSelection 
 507 #endif //wxUSE_SPINBTN