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_CHAR(wxSpinCtrl::OnChar
)
53 EVT_SPIN(wxID_ANY
, wxSpinCtrl::OnSpinChange
)
54 EVT_SET_FOCUS(wxSpinCtrl::OnSetFocus
)
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 // the margin between the up-down control and its buddy
61 static const int MARGIN_BETWEEN
= 5;
63 // ============================================================================
65 // ============================================================================
66 MRESULT EXPENTRY
wxSpinCtrlWndProc(
73 wxSpinCtrl
* pSpin
= (wxSpinCtrl
*)::WinQueryWindowULong( hWnd
78 // Forward some messages (the key ones only so far) to the spin ctrl
83 pSpin
->OS2WindowProc( uMessage
89 // The control may have been deleted at this point, so check.
91 if (!(::WinIsWindow(vHabmain
, hWnd
) && ((wxSpinCtrl
*)::WinQueryWindowULong( hWnd
99 return (fnWndProcSpinCtrl( hWnd
105 } // end of wxSpinCtrlWndProc
107 wxSpinCtrl::~wxSpinCtrl()
109 m_svAllSpins
.Remove(this);
111 // This removes spurious memory leak reporting
112 if (m_svAllSpins
.GetCount() == 0)
113 m_svAllSpins
.Clear();
114 } // end of wxSpinCtrl::~wxSpinCtrl
116 // ----------------------------------------------------------------------------
118 // ----------------------------------------------------------------------------
120 bool wxSpinCtrl::Create(
123 , const wxString
& rsValue
124 , const wxPoint
& rPos
125 , const wxSize
& rSize
130 , const wxString
& rsName
136 m_windowId
= NewControlId();
139 m_backgroundColour
= pParent
->GetBackgroundColour();
140 m_foregroundColour
= pParent
->GetForegroundColour();
143 m_windowStyle
= lStyle
;
147 lSstyle
= WS_VISIBLE
|
149 SPBS_MASTER
| // We use only single field spin buttons
150 SPBS_NUMERICONLY
; // We default to numeric data
152 if (m_windowStyle
& wxCLIP_SIBLINGS
)
153 lSstyle
|= WS_CLIPSIBLINGS
;
157 vCtrlData
.cbSize
= sizeof(SPBCDATA
);
158 vCtrlData
.ulTextLimit
= 10L;
159 vCtrlData
.lLowerLimit
= 0L;
160 vCtrlData
.lUpperLimit
= 100L;
161 vCtrlData
.idMasterSpb
= vId
;
162 vCtrlData
.pHWXCtlData
= NULL
;
164 m_hWnd
= (WXHWND
)::WinCreateWindow( GetWinHwnd(pParent
)
179 m_hWndBuddy
= m_hWnd
; // One in the same for OS/2
181 pParent
->AddChild((wxSpinButton
*)this);
182 wxFont
* pTextFont
= new wxFont( 10
188 ::WinQueryWindowPos(m_hWnd
, &vSwp
);
197 SetRange(nMin
, nMax
);
201 // For OS/2 we'll just set our handle into our long data
203 wxAssociateWinWithHandle( m_hWnd
206 ::WinSetWindowULong(GetHwnd(), QWL_USER
, (LONG
)this);
207 fnWndProcSpinCtrl
= (WXFARPROC
)::WinSubclassWindow(m_hWnd
, (PFNWP
)wxSpinCtrlWndProc
);
208 m_svAllSpins
.Add(this);
211 } // end of wxSpinCtrl::Create
213 wxSize
wxSpinCtrl::DoGetBestSize() const
215 wxSize vSizeBtn
= wxSpinButton::DoGetBestSize();
217 wxFont vFont
= (wxFont
)GetFont();
219 vSizeBtn
.x
+= DEFAULT_ITEM_WIDTH
+ MARGIN_BETWEEN
;
221 wxGetCharSize( GetHWND()
226 nHeight
= EDIT_HEIGHT_FROM_CHAR_HEIGHT(nHeight
);
228 if (vSizeBtn
.y
< nHeight
)
231 // Make the text tall enough
233 vSizeBtn
.y
= nHeight
;
236 } // end of wxSpinCtrl::DoGetBestSize
238 void wxSpinCtrl::DoGetPosition(
243 WXHWND hWnd
= GetHWND();
245 wxConstCast(this, wxSpinCtrl
)->m_hWnd
= m_hWndBuddy
;
246 wxSpinButton::DoGetPosition( pnX
249 wxConstCast(this, wxSpinCtrl
)->m_hWnd
= hWnd
;
250 } // end of wxpinCtrl::DoGetPosition
252 void wxSpinCtrl::DoGetSize(
259 ::WinQueryWindowRect(GetHwnd(), &vSpinrect
);
262 *pnWidth
= vSpinrect
.xRight
- vSpinrect
.xLeft
;
264 *pnHeight
= vSpinrect
.yTop
- vSpinrect
.yBottom
;
265 } // end of wxSpinCtrl::DoGetSize
267 void wxSpinCtrl::DoMoveWindow(
274 wxWindowOS2
* pParent
= (wxWindowOS2
*)GetParent();
278 int nOS2Height
= GetOS2ParentHeight(pParent
);
280 nY
= nOS2Height
- (nY
+ nHeight
);
286 ::WinQueryWindowRect(HWND_DESKTOP
, &vRect
);
287 nY
= vRect
.yTop
- (nY
+ nHeight
);
289 ::WinSetWindowPos( GetHwnd()
295 ,SWP_SIZE
| SWP_MOVE
| SWP_ZORDER
| SWP_SHOW
297 } // end of wxSpinCtrl::DoMoveWindow
299 bool wxSpinCtrl::Enable(
303 if (!wxControl::Enable(bEnable
))
307 ::WinEnableWindow(GetHwnd(), bEnable
);
309 } // end of wxSpinCtrl::Enable
311 wxSpinCtrl
* wxSpinCtrl::GetSpinForTextCtrl(
315 wxSpinCtrl
* pSpin
= (wxSpinCtrl
*)::WinQueryWindowULong( (HWND
)hWndBuddy
318 int i
= m_svAllSpins
.Index(pSpin
);
320 if (i
== wxNOT_FOUND
)
324 wxASSERT_MSG( pSpin
->m_hWndBuddy
== hWndBuddy
,
325 _T("wxSpinCtrl has incorrect buddy HWND!") );
328 } // end of wxSpinCtrl::GetSpinForTextCtrl
330 int wxSpinCtrl::GetValue() const
335 ::WinSendMsg( GetHwnd()
338 ,MPFROM2SHORT( (USHORT
)10
344 } // end of wxSpinCtrl::GetValue
346 void wxSpinCtrl::OnChar (
350 switch (rEvent
.GetKeyCode())
354 wxCommandEvent
vEvent( wxEVT_COMMAND_TEXT_ENTER
357 wxString sVal
= wxGetWindowText(m_hWndBuddy
);
359 InitCommandEvent(vEvent
);
360 vEvent
.SetString(sVal
);
361 vEvent
.SetInt(GetValue());
362 if (GetEventHandler()->ProcessEvent(vEvent
))
369 // Always produce navigation event - even if we process TAB
370 // ourselves the fact that we got here means that the user code
371 // decided to skip processing of this TAB - probably to let it
372 // do its default job.
375 wxNavigationKeyEvent vEventNav
;
377 vEventNav
.SetDirection(!rEvent
.ShiftDown());
378 vEventNav
.SetWindowChange(rEvent
.ControlDown());
379 vEventNav
.SetEventObject(this);
380 if (GetParent()->GetEventHandler()->ProcessEvent(vEventNav
))
387 // No, we didn't process it
390 } // end of wxSpinCtrl::OnChar
392 void wxSpinCtrl::OnSpinChange(
393 wxSpinEvent
& rEventSpin
396 wxCommandEvent
vEvent( wxEVT_COMMAND_SPINCTRL_UPDATED
400 vEvent
.SetEventObject(this);
401 vEvent
.SetInt(rEventSpin
.GetPosition());
402 (void)GetEventHandler()->ProcessEvent(vEvent
);
403 if (rEventSpin
.GetSkipped())
407 } // end of wxSpinCtrl::OnSpinChange
409 void wxSpinCtrl::OnSetFocus (
414 // When we get focus, give it to our buddy window as it needs it more than
417 ::WinSetFocus(HWND_DESKTOP
, (HWND
)m_hWndBuddy
);
419 } // end of wxSpinCtrl::OnSetFocus
421 bool wxSpinCtrl::ProcessTextCommand(
430 wxCommandEvent
vEvent( wxEVT_COMMAND_TEXT_UPDATED
433 vEvent
.SetEventObject(this);
435 wxString sVal
= wxGetWindowText(m_hWndBuddy
);
437 vEvent
.SetString(sVal
);
438 vEvent
.SetInt(GetValue());
439 return (GetEventHandler()->ProcessEvent(vEvent
));
445 wxFocusEvent
vEvent( wCmd
== EN_KILLFOCUS
? wxEVT_KILL_FOCUS
: wxEVT_SET_FOCUS
449 vEvent
.SetEventObject(this);
450 return(GetEventHandler()->ProcessEvent(vEvent
));
460 } // end of wxSpinCtrl::ProcessTextCommand
462 void wxSpinCtrl::SetFocus()
464 ::WinSetFocus(HWND_DESKTOP
, GetHwnd());
465 } // end of wxSpinCtrl::SetFocus
467 bool wxSpinCtrl::SetFont(
471 if (!wxWindowBase::SetFont(rFont
))
481 } // end of wxSpinCtrl::SetFont
483 void wxSpinCtrl::SetValue(
484 const wxString
& rsText
489 lVal
= atol((char*)rsText
.c_str());
490 wxSpinButton::SetValue(lVal
);
491 } // end of wxSpinCtrl::SetValue
493 bool wxSpinCtrl::Show(
497 if (!wxControl::Show(bShow
))
502 } // end of wxSpinCtrl::Show
504 void wxSpinCtrl::SetSelection (
510 // If from and to are both -1, it means (in wxWidgets) that all text should
511 // be selected - translate into Windows convention
513 if ((lFrom
== -1) && (lTo
== -1))
517 ::WinSendMsg(m_hWnd
, EM_SETSEL
, MPFROM2SHORT((USHORT
)lFrom
, (USHORT
)lTo
), (MPARAM
)0);
518 } // end of wxSpinCtrl::SetSelection
520 #endif //wxUSE_SPINCTRL