Sample17: Spin, Slider

Screenshot of Sample17.exe

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.

DLG's  Spin  and  Slider  controls are a good way to do that.

The following sections will give you some insight into

Spin - default + customized
Slider - standard
Slider - with Display
Slider - with selection range + Display
Slider - with application-specific Display
Slider - with fully customized Display
vertical Slider - with Range reversed

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


Screenshot of default + customized Spin

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.)

top

standard Slider


Screenshot of standard Slider (ticks only) Screenshot of standard Slider (scale)

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)

top

Slider
with Display


Screenshot: 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.)

top

Slider
with selection range + Display


Screenshot: 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.)

top

Slider
with application-specific Display


Screenshot: 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.)

top

Slider
with fully customized Display


Screenshot: 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));
}

top

Vertical Slider
with Range Reversed


Screenshot: 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);
}

top

Home | Outline | DLG