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