When I needed a numeric spin control, I searched both CodeGuru and
CodeProject. Surprisingly I only found one article by T. VU KHAC on CodeGuru, but as
it turned out his
CNumSpinCtrl could only be used in pair with
CNumEdit which was too restrictive for my purposes. So I ended up
writing my own numeric spin control.
CNumSpinCtrl allows you to work with non-integer numbers quite easily.
It provides methods to set up value range, increment, and current position. It
also lets you format the output value either by specifying number of decimal
places or by providing your own formatting string.
Using the control is not much different from using
CSpinButtonCtrl. You would subclass a dialog item or create the
control dynamically. Then all you need to do is to set up range and position
and, if necessary, the output formatting. Here’s an example from the demo
m_spinValue.SetRangeAndDelta (0.1, 1.0, 0.05);
There one thing to watch out however - style. Make sure you uncheck the "Set
buddy integer" style or, if you are creating control dynamically, do not add
UDS_SETBUDDYINT style. Otherwise the Windows automatically resets buddy's value
to some integer when user clicks up/down arrows.
There are two ways to format the output value: by specifying a number of
decimal places or by providing a formatting string. With the first method you
will specify number of decimal places with a call to
Passing -1 to this function will turn off rounding to decimal places (the value
will be output with
"%g" format string). You can also specify
whether you want to trim any trailing zeros with a call to
With a second method you simply provide your own formatting string, which later
will be used with
Format function. Example:
Be sure to set appropriate formatting settings. If your formatting settings
are inadequate for the current range and increment, the text in the buddy
control may not change at all. For example, if you set the increment to be
0.005, but the number of decimal places only to 1, the value in buddy control
will not change when a user clicks on up and down arrows. This is because the
control does not keep the current value internally. The value is obtained from
the buddy control before it is incremented or decremented. Then it is formatted
and passed back to the buddy control. So the formatting settings are quite
InitControl - it didn't work,
UDS_SETBUDDYINT style. Put
ASSERT instead. So now program will
ASSERT if you forget to remove
UDS_SETBUDDYINT style in resources.
Fixed wrapping. In some cases due to poor machine precision the wrapping
condition didn't evaluate properly.
||Warren Stevens added wrapping ability. If the style of the
spin control is set to "wrap", the value will wrap around if increased or
decreased past the range limits.
||Fixed bug with trimming zeros. If number of decimal places
was set to zero, it was still trimming zeros (e.g. 100 would become 1).
ON_NOTIFY_REFLECT_EX so that
parent can also handle notification message from spin control. Thanks to
Emmanuil Tsagarakis for this one.