![]() |
In most applications you need to prompt the user for a numeric
input. Well, technically that's no problem: simply present an EditBox and have the
user type into it. But - is that really a user-friendly way ... ?
Better it would be to
1. present an input control that can be handled by both, mouse and keyboard
2. give the user intuitive feedback what an input really means in that application.
The following sections will give you some insight into
After each section you will find a bookmark at the right edge of the screen (top). You can jump back to the top by clicking on it.
| Spin default + customized |
A "Spin" is
a combination of an EditBox and a vertical ScrollBar. When the user clicks one of
the buttons of the ScrollBar or presses one of certain keys, the Spin value varies
by a certain amount.
A Spin control is good if the user should not feel limited as to the input number.
If necessary, any number may be typed directly into the EditBox.
Therefore, a Spin can be handled by mouse and/or by keyboard.
If necessary, a Spin can have any of the standard DLG options for embellishment etc.
int iSpin1; Control (..., "Spin", DYN_SPIN, ..., ..., "\bIO=%p", &iSpin1, ... ), |
int iSpin2; Control (..., "Spin", DYN_SPIN, ..., ..., "\bIO=%p", &iSpin2, " Notempty BkColor=%x", RGB_YELLOW, " wScroll=... StepS=... " "StepL=...", ... ), |
| "Spin" | window class of this control |
| DYN_SPIN | style bit combination for a Spin |
| \b | DLG-specific separator to introduce options |
| "IO=%p", &iSpin1 "IO=%p", &iSpin2 |
DLG option to associate a control with an integer variable. |
| "Notempty" | DLG option to have the Spin value checked for <> 0
before dialog is closed. (If it is 0 then, the Spin is "blinked" and closing the dialog is refused.) |
| "BkColor=%x", RGB_YELLOW | DLG option to paint background in yellow color. (Good to draw the user attention to a checked input.) |
| "wScroll=..." | DLG option to set the width of the scroll buttons. (By default they are set to 1/3 of total width.) |
| "StepS=..." | Option to set small step size (default: 1). (Small step size is the amount the Spin value varies when an arrow key is pressed or when a scroll button is clicked.) |
| "StepL=..." | Option to set large step size (default: 10). (Large step size is the amount the Spin value varies when PgUp or PgDn key is pressed.) |
| standard Slider |
A "Slider" is
based on the Windows common control "Trackbar", optionally combined with a Display
to give the user meaningful feedback about the input value.
A Slider control is very versatile. It can be created in many different styles and can
have many different DLG options. But a few examples can be shown here.
In the simplest case, you can create a Slider with ticks only or create a scale
additionally, to give the user a rough feedback:
CreateCtl (..., ..., "Slider", DYN_SLIDER | TBS_TOP | TBS_AUTOTICKS, ..., ..., ..., ..., "\bTicks=10 Notempty ... ", ...); |
CreateCtl (..., ..., "Static", DYN_LTEXT, ..., ..., ..., ..., " 1 2 3 4 5 6 7\b ... ", ...); CreateCtl (..., ..., "Slider", DYN_SLIDER | TBS_TOP | TBS_NOTICKS, ..., ..., ..., ..., "\bRange=1,7 ... ", ...); |
| "Slider" | window class of this control |
| DYN_SLIDER | style bit combination for a Slider |
| TBS_TOP | style bit to have slider thumb directing to top |
| TBS_AUTOTICKS | style bit to make Slider display ticks automatically |
| TBS_NOTICKS | style bit to make Slider display no ticks |
| " 1 2 3 4 5 6 7" | scale to give feedback to user |
| \b | DLG-specific separator to introduce options |
| "Range=1,7" | option to set Slider range to 1 - 7 (default: 0 - 100) |
| Slider with Display |
![]() |
If you want to offer more convenience to the user, you should
create a Slider with a Display.
A Display is basically a Static control. Every time the user varies the Slider
value, the new value is printed as a decimal number to the Display.
A Slider with a Display can be created like in the following code line:
| CreateCtl (..., ..., "Slider", DYN_SLIDER | TBS_BOTH | TBS_NOTICKS | TBS_DISPLAY, ..., ..., ..., ..., "\bRange=0,50 StepS=5 StepL=10", ..., ...); |
| "Slider" | window class of this control |
| DYN_SLIDER | style bit combination for a Slider |
| TBS_BOTH | style bit to have slider thumb directing to no side |
| TBS_NOTICKS | style bit to make Slider display no ticks |
| TBS_DISPLAY | style bit to have Slider created with a Display |
| \b | DLG-specific separator to introduce options |
| "Range=0,50" | option to set Slider range to 1 - 50 (default: 0 - 100) |
| "StepS=5" | Option to set small step size to 5 (default: 1). (Small step size is the amount the Slider value varies when an arrow key is pressed.) |
| "StepL=20" | Option to set large step size to 20 (default: 10). (Large step size is the amount the Slider value varies when PgUp or PgDn key is pressed or when the shaft is clicked by the mouse.) |
| Slider with selection range + Display |
In many applications there is a range of values what the user
should keep his/her selection in. In the following example that "selection range"
was kept constant. With a bit more coding effort, though, you can use variables
for the limits of the selection range, too.
Optionally a Slider with selection range can also have a Display. The following
example demonstrates how easy it is to locate the Display anywhere:
| CreateCtl (..., ..., "Slider", DYN_SLIDER | TBS_ENABLESELRANGE | TBS_BOTH | TBS_DISPLAY, ..., ..., ..., ..., "\bMax=70 Sel=10,60 xDisplay=... yDisplay=...", ..., ...); |
| "Slider" | window class of this control |
| DYN_SLIDER | style bit combination for a Slider |
| TBS_ENABLESELRANGE | Style bit to have Slider created equipped with a selection range. (A selection range is for the user's convenience only.) |
| TBS_BOTH | style bit to have slider thumb directing to no side |
| TBS_DISPLAY | style bit to have Slider created with a Display |
| \b | DLG-specific separator to introduce options |
| "Max=70" | option to set the maximum Slider value to 70 (default: 100). (The minimum stays at its default value, 0.) |
| "Sel=10,60" | option to set have the selection range marked at 10 - 60 (default: none). |
| "xDisplay=... yDisplay=..." | option to set x- and y-coordinate of Display. (By default the Display is located in the middle of the shaft, beneath it.) |
| Slider with application-specific Display |
Often the bare Slider value has no meaning for the user. It is
just an index determining the further way of processing. If so, it would not be
very user-friendly to fling that value in the user's teeth. It is better to prepare
a series of application-specific texts and let DLG print one of these text items,
indexed by the Slider value.
In the following example it is assumed that the user selects screen resolutions
by a Slider. Depending on Slider's position the resolution changes from 640 x 480
to 800 x 600, etc. Consequently, these texts are printed to the Display:
| static char szDisplay [80] = "640 x 480;800 x 600;1024 x 768;1280 x 1024"; |
| CreateCtl (..., ..., "Slider", DYN_SLIDER | TBS_AUTOTICKS | TBS_DISPLAY, ..., ..., ..., ..., "\bMax=3 Display=%p", szDisplay, " wDisplay= ... ", ...); |
| "Slider" | window class of this control |
| DYN_SLIDER | style bit combination for a Slider |
| TBS_AUTOTICKS | style bit to make Slider display ticks automatically |
| TBS_DISPLAY | style bit to have Slider created with a Display |
| \b | DLG-specific separator to introduce options |
| "Max=3" | option to set the maximum Slider value to 3 (default: 100). (The minimum stays at its default value, 0.) |
| "Display=%p", szDisplay | option to make DLG use the text items assembled in char array szDisplay. (By default the current Slider value would be printed to Display.) |
| "wDisplay= ..." | option to set the Slider width. (The default value, 22, would be too small to hold a text item.) |
| Slider with fully customized Display |
![]() |
In some applications it would not give an intuitive understanding
to the user to print any text at all. For example, if the Slider value represents
actually no cardinal but rather ordinal data, such as different shades
of a color, it makes more sense to paint the color directly to the display.
In programming, this can be done by providing a callback procedure and telling DLG
not to handle the Display automatically. Instead, that callback procedure is called
every time the user varies the Slider value:
| CreateCtl (..., ..., "Slider", DYN_SLIDER | TBS_DISPLAY, ..., ..., ..., ..., "\bMax=255 ... DisplayProc=%p", DisplayProc, ...); |
| "Slider" | window class of this control |
| DYN_SLIDER | style bit combination for a Slider |
| TBS_DISPLAY | style bit to have Slider created with a Display |
| \b | DLG-specific separator to introduce options |
| "Max=255" | option to set the maximum Slider value to 255 (default: 100). (The minimum stays at its default value, 0.) |
| "DisplayProc=%p", DisplayProc | option to make DLG use the callback procedure
DisplayProc for handling the Display. (By default, DLG would handle it automatically.) |
The callback procedure needed to paint the Display in the corresponding color is one line only:
void DisplayProc (HWND hDisplay, int idSlider, int iVal)
{
SetDisplayColor (hDisplay, RGB (iVal, 0, 0));
} |
| Vertical Slider with Range Reversed |
A Slider is a good UIF-element for intuitive user handling. To that end,
you might consider to arrange it vertically, for better conveying of "more" and "less".
By default, a vertical Slider would have the minimum at top, the maximum at its lower end.
For a more intuitive handling by the user it would be good to make it quite the reverse.
With a few options and a callback procedure you can do that easily:
| CreateCtl (..., ..., "Slider", DYN_SLIDER | TBS_VERT | TBS_DISPLAY, ..., ..., ..., ..., "\bRange=-100,0 Step=-1 DisplayProc=%p", NegDisplayProc, ... ); |
| "Slider" | window class of this control |
| DYN_SLIDER | style bit combination for a Slider |
| TBS_VERT | style bit to have Slider created vertically (By default it would be horizontally.) |
| TBS_DISPLAY | style bit to have Slider created with a Display |
| \b | DLG-specific separator to introduce options |
| "Range=-100,0" | option to set the Slider range from minimum -100 to maximum 0. (It runs thru negative numbers, to have the "-100" at top. So a callback procedure to invert the sign is needed.) |
| Step=-1 | The range runs thru negative numbers, i.e. a step would move towards 0 (= the wrong direction!) To be more user-friendly, let's turn it around. |
| "DisplayProc=%p", NegDisplayProc | option to make DLG use the callback procedure NegDisplayProc for handling the Display. |
The callback procedure to set the Display text to its negative value is quite simple:
void NegDisplayProc (HWND hDisplay, int idSlider, int iVal)
{
SetWindowTextF (hDisplay, "%d", -iVal);
} |