]> git.saurik.com Git - wxWidgets.git/blame - src/os2/spinctrl.cpp
added stipple opaque mask detection
[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
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16
1c85008f
SN
17#ifdef __GNUG__
18 #pragma implementation "spinctrlbase.h"
19 #pragma implementation "spinctrl.h"
20#endif
21
409c9842
DW
22// ----------------------------------------------------------------------------
23// headers
24// ----------------------------------------------------------------------------
25
26// for compilers that support precompilation, includes "wx.h".
27#include "wx/wxprec.h"
28
29
30#ifndef WX_PRECOMP
31 #include "wx/wx.h"
32#endif
33
7e99520b
DW
34#if wxUSE_SPINBTN
35
409c9842
DW
36#include "wx/spinctrl.h"
37#include "wx/os2/private.h"
38
39// ----------------------------------------------------------------------------
40// macros
41// ----------------------------------------------------------------------------
42
3c299c3a
DW
43extern void wxAssociateWinWithHandle( HWND hWnd
44 ,wxWindowOS2* pWin
45 );
46static WXFARPROC fnWndProcSpinCtrl = (WXFARPROC)NULL;
32334453 47wxArraySpins wxSpinCtrl::m_svAllSpins;
3c299c3a 48
3d62dcb6 49IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl)
409c9842 50
3d62dcb6
DW
51BEGIN_EVENT_TABLE(wxSpinCtrl, wxSpinButton)
52 EVT_SPIN(-1, wxSpinCtrl::OnSpinChange)
53END_EVENT_TABLE()
409c9842
DW
54// ----------------------------------------------------------------------------
55// constants
56// ----------------------------------------------------------------------------
57
58// the margin between the up-down control and its buddy
59static const int MARGIN_BETWEEN = 5;
60
61// ============================================================================
62// implementation
63// ============================================================================
3c299c3a
DW
64MRESULT EXPENTRY wxSpinCtrlWndProc(
65 HWND hWnd
66, UINT uMessage
67, MPARAM wParam
68, MPARAM lParam
69)
409c9842 70{
3c299c3a
DW
71 wxSpinCtrl* pSpin = (wxSpinCtrl *)::WinQueryWindowULong( hWnd
72 ,QWL_USER
73 );
74 bool bProccesed = FALSE;
75 MRESULT rc = (MRESULT)0;
76 //
77 // Forward some messages (the key ones only so far) to the spin ctrl
78 //
79 switch (uMessage )
3d62dcb6 80 {
3c299c3a
DW
81 case WM_CHAR:
82 pSpin->OS2WindowProc( uMessage
83 ,wParam
84 ,lParam
85 );
86
87 //
88 // The control may have been deleted at this point, so check.
89 //
90 if (!(::WinIsWindow(vHabmain, hWnd) && ((wxSpinCtrl *)::WinQueryWindowULong( hWnd
91 ,QWL_USER
92 )
93 ) == pSpin))
94 return 0;
95 break;
3d62dcb6 96
409c9842 97 }
3c299c3a
DW
98 return (fnWndProcSpinCtrl( hWnd
99 ,(ULONG)uMessage
100 ,(MPARAM)wParam
101 ,(MPARAM)lParam
102 )
103 );
104} // end of wxSpinCtrlWndProc
105
106wxSpinCtrl::~wxSpinCtrl()
107{
108 m_svAllSpins.Remove(this);
409c9842 109
3c299c3a
DW
110 // This removes spurious memory leak reporting
111 if (m_svAllSpins.GetCount() == 0)
112 m_svAllSpins.Clear();
113} // end of wxSpinCtrl::~wxSpinCtrl
409c9842 114
3c299c3a
DW
115// ----------------------------------------------------------------------------
116// construction
117// ----------------------------------------------------------------------------
118
119bool wxSpinCtrl::Create(
120 wxWindow* pParent
121, wxWindowID vId
122, const wxString& rsValue
123, const wxPoint& rPos
124, const wxSize& rSize
125, long lStyle
126, int nMin
127, int nMax
128, int nInitial
129, const wxString& rsName
130)
131{
d8a3f66c
DW
132 SWP vSwp;
133
3c299c3a
DW
134 if (vId == -1)
135 m_windowId = NewControlId();
136 else
137 m_windowId = vId;
138 m_backgroundColour = pParent->GetBackgroundColour();
139 m_foregroundColour = pParent->GetForegroundColour();
140 SetName(rsName);
141 SetParent(pParent);
142 m_windowStyle = lStyle;
143
144 int lSstyle = 0L;
145
146 lSstyle = WS_VISIBLE |
147 WS_TABSTOP |
148 SPBS_MASTER | // We use only single field spin buttons
149 SPBS_NUMERICONLY; // We default to numeric data
150
151 if (m_windowStyle & wxCLIP_SIBLINGS )
152 lSstyle |= WS_CLIPSIBLINGS;
153
154 SPBCDATA vCtrlData;
155
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;
162
163 m_hWnd = (WXHWND)::WinCreateWindow( GetWinHwnd(pParent)
164 ,WC_SPINBUTTON
165 ,(PSZ)NULL
166 ,lSstyle
167 ,0L, 0L, 0L, 0L
168 ,GetWinHwnd(pParent)
169 ,HWND_TOP
170 ,(HMENU)vId
171 ,(PVOID)&vCtrlData
172 ,NULL
173 );
174 if (m_hWnd == 0)
409c9842
DW
175 {
176 return FALSE;
177 }
3c299c3a
DW
178 m_hWndBuddy = m_hWnd; // One in the same for OS/2
179 if(pParent)
180 pParent->AddChild((wxSpinButton *)this);
181 SetFont(pParent->GetFont());
d8a3f66c
DW
182 ::WinQueryWindowPos(m_hWnd, &vSwp);
183 SetXComp(vSwp.x);
184 SetYComp(vSwp.y);
3c299c3a
DW
185 SetSize( rPos.x
186 ,rPos.y
187 ,rSize.x
188 ,rSize.y
189 );
190
191 SetRange(nMin, nMax);
192 SetValue(nInitial);
193
194 //
195 // For OS/2 we'll just set our handle into our long data
196 //
197 wxAssociateWinWithHandle( m_hWnd
198 ,(wxWindowOS2*)this
199 );
200 ::WinSetWindowULong(GetHwnd(), QWL_USER, (LONG)this);
201 fnWndProcSpinCtrl = (WXFARPROC)::WinSubclassWindow(m_hWnd, (PFNWP)wxSpinCtrlWndProc);
202 m_svAllSpins.Add(this);
203 return TRUE;
204} // end of wxSpinCtrl::Create
409c9842 205
3c299c3a
DW
206wxSize wxSpinCtrl::DoGetBestSize() const
207{
208 wxSize vSizeBtn = wxSpinButton::DoGetBestSize();
209 int nHeight;
409c9842 210
3c299c3a 211 vSizeBtn.x += DEFAULT_ITEM_WIDTH + MARGIN_BETWEEN;
409c9842 212
3c299c3a
DW
213 wxGetCharSize( GetHWND()
214 ,NULL
215 ,&nHeight
216 ,(wxFont*)&GetFont()
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 {
3c299c3a 297 return FALSE;
3d62dcb6 298 }
3c299c3a
DW
299 ::WinEnableWindow(GetHwnd(), bEnable);
300 return TRUE;
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 );
334 lVal - atol(zVal);
335 return lVal;
336} // end of wxSpinCtrl::GetValue
337
338void wxSpinCtrl::OnChar (
339 wxKeyEvent& rEvent
340)
341{
342 switch (rEvent.KeyCode())
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);
352 vEvent.SetString((char*)sVal.c_str());
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
3c299c3a
DW
401bool wxSpinCtrl::ProcessTextCommand(
402 WXWORD wCmd
403, WXWORD wId
404)
3d62dcb6 405{
3c299c3a 406 switch (wCmd)
3d62dcb6 407 {
3c299c3a
DW
408 case SPBN_CHANGE:
409 {
410 wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED
411 ,GetId()
412 );
413 vEvent.SetEventObject(this);
414
415 wxString sVal = wxGetWindowText(m_hWndBuddy);
416
417 vEvent.SetString((char*)sVal.c_str());
418 vEvent.SetInt(GetValue());
419 return (GetEventHandler()->ProcessEvent(vEvent));
420 }
421
422 case SPBN_SETFOCUS:
423 case SPBN_KILLFOCUS:
424 {
425 wxFocusEvent vEvent( wCmd == EN_KILLFOCUS ? wxEVT_KILL_FOCUS : wxEVT_SET_FOCUS
426 ,m_windowId
427 );
428
429 vEvent.SetEventObject(this);
430 return(GetEventHandler()->ProcessEvent(vEvent));
431 }
432 default:
433 break;
3d62dcb6
DW
434 }
435
3c299c3a
DW
436 //
437 // Not processed
438 //
439 return FALSE;
440} // end of wxSpinCtrl::ProcessTextCommand
3d62dcb6 441
3c299c3a 442void wxSpinCtrl::SetFocus()
3d62dcb6 443{
3c299c3a
DW
444 ::WinSetFocus(HWND_DESKTOP, GetHwnd());
445} // end of wxSpinCtrl::SetFocus
3d62dcb6 446
3c299c3a
DW
447bool wxSpinCtrl::SetFont(
448 const wxFont& rFont
449)
450{
451 if (!wxWindowBase::SetFont(rFont))
3d62dcb6 452 {
3c299c3a
DW
453 // nothing to do
454 return FALSE;
3d62dcb6 455 }
3d62dcb6 456
3c299c3a
DW
457 WXHANDLE hFont = GetFont().GetResourceHandle();
458 wxOS2SetFont( m_hWnd
459 ,rFont
460 );
461 return TRUE;
462} // end of wxSpinCtrl::SetFont
409c9842 463
3c299c3a
DW
464void wxSpinCtrl::SetValue(
465 const wxString& rsText
466)
3d62dcb6 467{
3c299c3a 468 long lVal;
3d62dcb6 469
3c299c3a
DW
470 lVal = atol(rsText.c_str());
471 wxSpinButton::SetValue(lVal);
472} // end of wxSpinCtrl::SetValue
3d62dcb6 473
3c299c3a
DW
474bool wxSpinCtrl::Show(
475 bool bShow
476)
409c9842 477{
3c299c3a 478 if (!wxControl::Show(bShow))
409c9842 479 {
3c299c3a 480 return FALSE;
409c9842 481 }
3c299c3a
DW
482 return TRUE;
483} // end of wxSpinCtrl::Show
7e99520b
DW
484
485#endif //wxUSE_SPINBTN