]> git.saurik.com Git - wxWidgets.git/blob - src/msw/spinctrl.cpp
1e5ed522668e83575a2e3eb605f658f49383f5e6
[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 defined(__WIN95__)
37
38 #include "wx/spinctrl.h"
39 #include "wx/msw/private.h"
40
41 #if (defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__) || defined(wxUSE_NORLANDER_HEADERS)
42 #include <commctrl.h>
43 #endif
44
45 #include <limits.h> // for INT_MIN
46
47 // ----------------------------------------------------------------------------
48 // macros
49 // ----------------------------------------------------------------------------
50
51 #if !USE_SHARED_LIBRARY
52 IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl)
53 #endif
54
55 // ----------------------------------------------------------------------------
56 // constants
57 // ----------------------------------------------------------------------------
58
59 // the margin between the up-down control and its buddy (can be arbitrary,
60 // choose what you like - or may be decide during run-time depending on the
61 // font size?)
62 static const int MARGIN_BETWEEN = 1;
63
64 // ============================================================================
65 // implementation
66 // ============================================================================
67
68 // ----------------------------------------------------------------------------
69 // construction
70 // ----------------------------------------------------------------------------
71
72 bool wxSpinCtrl::Create(wxWindow *parent,
73 wxWindowID id,
74 const wxString& value,
75 const wxPoint& pos,
76 const wxSize& size,
77 long style,
78 int min, int max, int initial,
79 const wxString& name)
80 {
81 // before using DoGetBestSize(), have to set style to let the base class
82 // know whether this is a horizontal or vertical control (we're always
83 // vertical)
84 SetWindowStyle(style | wxSP_VERTICAL);
85
86 // calculate the sizes: the size given is the toal size for both controls
87 // and we need to fit them both in the given width (height is the same)
88 wxSize sizeText(size), sizeBtn(size);
89 sizeBtn.x = wxSpinButton::DoGetBestSize().x;
90 if ( sizeText.x <= 0 )
91 {
92 // DEFAULT_ITEM_WIDTH is the default width for the text control
93 sizeText.x = DEFAULT_ITEM_WIDTH + MARGIN_BETWEEN + sizeBtn.x;
94 }
95
96 sizeText.x -= sizeBtn.x + MARGIN_BETWEEN;
97 if ( sizeText.x <= 0 )
98 {
99 wxLogDebug(_T("not enough space for wxSpinCtrl!"));
100 }
101
102 wxPoint posBtn(pos);
103 posBtn.x += sizeText.x + MARGIN_BETWEEN;
104
105 // create the spin button
106 if ( !wxSpinButton::Create(parent, id, posBtn, sizeBtn, style, name) )
107 {
108 return FALSE;
109 }
110
111 SetRange(min, max);
112 SetValue(initial);
113
114 // create the text window
115 m_hwndBuddy = (WXHWND)::CreateWindowEx
116 (
117 WS_EX_CLIENTEDGE, // sunken border
118 _T("EDIT"), // window class
119 NULL, // no window title
120 WS_CHILD | WS_BORDER, // style (will be shown later)
121 pos.x, pos.y, // position
122 0, 0, // size (will be set later)
123 GetHwndOf(parent), // parent
124 (HMENU)-1, // control id
125 wxGetInstance(), // app instance
126 NULL // unused client data
127 );
128
129 if ( !m_hwndBuddy )
130 {
131 wxLogLastError("CreateWindow(buddy text window)");
132
133 return FALSE;
134 }
135
136 // should have the same font as the other controls
137 SetFont(GetParent()->GetFont());
138
139 // set the size of the text window - can do it only now, because we
140 // couldn't call DoGetBestSize() before as font wasn't set
141 if ( sizeText.y <= 0 )
142 {
143 // make it the same height as the button then
144 sizeText.y = DoGetBestSize().y;
145 }
146
147 DoMoveWindow(pos.x, pos.y,
148 sizeText.x + sizeBtn.x + MARGIN_BETWEEN, sizeText.y);
149
150 (void)::ShowWindow((HWND)m_hwndBuddy, SW_SHOW);
151
152 // associate the text window with the spin button
153 (void)::SendMessage(GetHwnd(), UDM_SETBUDDY, (WPARAM)m_hwndBuddy, 0);
154
155 if ( !value.IsEmpty() )
156 {
157 SetValue(value);
158 }
159
160 return TRUE;
161 }
162
163 // ----------------------------------------------------------------------------
164 // wxTextCtrl-like methods
165 // ----------------------------------------------------------------------------
166
167 void wxSpinCtrl::SetValue(const wxString& text)
168 {
169 if ( ::SetWindowText((HWND)m_hwndBuddy, text.c_str()) )
170 {
171 wxLogLastError("SetWindowText(buddy)");
172 }
173 }
174
175 int wxSpinCtrl::GetValue() const
176 {
177 wxString val = wxGetWindowText(m_hwndBuddy);
178
179 long n;
180 if ( (wxSscanf(val, wxT("%lu"), &n) != 1) )
181 n = INT_MIN;
182
183 return n;
184 }
185
186 // ----------------------------------------------------------------------------
187 // when setting font, we need to do it for both controls
188 // ----------------------------------------------------------------------------
189
190 bool wxSpinCtrl::SetFont(const wxFont& font)
191 {
192 if ( !wxWindowBase::SetFont(font) )
193 {
194 // nothing to do
195 return FALSE;
196 }
197
198 WXHANDLE hFont = GetFont().GetResourceHandle();
199 (void)::SendMessage((HWND)m_hwndBuddy, WM_SETFONT, (WPARAM)hFont, TRUE);
200
201 return TRUE;
202 }
203
204 // ----------------------------------------------------------------------------
205 // size calculations
206 // ----------------------------------------------------------------------------
207
208 wxSize wxSpinCtrl::DoGetBestSize()
209 {
210 wxSize sizeBtn = wxSpinButton::DoGetBestSize();
211 sizeBtn.x += DEFAULT_ITEM_WIDTH + MARGIN_BETWEEN;
212
213 int y;
214 wxGetCharSize(GetHWND(), NULL, &y, &GetFont());
215 y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(y);
216
217 if ( sizeBtn.y < y )
218 {
219 // make the text tall enough
220 sizeBtn.y = y;
221 }
222
223 return sizeBtn;
224 }
225
226 void wxSpinCtrl::DoMoveWindow(int x, int y, int width, int height)
227 {
228 int widthBtn = wxSpinButton::DoGetBestSize().x;
229 int widthText = width - widthBtn - MARGIN_BETWEEN;
230 if ( widthText <= 0 )
231 {
232 wxLogDebug(_T("not enough space for wxSpinCtrl!"));
233 }
234
235 if ( !::MoveWindow((HWND)m_hwndBuddy, x, y, widthText, height, TRUE) )
236 {
237 wxLogLastError("MoveWindow(buddy)");
238 }
239
240 x += widthText + MARGIN_BETWEEN;
241 if ( !::MoveWindow(GetHwnd(), x, y, widthBtn, height, TRUE) )
242 {
243 wxLogLastError("MoveWindow");
244 }
245 }
246
247 #endif // __WIN95__