]> git.saurik.com Git - wxWidgets.git/blame - src/os2/spinctrl.cpp
Do not allow events to fire after socket is closed (fixes crash on GTK with GDK_Input...
[wxWidgets.git] / src / os2 / spinctrl.cpp
CommitLineData
409c9842
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: msw/spinctrl.cpp
3// Purpose: wxSpinCtrl class implementation for Win32
4// Author: David Webster
5// Modified by:
6// Created: 10/15/99
7// RCS-ID: $Id$
8// Copyright: (c) David Webster
65571936 9// Licence: wxWindows licence
409c9842
DW
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
409c9842
DW
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// for compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23
24#ifndef WX_PRECOMP
25 #include "wx/wx.h"
26#endif
27
312ebad4 28#if wxUSE_SPINCTRL
7e99520b 29
409c9842
DW
30#include "wx/spinctrl.h"
31#include "wx/os2/private.h"
32
33// ----------------------------------------------------------------------------
34// macros
35// ----------------------------------------------------------------------------
36
3c299c3a
DW
37extern void wxAssociateWinWithHandle( HWND hWnd
38 ,wxWindowOS2* pWin
39 );
40static WXFARPROC fnWndProcSpinCtrl = (WXFARPROC)NULL;
32334453 41wxArraySpins wxSpinCtrl::m_svAllSpins;
3c299c3a 42
3d62dcb6 43IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl)
409c9842 44
3d62dcb6 45BEGIN_EVENT_TABLE(wxSpinCtrl, wxSpinButton)
6e348b12 46 EVT_CHAR(wxSpinCtrl::OnChar)
312ebad4 47 EVT_SPIN(wxID_ANY, wxSpinCtrl::OnSpinChange)
6e348b12 48 EVT_SET_FOCUS(wxSpinCtrl::OnSetFocus)
3d62dcb6 49END_EVENT_TABLE()
409c9842
DW
50// ----------------------------------------------------------------------------
51// constants
52// ----------------------------------------------------------------------------
53
54// the margin between the up-down control and its buddy
55static const int MARGIN_BETWEEN = 5;
56
57// ============================================================================
58// implementation
59// ============================================================================
3c299c3a
DW
60MRESULT EXPENTRY wxSpinCtrlWndProc(
61 HWND hWnd
62, UINT uMessage
63, MPARAM wParam
64, MPARAM lParam
65)
409c9842 66{
3c299c3a
DW
67 wxSpinCtrl* pSpin = (wxSpinCtrl *)::WinQueryWindowULong( hWnd
68 ,QWL_USER
69 );
9923c37d 70
3c299c3a
DW
71 //
72 // Forward some messages (the key ones only so far) to the spin ctrl
73 //
74 switch (uMessage )
3d62dcb6 75 {
3c299c3a
DW
76 case WM_CHAR:
77 pSpin->OS2WindowProc( uMessage
78 ,wParam
79 ,lParam
80 );
81
82 //
83 // The control may have been deleted at this point, so check.
84 //
85 if (!(::WinIsWindow(vHabmain, hWnd) && ((wxSpinCtrl *)::WinQueryWindowULong( hWnd
86 ,QWL_USER
87 )
88 ) == pSpin))
89 return 0;
90 break;
3d62dcb6 91
409c9842 92 }
3c299c3a
DW
93 return (fnWndProcSpinCtrl( hWnd
94 ,(ULONG)uMessage
95 ,(MPARAM)wParam
96 ,(MPARAM)lParam
97 )
98 );
99} // end of wxSpinCtrlWndProc
100
101wxSpinCtrl::~wxSpinCtrl()
102{
103 m_svAllSpins.Remove(this);
409c9842 104
3c299c3a
DW
105 // This removes spurious memory leak reporting
106 if (m_svAllSpins.GetCount() == 0)
107 m_svAllSpins.Clear();
108} // end of wxSpinCtrl::~wxSpinCtrl
409c9842 109
3c299c3a
DW
110// ----------------------------------------------------------------------------
111// construction
112// ----------------------------------------------------------------------------
113
6670f564
WS
114bool wxSpinCtrl::Create( wxWindow* pParent,
115 wxWindowID vId,
116 const wxString& WXUNUSED(rsValue),
117 const wxPoint& rPos,
118 const wxSize& rSize,
119 long lStyle,
120 int nMin,
121 int nMax,
122 int nInitial,
123 const wxString& rsName )
3c299c3a 124{
d8a3f66c
DW
125 SWP vSwp;
126
312ebad4 127 if (vId == wxID_ANY)
3c299c3a
DW
128 m_windowId = NewControlId();
129 else
130 m_windowId = vId;
131 m_backgroundColour = pParent->GetBackgroundColour();
132 m_foregroundColour = pParent->GetForegroundColour();
133 SetName(rsName);
134 SetParent(pParent);
135 m_windowStyle = lStyle;
136
137 int lSstyle = 0L;
138
139 lSstyle = WS_VISIBLE |
140 WS_TABSTOP |
141 SPBS_MASTER | // We use only single field spin buttons
142 SPBS_NUMERICONLY; // We default to numeric data
143
144 if (m_windowStyle & wxCLIP_SIBLINGS )
145 lSstyle |= WS_CLIPSIBLINGS;
146
147 SPBCDATA vCtrlData;
148
149 vCtrlData.cbSize = sizeof(SPBCDATA);
150 vCtrlData.ulTextLimit = 10L;
151 vCtrlData.lLowerLimit = 0L;
152 vCtrlData.lUpperLimit = 100L;
153 vCtrlData.idMasterSpb = vId;
154 vCtrlData.pHWXCtlData = NULL;
155
156 m_hWnd = (WXHWND)::WinCreateWindow( GetWinHwnd(pParent)
157 ,WC_SPINBUTTON
158 ,(PSZ)NULL
159 ,lSstyle
160 ,0L, 0L, 0L, 0L
161 ,GetWinHwnd(pParent)
162 ,HWND_TOP
163 ,(HMENU)vId
164 ,(PVOID)&vCtrlData
165 ,NULL
166 );
167 if (m_hWnd == 0)
409c9842 168 {
312ebad4 169 return false;
409c9842 170 }
3c299c3a
DW
171 m_hWndBuddy = m_hWnd; // One in the same for OS/2
172 if(pParent)
173 pParent->AddChild((wxSpinButton *)this);
b3260bce
DW
174 wxFont* pTextFont = new wxFont( 10
175 ,wxMODERN
176 ,wxNORMAL
177 ,wxNORMAL
178 );
179 SetFont(*pTextFont);
d8a3f66c
DW
180 ::WinQueryWindowPos(m_hWnd, &vSwp);
181 SetXComp(vSwp.x);
182 SetYComp(vSwp.y);
3c299c3a
DW
183 SetSize( rPos.x
184 ,rPos.y
185 ,rSize.x
186 ,rSize.y
187 );
188
189 SetRange(nMin, nMax);
190 SetValue(nInitial);
191
192 //
193 // For OS/2 we'll just set our handle into our long data
194 //
195 wxAssociateWinWithHandle( m_hWnd
196 ,(wxWindowOS2*)this
197 );
198 ::WinSetWindowULong(GetHwnd(), QWL_USER, (LONG)this);
199 fnWndProcSpinCtrl = (WXFARPROC)::WinSubclassWindow(m_hWnd, (PFNWP)wxSpinCtrlWndProc);
200 m_svAllSpins.Add(this);
b3260bce 201 delete pTextFont;
312ebad4 202 return true;
3c299c3a 203} // end of wxSpinCtrl::Create
409c9842 204
3c299c3a
DW
205wxSize wxSpinCtrl::DoGetBestSize() const
206{
207 wxSize vSizeBtn = wxSpinButton::DoGetBestSize();
208 int nHeight;
0d598bae 209 wxFont vFont = (wxFont)GetFont();
409c9842 210
3c299c3a 211 vSizeBtn.x += DEFAULT_ITEM_WIDTH + MARGIN_BETWEEN;
409c9842 212
3c299c3a
DW
213 wxGetCharSize( GetHWND()
214 ,NULL
215 ,&nHeight
0d598bae 216 ,&vFont
3c299c3a
DW
217 );
218 nHeight = EDIT_HEIGHT_FROM_CHAR_HEIGHT(nHeight);
3d62dcb6 219
3c299c3a 220 if (vSizeBtn.y < nHeight)
3d62dcb6 221 {
3c299c3a
DW
222 //
223 // Make the text tall enough
224 //
225 vSizeBtn.y = nHeight;
3d62dcb6 226 }
3c299c3a
DW
227 return vSizeBtn;
228} // end of wxSpinCtrl::DoGetBestSize
3d62dcb6 229
3c299c3a
DW
230void wxSpinCtrl::DoGetPosition(
231 int* pnX
232, int* pnY
233) const
234{
235 WXHWND hWnd = GetHWND();
236
237 wxConstCast(this, wxSpinCtrl)->m_hWnd = m_hWndBuddy;
238 wxSpinButton::DoGetPosition( pnX
239 ,pnY
240 );
241 wxConstCast(this, wxSpinCtrl)->m_hWnd = hWnd;
242} // end of wxpinCtrl::DoGetPosition
243
244void wxSpinCtrl::DoGetSize(
245 int* pnWidth
246, int* pnHeight
247) const
248{
249 RECTL vSpinrect;
250
251 ::WinQueryWindowRect(GetHwnd(), &vSpinrect);
252
253 if (pnWidth)
254 *pnWidth = vSpinrect.xRight - vSpinrect.xLeft;
255 if (pnHeight)
256 *pnHeight = vSpinrect.yTop - vSpinrect.yBottom;
257} // end of wxSpinCtrl::DoGetSize
258
259void wxSpinCtrl::DoMoveWindow(
260 int nX
261, int nY
262, int nWidth
263, int nHeight
264)
265{
266 wxWindowOS2* pParent = (wxWindowOS2*)GetParent();
3d62dcb6 267
3c299c3a 268 if (pParent)
3d62dcb6 269 {
d8a3f66c
DW
270 int nOS2Height = GetOS2ParentHeight(pParent);
271
272 nY = nOS2Height - (nY + nHeight);
3d62dcb6 273 }
3c299c3a
DW
274 else
275 {
276 RECTL vRect;
3d62dcb6 277
3c299c3a
DW
278 ::WinQueryWindowRect(HWND_DESKTOP, &vRect);
279 nY = vRect.yTop - (nY + nHeight);
280 }
281 ::WinSetWindowPos( GetHwnd()
282 ,HWND_TOP
283 ,nX
284 ,nY
285 ,nWidth
286 ,nHeight
287 ,SWP_SIZE | SWP_MOVE | SWP_ZORDER | SWP_SHOW
288 );
289} // end of wxSpinCtrl::DoMoveWindow
290
291bool wxSpinCtrl::Enable(
292 bool bEnable
293)
3d62dcb6 294{
3c299c3a 295 if (!wxControl::Enable(bEnable))
3d62dcb6 296 {
312ebad4 297 return false;
3d62dcb6 298 }
3c299c3a 299 ::WinEnableWindow(GetHwnd(), bEnable);
312ebad4 300 return true;
3c299c3a 301} // end of wxSpinCtrl::Enable
3d62dcb6 302
3c299c3a
DW
303wxSpinCtrl* wxSpinCtrl::GetSpinForTextCtrl(
304 WXHWND hWndBuddy
305)
3d62dcb6 306{
3c299c3a
DW
307 wxSpinCtrl* pSpin = (wxSpinCtrl *)::WinQueryWindowULong( (HWND)hWndBuddy
308 ,QWL_USER
309 );
310 int i = m_svAllSpins.Index(pSpin);
3d62dcb6 311
3c299c3a
DW
312 if (i == wxNOT_FOUND)
313 return NULL;
3d62dcb6 314
3c299c3a
DW
315 // sanity check
316 wxASSERT_MSG( pSpin->m_hWndBuddy == hWndBuddy,
317 _T("wxSpinCtrl has incorrect buddy HWND!") );
3d62dcb6 318
3c299c3a
DW
319 return pSpin;
320} // end of wxSpinCtrl::GetSpinForTextCtrl
3d62dcb6 321
3c299c3a 322int wxSpinCtrl::GetValue() const
3d62dcb6 323{
3c299c3a
DW
324 long lVal = 0L;
325 char zVal[10];
326
327 ::WinSendMsg( GetHwnd()
328 ,SPBM_QUERYVALUE
329 ,MPFROMP(zVal)
330 ,MPFROM2SHORT( (USHORT)10
331 ,SPBQ_UPDATEIFVALID
332 )
333 );
70a2c656
DW
334 lVal = atol(zVal);
335 return (int)lVal;
3c299c3a
DW
336} // end of wxSpinCtrl::GetValue
337
338void wxSpinCtrl::OnChar (
339 wxKeyEvent& rEvent
340)
341{
9923c37d 342 switch (rEvent.GetKeyCode())
3d62dcb6 343 {
3c299c3a
DW
344 case WXK_RETURN:
345 {
346 wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_ENTER
347 ,m_windowId
348 );
349 wxString sVal = wxGetWindowText(m_hWndBuddy);
350
351 InitCommandEvent(vEvent);
0fba44b4 352 vEvent.SetString(sVal);
3c299c3a
DW
353 vEvent.SetInt(GetValue());
354 if (GetEventHandler()->ProcessEvent(vEvent))
355 return;
356 break;
357 }
358
359 case WXK_TAB:
360 //
361 // Always produce navigation event - even if we process TAB
362 // ourselves the fact that we got here means that the user code
363 // decided to skip processing of this TAB - probably to let it
364 // do its default job.
365 //
366 {
367 wxNavigationKeyEvent vEventNav;
368
369 vEventNav.SetDirection(!rEvent.ShiftDown());
370 vEventNav.SetWindowChange(rEvent.ControlDown());
371 vEventNav.SetEventObject(this);
372 if (GetParent()->GetEventHandler()->ProcessEvent(vEventNav))
373 return;
374 }
375 break;
3d62dcb6
DW
376 }
377
3c299c3a
DW
378 //
379 // No, we didn't process it
380 //
381 rEvent.Skip();
382} // end of wxSpinCtrl::OnChar
3d62dcb6 383
3c299c3a
DW
384void wxSpinCtrl::OnSpinChange(
385 wxSpinEvent& rEventSpin
386)
3d62dcb6 387{
3c299c3a
DW
388 wxCommandEvent vEvent( wxEVT_COMMAND_SPINCTRL_UPDATED
389 ,GetId()
390 );
391
392 vEvent.SetEventObject(this);
393 vEvent.SetInt(rEventSpin.GetPosition());
394 (void)GetEventHandler()->ProcessEvent(vEvent);
395 if (rEventSpin.GetSkipped())
3d62dcb6 396 {
3c299c3a 397 vEvent.Skip();
3d62dcb6 398 }
3c299c3a 399} // end of wxSpinCtrl::OnSpinChange
3d62dcb6 400
6e348b12
DW
401void wxSpinCtrl::OnSetFocus (
402 wxFocusEvent& rEvent
403)
404{
405 //
406 // When we get focus, give it to our buddy window as it needs it more than
407 // we do
408 //
409 ::WinSetFocus(HWND_DESKTOP, (HWND)m_hWndBuddy);
410 rEvent.Skip();
411} // end of wxSpinCtrl::OnSetFocus
412
6670f564
WS
413bool wxSpinCtrl::ProcessTextCommand( WXWORD wCmd,
414 WXWORD WXUNUSED(wId) )
3d62dcb6 415{
3c299c3a 416 switch (wCmd)
3d62dcb6 417 {
3c299c3a
DW
418 case SPBN_CHANGE:
419 {
6670f564 420 wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED, GetId() );
3c299c3a
DW
421 vEvent.SetEventObject(this);
422
6670f564 423 wxString sVal = wxGetWindowText(m_hWndBuddy);
3c299c3a 424
0fba44b4 425 vEvent.SetString(sVal);
3c299c3a
DW
426 vEvent.SetInt(GetValue());
427 return (GetEventHandler()->ProcessEvent(vEvent));
428 }
429
430 case SPBN_SETFOCUS:
431 case SPBN_KILLFOCUS:
432 {
6670f564
WS
433 wxFocusEvent vEvent( wCmd == EN_KILLFOCUS ? wxEVT_KILL_FOCUS : wxEVT_SET_FOCUS
434 ,m_windowId
435 );
3c299c3a
DW
436
437 vEvent.SetEventObject(this);
438 return(GetEventHandler()->ProcessEvent(vEvent));
439 }
440 default:
441 break;
3d62dcb6
DW
442 }
443
3c299c3a
DW
444 //
445 // Not processed
446 //
312ebad4 447 return false;
3c299c3a 448} // end of wxSpinCtrl::ProcessTextCommand
3d62dcb6 449
3c299c3a 450void wxSpinCtrl::SetFocus()
3d62dcb6 451{
3c299c3a
DW
452 ::WinSetFocus(HWND_DESKTOP, GetHwnd());
453} // end of wxSpinCtrl::SetFocus
3d62dcb6 454
3c299c3a
DW
455bool wxSpinCtrl::SetFont(
456 const wxFont& rFont
457)
458{
459 if (!wxWindowBase::SetFont(rFont))
3d62dcb6 460 {
3c299c3a 461 // nothing to do
312ebad4 462 return false;
3d62dcb6 463 }
3d62dcb6 464
3c299c3a
DW
465 wxOS2SetFont( m_hWnd
466 ,rFont
467 );
312ebad4 468 return true;
3c299c3a 469} // end of wxSpinCtrl::SetFont
409c9842 470
3c299c3a
DW
471void wxSpinCtrl::SetValue(
472 const wxString& rsText
473)
3d62dcb6 474{
3c299c3a 475 long lVal;
3d62dcb6 476
0fba44b4 477 lVal = atol((char*)rsText.c_str());
3c299c3a
DW
478 wxSpinButton::SetValue(lVal);
479} // end of wxSpinCtrl::SetValue
3d62dcb6 480
3c299c3a
DW
481bool wxSpinCtrl::Show(
482 bool bShow
483)
409c9842 484{
3c299c3a 485 if (!wxControl::Show(bShow))
409c9842 486 {
312ebad4 487 return false;
409c9842 488 }
312ebad4 489 return true;
3c299c3a 490} // end of wxSpinCtrl::Show
7e99520b 491
cfcebdb1
DW
492void wxSpinCtrl::SetSelection (
493 long lFrom
494, long lTo
495)
496{
497 //
77ffb593 498 // If from and to are both -1, it means (in wxWidgets) that all text should
cfcebdb1
DW
499 // be selected - translate into Windows convention
500 //
501 if ((lFrom == -1) && (lTo == -1))
502 {
503 lFrom = 0;
504 }
505 ::WinSendMsg(m_hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), (MPARAM)0);
506} // end of wxSpinCtrl::SetSelection
507
312ebad4 508#endif //wxUSE_SPINCTRL