]> git.saurik.com Git - wxWidgets.git/blob - src/msw/spinctrl.cpp
Small doc updates, mainly wxDropTarget,
[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 SetWindowStyle(style | wxSP_VERTICAL);
89
90 // calculate the sizes: the size given is the toal size for both controls
91 // and we need to fit them both in the given width (height is the same)
92 wxSize sizeText(size), sizeBtn(size);
93 sizeBtn.x = wxSpinButton::DoGetBestSize().x;
94 if ( sizeText.x <= 0 )
95 {
96 // DEFAULT_ITEM_WIDTH is the default width for the text control
97 sizeText.x = DEFAULT_ITEM_WIDTH + MARGIN_BETWEEN + sizeBtn.x;
98 }
99
100 sizeText.x -= sizeBtn.x + MARGIN_BETWEEN;
101 if ( sizeText.x <= 0 )
102 {
103 wxLogDebug(_T("not enough space for wxSpinCtrl!"));
104 }
105
106 wxPoint posBtn(pos);
107 posBtn.x += sizeText.x + MARGIN_BETWEEN;
108
109 // create the spin button
110 if ( !wxSpinButton::Create(parent, id, posBtn, sizeBtn, style, name) )
111 {
112 return FALSE;
113 }
114
115 SetRange(min, max);
116 SetValue(initial);
117
118 // create the text window
119 m_hwndBuddy = (WXHWND)::CreateWindowEx
120 (
121 WS_EX_CLIENTEDGE, // sunken border
122 _T("EDIT"), // window class
123 NULL, // no window title
124 WS_CHILD | WS_BORDER, // style (will be shown later)
125 pos.x, pos.y, // position
126 0, 0, // size (will be set later)
127 GetHwndOf(parent), // parent
128 (HMENU)-1, // control id
129 wxGetInstance(), // app instance
130 NULL // unused client data
131 );
132
133 if ( !m_hwndBuddy )
134 {
135 wxLogLastError("CreateWindow(buddy text window)");
136
137 return FALSE;
138 }
139
140 // should have the same font as the other controls
141 SetFont(GetParent()->GetFont());
142
143 // set the size of the text window - can do it only now, because we
144 // couldn't call DoGetBestSize() before as font wasn't set
145 if ( sizeText.y <= 0 )
146 {
147 // make it the same height as the button then
148 sizeText.y = DoGetBestSize().y;
149 }
150
151 DoMoveWindow(pos.x, pos.y,
152 sizeText.x + sizeBtn.x + MARGIN_BETWEEN, sizeText.y);
153
154 (void)::ShowWindow((HWND)m_hwndBuddy, SW_SHOW);
155
156 // associate the text window with the spin button
157 (void)::SendMessage(GetHwnd(), UDM_SETBUDDY, (WPARAM)m_hwndBuddy, 0);
158
159 if ( !value.IsEmpty() )
160 {
161 SetValue(value);
162 }
163
164 return TRUE;
165 }
166
167 // ----------------------------------------------------------------------------
168 // wxTextCtrl-like methods
169 // ----------------------------------------------------------------------------
170
171 void wxSpinCtrl::SetValue(const wxString& text)
172 {
173 if ( ::SetWindowText((HWND)m_hwndBuddy, text.c_str()) )
174 {
175 wxLogLastError("SetWindowText(buddy)");
176 }
177 }
178
179 int wxSpinCtrl::GetValue() const
180 {
181 wxString val = wxGetWindowText(m_hwndBuddy);
182
183 long n;
184 if ( (wxSscanf(val, wxT("%lu"), &n) != 1) )
185 n = INT_MIN;
186
187 return n;
188 }
189
190 // ----------------------------------------------------------------------------
191 // when setting font, we need to do it for both controls
192 // ----------------------------------------------------------------------------
193
194 bool wxSpinCtrl::SetFont(const wxFont& font)
195 {
196 if ( !wxWindowBase::SetFont(font) )
197 {
198 // nothing to do
199 return FALSE;
200 }
201
202 WXHANDLE hFont = GetFont().GetResourceHandle();
203 (void)::SendMessage((HWND)m_hwndBuddy, WM_SETFONT, (WPARAM)hFont, TRUE);
204
205 return TRUE;
206 }
207
208 // ----------------------------------------------------------------------------
209 // event processing
210 // ----------------------------------------------------------------------------
211
212 void wxSpinCtrl::OnSpinChange(wxSpinEvent& eventSpin)
213 {
214 wxCommandEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, GetId());
215 event.SetEventObject(this);
216 event.SetInt(eventSpin.GetPosition());
217
218 (void)GetEventHandler()->ProcessEvent(event);
219
220 if ( eventSpin.GetSkipped() )
221 {
222 event.Skip();
223 }
224 }
225
226 // ----------------------------------------------------------------------------
227 // size calculations
228 // ----------------------------------------------------------------------------
229
230 wxSize wxSpinCtrl::DoGetBestSize() const
231 {
232 wxSize sizeBtn = wxSpinButton::DoGetBestSize();
233 sizeBtn.x += DEFAULT_ITEM_WIDTH + MARGIN_BETWEEN;
234
235 int y;
236 wxGetCharSize(GetHWND(), NULL, &y, &GetFont());
237 y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(y);
238
239 if ( sizeBtn.y < y )
240 {
241 // make the text tall enough
242 sizeBtn.y = y;
243 }
244
245 return sizeBtn;
246 }
247
248 void wxSpinCtrl::DoMoveWindow(int x, int y, int width, int height)
249 {
250 int widthBtn = wxSpinButton::DoGetBestSize().x;
251 int widthText = width - widthBtn - MARGIN_BETWEEN;
252 if ( widthText <= 0 )
253 {
254 wxLogDebug(_T("not enough space for wxSpinCtrl!"));
255 }
256
257 if ( !::MoveWindow((HWND)m_hwndBuddy, x, y, widthText, height, TRUE) )
258 {
259 wxLogLastError("MoveWindow(buddy)");
260 }
261
262 x += widthText + MARGIN_BETWEEN;
263 if ( !::MoveWindow(GetHwnd(), x, y, widthBtn, height, TRUE) )
264 {
265 wxLogLastError("MoveWindow");
266 }
267 }
268
269 #endif // __WIN95__
270
271 #endif
272 // wxUSE_SPINCTRL
273