]> git.saurik.com Git - wxWidgets.git/blob - src/msw/spinctrl.cpp
wxCalendarCtrl works under MSW too
[wxWidgets.git] / src / msw / spinctrl.cpp
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
36 #if wxUSE_SPINCTRL
37
38 #if defined(__WIN95__)
39
40 #include "wx/spinctrl.h"
41 #include "wx/msw/private.h"
42
43 #if (defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__) || defined(wxUSE_NORLANDER_HEADERS)
44 #include <commctrl.h>
45 #endif
46
47 #include <limits.h> // for INT_MIN
48
49 // ----------------------------------------------------------------------------
50 // macros
51 // ----------------------------------------------------------------------------
52
53 IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl)
54
55 BEGIN_EVENT_TABLE(wxSpinCtrl, wxSpinButton)
56 EVT_SPIN(-1, wxSpinCtrl::OnSpinChange)
57 END_EVENT_TABLE()
58
59 // ----------------------------------------------------------------------------
60 // constants
61 // ----------------------------------------------------------------------------
62
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?)
66 static const int MARGIN_BETWEEN = 1;
67
68 // ============================================================================
69 // implementation
70 // ============================================================================
71
72 // ----------------------------------------------------------------------------
73 // construction
74 // ----------------------------------------------------------------------------
75
76 bool wxSpinCtrl::Create(wxWindow *parent,
77 wxWindowID id,
78 const wxString& value,
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)
88 style |= wxSP_VERTICAL;
89 SetWindowStyle(style);
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;
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
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
120 m_hwndBuddy = (WXHWND)::CreateWindowEx
121 (
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
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
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 {
148 int cx, cy;
149 wxGetCharSize(GetHWND(), &cx, &cy, &GetFont());
150
151 sizeText.y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
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);
158
159 // associate the text window with the spin button
160 (void)::SendMessage(GetHwnd(), UDM_SETBUDDY, (WPARAM)m_hwndBuddy, 0);
161
162 if ( !value.IsEmpty() )
163 {
164 SetValue(value);
165 }
166
167 return TRUE;
168 }
169
170 // ----------------------------------------------------------------------------
171 // wxTextCtrl-like methods
172 // ----------------------------------------------------------------------------
173
174 void wxSpinCtrl::SetValue(const wxString& text)
175 {
176 if ( !::SetWindowText((HWND)m_hwndBuddy, text.c_str()) )
177 {
178 wxLogLastError("SetWindowText(buddy)");
179 }
180 }
181
182 int 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
193 // ----------------------------------------------------------------------------
194 // forward some methods to subcontrols
195 // ----------------------------------------------------------------------------
196
197 bool 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);
207
208 return TRUE;
209 }
210
211 bool 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
223 bool 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
235 // ----------------------------------------------------------------------------
236 // event processing
237 // ----------------------------------------------------------------------------
238
239 void wxSpinCtrl::OnSpinChange(wxSpinEvent& eventSpin)
240 {
241 wxCommandEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, GetId());
242 event.SetEventObject(this);
243 event.SetInt(eventSpin.GetPosition());
244
245 (void)GetEventHandler()->ProcessEvent(event);
246
247 if ( eventSpin.GetSkipped() )
248 {
249 event.Skip();
250 }
251 }
252
253 // ----------------------------------------------------------------------------
254 // size calculations
255 // ----------------------------------------------------------------------------
256
257 wxSize wxSpinCtrl::DoGetBestSize() const
258 {
259 wxSize sizeBtn = wxSpinButton::DoGetBestSize();
260 sizeBtn.x += DEFAULT_ITEM_WIDTH + MARGIN_BETWEEN;
261
262 int y;
263 wxGetCharSize(GetHWND(), NULL, &y, &GetFont());
264 y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(y);
265
266 if ( sizeBtn.y < y )
267 {
268 // make the text tall enough
269 sizeBtn.y = y;
270 }
271
272 return sizeBtn;
273 }
274
275 void wxSpinCtrl::DoMoveWindow(int x, int y, int width, int height)
276 {
277 int widthBtn = wxSpinButton::DoGetBestSize().x;
278 int widthText = width - widthBtn - MARGIN_BETWEEN;
279 if ( widthText <= 0 )
280 {
281 wxLogDebug(_T("not enough space for wxSpinCtrl!"));
282 }
283
284 if ( !::MoveWindow((HWND)m_hwndBuddy, x, y, widthText, height, TRUE) )
285 {
286 wxLogLastError("MoveWindow(buddy)");
287 }
288
289 x += widthText + MARGIN_BETWEEN;
290 if ( !::MoveWindow(GetHwnd(), x, y, widthBtn, height, TRUE) )
291 {
292 wxLogLastError("MoveWindow");
293 }
294 }
295
296 #endif // __WIN95__
297
298 #endif
299 // wxUSE_SPINCTRL
300