]> git.saurik.com Git - wxWidgets.git/blame - src/msw/spinctrl.cpp
1. some fixes for the problems reported by BoundsChecker
[wxWidgets.git] / src / msw / spinctrl.cpp
CommitLineData
b782f2e0
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: msw/spinctrl.cpp
3// Purpose: wxSpinCtrl class implementation for Win32
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 22.07.99
7// RCS-ID: $Id$
8// Copyright: (c) Vadim Zeitlin
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16#ifdef __GNUG__
17 #pragma implementation "spinctrlbase.h"
18 #pragma implementation "spinctrl.h"
19#endif
20
21// ----------------------------------------------------------------------------
22// headers
23// ----------------------------------------------------------------------------
24
25// for compilers that support precompilation, includes "wx.h".
26#include "wx/wxprec.h"
27
28#ifdef __BORLANDC__
29 #pragma hdrstop
30#endif
31
32#ifndef WX_PRECOMP
33 #include "wx/wx.h"
34#endif
35
0e528b99
JS
36#if wxUSE_SPINCTRL
37
b782f2e0
VZ
38#if defined(__WIN95__)
39
40#include "wx/spinctrl.h"
41#include "wx/msw/private.h"
42
4c0a2c5c
JS
43#if (defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__) || defined(wxUSE_NORLANDER_HEADERS)
44 #include <commctrl.h>
45#endif
b782f2e0 46
678cd6de
VZ
47#include <limits.h> // for INT_MIN
48
b782f2e0
VZ
49// ----------------------------------------------------------------------------
50// macros
51// ----------------------------------------------------------------------------
52
9750fc42
VZ
53IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl)
54
55BEGIN_EVENT_TABLE(wxSpinCtrl, wxSpinButton)
56 EVT_SPIN(-1, wxSpinCtrl::OnSpinChange)
57END_EVENT_TABLE()
b782f2e0
VZ
58
59// ----------------------------------------------------------------------------
60// constants
61// ----------------------------------------------------------------------------
62
baccb514
VZ
63// the margin between the up-down control and its buddy (can be arbitrary,
64// choose what you like - or may be decide during run-time depending on the
65// font size?)
66static const int MARGIN_BETWEEN = 1;
b782f2e0
VZ
67
68// ============================================================================
69// implementation
70// ============================================================================
71
72// ----------------------------------------------------------------------------
73// construction
74// ----------------------------------------------------------------------------
75
76bool wxSpinCtrl::Create(wxWindow *parent,
77 wxWindowID id,
678cd6de 78 const wxString& value,
b782f2e0
VZ
79 const wxPoint& pos,
80 const wxSize& size,
81 long style,
82 int min, int max, int initial,
83 const wxString& name)
84{
85 // before using DoGetBestSize(), have to set style to let the base class
86 // know whether this is a horizontal or vertical control (we're always
87 // vertical)
882a8f40
VZ
88 style |= wxSP_VERTICAL;
89 SetWindowStyle(style);
b782f2e0
VZ
90
91 // calculate the sizes: the size given is the toal size for both controls
92 // and we need to fit them both in the given width (height is the same)
93 wxSize sizeText(size), sizeBtn(size);
94 sizeBtn.x = wxSpinButton::DoGetBestSize().x;
baccb514
VZ
95 if ( sizeText.x <= 0 )
96 {
97 // DEFAULT_ITEM_WIDTH is the default width for the text control
98 sizeText.x = DEFAULT_ITEM_WIDTH + MARGIN_BETWEEN + sizeBtn.x;
99 }
100
b782f2e0
VZ
101 sizeText.x -= sizeBtn.x + MARGIN_BETWEEN;
102 if ( sizeText.x <= 0 )
103 {
104 wxLogDebug(_T("not enough space for wxSpinCtrl!"));
105 }
106
107 wxPoint posBtn(pos);
108 posBtn.x += sizeText.x + MARGIN_BETWEEN;
109
110 // create the spin button
111 if ( !wxSpinButton::Create(parent, id, posBtn, sizeBtn, style, name) )
112 {
113 return FALSE;
114 }
115
116 SetRange(min, max);
117 SetValue(initial);
118
119 // create the text window
b782f2e0
VZ
120 m_hwndBuddy = (WXHWND)::CreateWindowEx
121 (
baccb514
VZ
122 WS_EX_CLIENTEDGE, // sunken border
123 _T("EDIT"), // window class
124 NULL, // no window title
125 WS_CHILD | WS_BORDER, // style (will be shown later)
126 pos.x, pos.y, // position
127 0, 0, // size (will be set later)
128 GetHwndOf(parent), // parent
129 (HMENU)-1, // control id
130 wxGetInstance(), // app instance
131 NULL // unused client data
b782f2e0
VZ
132 );
133
134 if ( !m_hwndBuddy )
135 {
136 wxLogLastError("CreateWindow(buddy text window)");
137
138 return FALSE;
139 }
140
141 // should have the same font as the other controls
baccb514
VZ
142 SetFont(GetParent()->GetFont());
143
144 // set the size of the text window - can do it only now, because we
145 // couldn't call DoGetBestSize() before as font wasn't set
146 if ( sizeText.y <= 0 )
147 {
882a8f40
VZ
148 int cx, cy;
149 wxGetCharSize(GetHWND(), &cx, &cy, &GetFont());
150
151 sizeText.y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
baccb514
VZ
152 }
153
154 DoMoveWindow(pos.x, pos.y,
155 sizeText.x + sizeBtn.x + MARGIN_BETWEEN, sizeText.y);
156
157 (void)::ShowWindow((HWND)m_hwndBuddy, SW_SHOW);
b782f2e0
VZ
158
159 // associate the text window with the spin button
baccb514
VZ
160 (void)::SendMessage(GetHwnd(), UDM_SETBUDDY, (WPARAM)m_hwndBuddy, 0);
161
678cd6de
VZ
162 if ( !value.IsEmpty() )
163 {
164 SetValue(value);
165 }
166
baccb514
VZ
167 return TRUE;
168}
169
678cd6de
VZ
170// ----------------------------------------------------------------------------
171// wxTextCtrl-like methods
172// ----------------------------------------------------------------------------
173
174void wxSpinCtrl::SetValue(const wxString& text)
175{
882a8f40 176 if ( !::SetWindowText((HWND)m_hwndBuddy, text.c_str()) )
678cd6de
VZ
177 {
178 wxLogLastError("SetWindowText(buddy)");
179 }
180}
181
182int wxSpinCtrl::GetValue() const
183{
184 wxString val = wxGetWindowText(m_hwndBuddy);
185
186 long n;
187 if ( (wxSscanf(val, wxT("%lu"), &n) != 1) )
188 n = INT_MIN;
189
190 return n;
191}
192
baccb514 193// ----------------------------------------------------------------------------
882a8f40 194// forward some methods to subcontrols
baccb514
VZ
195// ----------------------------------------------------------------------------
196
197bool wxSpinCtrl::SetFont(const wxFont& font)
198{
199 if ( !wxWindowBase::SetFont(font) )
200 {
201 // nothing to do
202 return FALSE;
203 }
204
205 WXHANDLE hFont = GetFont().GetResourceHandle();
206 (void)::SendMessage((HWND)m_hwndBuddy, WM_SETFONT, (WPARAM)hFont, TRUE);
b782f2e0
VZ
207
208 return TRUE;
209}
210
882a8f40
VZ
211bool wxSpinCtrl::Show(bool show)
212{
213 if ( !wxControl::Show(show) )
214 {
215 return FALSE;
216 }
217
218 ::ShowWindow((HWND)m_hwndBuddy, show ? SW_SHOW : SW_HIDE);
219
220 return TRUE;
221}
222
223bool wxSpinCtrl::Enable(bool enable)
224{
225 if ( !wxControl::Enable(enable) )
226 {
227 return FALSE;
228 }
229
230 ::EnableWindow((HWND)m_hwndBuddy, enable);
231
232 return TRUE;
233}
234
8bf3196d
GRG
235void wxSpinCtrl::SetFocus()
236{
237 ::SetFocus((HWND)m_hwndBuddy);
238}
239
9750fc42
VZ
240// ----------------------------------------------------------------------------
241// event processing
242// ----------------------------------------------------------------------------
243
244void wxSpinCtrl::OnSpinChange(wxSpinEvent& eventSpin)
245{
246 wxCommandEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, GetId());
247 event.SetEventObject(this);
248 event.SetInt(eventSpin.GetPosition());
249
250 (void)GetEventHandler()->ProcessEvent(event);
251
252 if ( eventSpin.GetSkipped() )
253 {
254 event.Skip();
255 }
256}
257
b782f2e0
VZ
258// ----------------------------------------------------------------------------
259// size calculations
260// ----------------------------------------------------------------------------
261
f68586e5 262wxSize wxSpinCtrl::DoGetBestSize() const
baccb514
VZ
263{
264 wxSize sizeBtn = wxSpinButton::DoGetBestSize();
265 sizeBtn.x += DEFAULT_ITEM_WIDTH + MARGIN_BETWEEN;
266
267 int y;
268 wxGetCharSize(GetHWND(), NULL, &y, &GetFont());
269 y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(y);
270
271 if ( sizeBtn.y < y )
272 {
273 // make the text tall enough
274 sizeBtn.y = y;
275 }
276
277 return sizeBtn;
278}
279
b782f2e0
VZ
280void wxSpinCtrl::DoMoveWindow(int x, int y, int width, int height)
281{
baccb514 282 int widthBtn = wxSpinButton::DoGetBestSize().x;
b782f2e0
VZ
283 int widthText = width - widthBtn - MARGIN_BETWEEN;
284 if ( widthText <= 0 )
285 {
286 wxLogDebug(_T("not enough space for wxSpinCtrl!"));
287 }
288
289 if ( !::MoveWindow((HWND)m_hwndBuddy, x, y, widthText, height, TRUE) )
290 {
291 wxLogLastError("MoveWindow(buddy)");
292 }
293
294 x += widthText + MARGIN_BETWEEN;
295 if ( !::MoveWindow(GetHwnd(), x, y, widthBtn, height, TRUE) )
296 {
297 wxLogLastError("MoveWindow");
298 }
299}
300
301#endif // __WIN95__
0e528b99
JS
302
303#endif
304 // wxUSE_SPINCTRL
305