|
|
|
| GUI Clinic Home |
||
| Example 30 Described | Line-by-Line Explanation | ||
Previous: Annotated Example 14 Example 30 kills two birds with one stone. It's really an example showing how to use the RGB-to-HSV color conversion functions, but it also uses the GUI. Specifically, it uses six sliders (which have been slightly extended with a custom dialog procedure), one each for Red, Green, Blue, Hue, Saturation, and Value. Moving these sliders around changes the color of the background color. Moving the RGB sliders automatically updates the HSV sliders, and vice versa. Here is a screen shot: ![]()
Here's how example 30 works. Some of the code has been re-formatted, but none of it has been changed. First, as usual, come the include files and the global declarations. We have a define for each of the six sliders, which can be used to map values into the proper items in the colors[] array. These items correspond to the Red, Green, Blue, Hue, Saturation, and Value sliders, respectively. Their starting values are given as initializers. /*
* Example program for the Allegro library,
* by Shawn Hargreaves.
*
* This program shows how to convert colors
* between the RGB and HSV representations.
*/
#include <stdlib.h>
#include <stdio.h>
#include "allegro.h"
/* slider types (R, G, B, and H, S, V) */
#define S_R 0
#define S_G 1
#define S_B 2
#define S_H 3
#define S_S 4
#define S_V 5
/* the current color values */
static int colors[6] =
{
255, /* red */
255, /* green */
255, /* blue */
0, /* hue */
0, /* saturation */
255 /* value */
};
Next, we have a callback function for the sliders. The dp2 fields will point to this routine, so it will be executed every time the slider's value changes. Basically, it updates the background color to reflect the values of the sliders on-screen. First, it determines which slider is requesting the update. If it is one of the RGB sliders, it recalculates the HSV values. If it is one of the HSV sliders, it recalculates the RGB values. Finally, it updates the screen background by adjusting color 0 in the palette. Here it is: /* helper for changing one of the color values */
int update_color(void *dp3, int val)
{
int type = ((unsigned long)dp3 -
(unsigned long)colors) /
sizeof(colors[0]);
int r, g, b;
float h, s, v;
RGB rgb;
if (colors[type] != val) {
colors[type] = val;
if ((type == S_R) || (type == S_G) ||
(type == S_B)) {
/* convert RGB color to HSV */
r = colors[S_R];
g = colors[S_G];
b = colors[S_B];
rgb_to_hsv(r, g, b, &h, &s, &v);
colors[S_H] = h * 255.0 / 360.0;
colors[S_S] = s * 255.0;
colors[S_V] = v * 255.0;
}
else {
/* convert HSV color to RGB */
h = colors[S_H] * 360.0 / 255.0;
s = colors[S_S] / 255.0;
v = colors[S_V] / 255.0;
hsv_to_rgb(h, s, v, &r, &g, &b);
colors[S_R] = r;
colors[S_G] = g;
colors[S_B] = b;
}
/* set the screen background to the new color */
rgb.r = colors[S_R]/4;
rgb.g = colors[S_G]/4;
rgb.b = colors[S_B]/4;
vsync();
set_color(0, &rgb);
}
return D_O_K;
}
After the callback comes the custom slider procedure that each slider will use. This is a pretty simple extension of the prepackaged d_slider_proc dialog procedure. It basically keeps the d2 (current value) and dp3 (current color) synchronized. /* gui object procedure for the color */
/* selection sliders */
int my_slider_proc(int msg, DIALOG *d, int c)
{
int *color = (int *)d->dp3;
switch (msg) {
case MSG_START:
/* initialise the slider position */
d->d2 = *color;
break;
case MSG_IDLE:
/* has the slider position changed? */
if (d->d2 != *color) {
d->d2 = *color;
show_mouse(NULL);
SEND_MESSAGE(d, MSG_DRAW, 0);
show_mouse(screen);
}
break;
}
return d_slider_proc(msg, d, c);
}
Next, the main dialog is declared and initialized. It's the largest dialog out of all the Allegro example dialogs, but it's one of the simplest. Let's go through it item by item. First, we have the six sliders. They're all pretty similar, so we'll discuss them all at once. They're pretty much just typical sliders. The only thing that's different is the dp3 value. The dp3 pointers all point to one of the values in the colors[] array, the one which corresponds to the value each slider controls (R, G, B, H, S, or V). The update_color callback uses this value to determine which part of the color is changing when the sliders move around. It would have been easier to just use d1 or d2 as indexes into the array, but they're already taken by the default slider code. Next, we have six inert text labels, one each for each slider. They just serve to label the sliders, so the user knows which slider does what. Finally, the dialog is terminated by a DIALOG structure with a NULL proc pointer. DIALOG the_dlg[] =
{
/* (dialog proc) (x) (y) (w) (h)
(fg) (bg) (key) (flags)
(d1) (d2) (dp)
(dp2) (dp3) */
{ my_slider_proc, 32, 32, 256, 16,
1, 0, 0, 0,
255, 0, NULL,
update_color, &colors[S_R] },
{ my_slider_proc, 48, 64, 256, 16,
2, 0, 0, 0,
255, 0, NULL,
update_color, &colors[S_G] },
{ my_slider_proc, 64, 96, 256, 16,
4, 0, 0, 0,
255, 0, NULL,
update_color, &colors[S_B] },
{ my_slider_proc, 320, 368, 256, 16,
255, 0, 0, 0,
255, 0, NULL,
update_color, &colors[S_H] },
{ my_slider_proc, 336, 400, 256, 16,
255, 0, 0, 0,
255, 0, NULL,
update_color, &colors[S_S] },
{ my_slider_proc, 352, 432, 256, 16,
255, 0, 0, 0,
255, 0, NULL,
update_color, &colors[S_V] },
{ d_text_proc, 300, 38, 0, 0,
255, 0, 0, 0,
0, 0, "R" },
{ d_text_proc, 316, 70, 0, 0,
255, 0, 0, 0,
0, 0, "G" },
{ d_text_proc, 332, 102, 0, 0,
255, 0, 0, 0,
0, 0, "B" },
{ d_text_proc, 302, 374, 0, 0,
255, 0, 0, 0,
0, 0, "H" },
{ d_text_proc, 318, 406, 0, 0,
255, 0, 0, 0,
0, 0, "S" },
{ d_text_proc, 334, 438, 0, 0,
255, 0, 0, 0,
0, 0, "V" },
{ NULL, 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, NULL }
};
Last, we have the main() function. It's a pretty simple one: it just initializes the library (checking that the screen mode was set properly--always do this!), clears the screen, and runs the main dialog. No sweat. int main()
{
allegro_init();
install_keyboard();
install_mouse();
install_timer();
if (set_gfx_mode(GFX_AUTODETECT,640,480,0,0)!=0) {
allegro_exit();
printf("Error setting graphics mode\n%s\n\n",
allegro_error);
return 1;
}
set_pallete(desktop_pallete);
clear(screen);
do_dialog(the_dlg, -1);
return 0;
}
Example 30 is a pretty easy example to follow. The only confusing thing involved is the odd way that the sliders keep track of which value they are supposed to modify. Once you have that under your belt, the rest is easy. Next: Other Allegro Documents |