Remembering Logo
Turtle graphics tutorial
Scripting language tutorial
Changing window icons at runtime
A real spinner control
Tip Corner - Select Case
Hocus Focus
Illuminated Radiobuttons
A spinner, or updown control is a textbox with two small arrow buttons attached to one side. When a user presses the buttons, either by clicking on them with the mouse, or by pressing the up and down arrow keys on the keyboard, the value displayed in the textbox is incremented or decremented.
Pressing a regular push button only activates a routine once. To activate it again, the button must be released, then pressed again. This is not true of the arrow buttons on spinner controls. As long as the button is depressed, the value displayed in the textbox continues to change - it is incremented if the up arrow is being pressed, and decremented if the down arrow is being pressed.
Although it may sound as if this control would be complicated to create with API calls, and to use, it is actually quite simple. It does require a knowledge of the Windows API as used in Liberty BASIC, however, and that basic knowledge is assumed for this article.
Please note that this is for LB3 only. It is a good idea to include version checks in our programs to insure that the correct version of LB is used to run them:
if val(Version$)<3 then notice "Requires LB3." end end if
The function to create it is part of the common controls 32-bit DLL -- comctl32.dll. It is first necessary to initialize the DLL for use:
calldll #comctl32, "InitCommonControls",re as void
The function is called "CreateUpDownControl". It requires several arguments. You must include the handle of the parent window, which is obtained with LB's HWND() function. It also requires the Instance Handle of the window, which is obtained with the GetWindowLongA function, using the _GWL_HINSTANCE flag.
hwndParent = hwnd(#1)
'get parent instance handle: CallDLL #user32, "GetWindowLongA",_ hwndParent As long,_ 'window handle _GWL_HINSTANCE As long,_'want instance handle hInstance As long 'returns instance handle of window
The function arguments also include x, y, width and height values, which can all be set to 0, because our example gives the updown control a buddy textbox, and the control will be located and sized according to the buddy control. We'll need the handle of the buddy textbox as well:
textbox #1.t, 50,40,60,26 hText=hwnd(#1.t)
The function also allows us to set the upper limit value for the spinner as well as the lower limit. It also allows us to set the initial value to be displayed. The function returns a handle to the spinner (updown) control:
x=0:y=0:wide=0:high=0:upr=100:lwr=0:pos=50 calldll #comctl32, "CreateUpDownControl",_ dwStyle as ulong,_ 'style x as long,_ 'x placement y as long,_ 'y placement wide as long,_ 'width high as long,_ 'height hwndParent as long,_ 'parent handle id as long,_ 'an ID number hInstance as long,_ 'parent instance handle hText as long,_ 'buddy control - a textbox handle upr as long,_ 'upper limit lwr as long,_ 'lower limit pos as long,_ 'initial value hSpinner as long 'handle of control
We haven't yet addressed an essential argument for the function. This is the
style argument. All controls created by API must have a minimum style flag
that includes the _WS_CHILD and _WS_VISIBLE window styles, so that the control
is a child of the program window, and so that it is visible. It is also good
to include the _WS_BORDER style so that the control has a nice appearance.
dwStyle = _WS_CHILD or _WS_VISIBLE or _WS_BORDER
There are other style bits that must be set for an updown spinnercontrol.
UDS.SETBUDDYINT or UDS.ALIGNRIGHT or UDS.ARROWKEYS
Our demo uses the ones above. The UDS.SETBUDDYINT causes the buddy textbox to display the value continuously and automatically when the spinner is activated. The UDS.ALIGNRIGHT bit places the spinner on the right edge of the buddy textbox. The UDS.ARROWKEYS makes the spinner respond when the user presses the keyboard arrow keys.
Here are all of the possible UDS styles, along with their values and descriptions:
UDS.SETBUDDYINT = hexdec("2") Causes the up-down control
to set the text of the buddy window (using the WM_SETTEXT message) when the
position changes. The text consists of the position formatted as a decimal
or hexadecimal string.
UDS.NOTHOUSANDS = hexdec("80") Does not insert a thousands separator between every three decimal digits.
UDS.HOTTRACK = hexdec("100") Causes the control to exhibit "hot tracking" behavior. That is, it highlights the UP ARROW and DOWN ARROW on the control as the pointer passes over them. This style requires Microsoft® Windows® 98 or Windows® 2000. If the system is running Windows® 95 or Windows NT® 4.0, the flag is ignored. To check whether hot tracking is enabled, call SystemParametersInfo.
UDS.HORZ = hexdec("40") Causes the up-down control's arrows to point left and right instead of up and down.
UDS.AUTOBUDDY = hexdec("10") Automatically selects the previous window in the z-order as the up-down control's buddy window.
UDS.ARROWKEYS = hexdec("20") Causes the up-down control to increment and decrement the position when the UP ARROW and DOWN ARROW keys are pressed.
UDS.ALIGNRIGHT = hexdec("4") Positions the up-down control next to the right edge of the buddy window. The width of the buddy window is decreased to accommodate the width of the up-down control.
UDS.ALIGNLEFT = hexdec("8") Positions the up-down control next to the left edge of the buddy window. The buddy window is moved to the right, and its width is decreased to accommodate the width of the up-down control.
UDS.WRAP = hexdec("1") Causes the position to "wrap" if it is incremented or decremented beyond the ending or beginning of the range.
The style bits as set in our demo:
dwStyle = _WS_CHILD or _WS_VISIBLE or _WS_BORDER _ or UDS.SETBUDDYINT or UDS.ALIGNRIGHT _ or UDS.ARROWKEYS
When the program finishes, free the memory used by the control by destroying it with a call to DestroyWindow"
[quit] calldll #user32, "DestroyWindow",_ hSpinner as long, re as long close #1:end
To discover the value chosen by the user, simply check the contents of the buddy textbox:
#1.t "!contents? txt$" notice "Percent is ";txt$
Although it takes a few function calls to create the control, once it is created, it is very simple to get the buddy textbox contents with the Liberty BASIC "!contents? txt$" command to discover the value. If necessary, use the VAL() function to get a numeric value
answer = VAL(txt$)
Please see the attached file, updownspinner.bas for the complete demo program.