|
|
| How can I detect when a user clicks on a bitmap? |
|
starkiller53861
Member #11,739
March 2010
|
Hi, I'm trying to create a menu for a game. I used have loaded my various bitmaps (buttons for start, instructions, exit, etc.) with little trouble. However, I am unsure how to detect when the user clicks on the button (the bitmap) and execute a function based on that. For example, when the user clicks on the exit button, the program will exit. I achieved this previously by simple telling the user to press the escape key, thus: At the moment, the best I can do is get the game to exit when the user clicks the mouse anywhere on the screen, which isn't much help. Thanks, starkiller53861 |
|
Tomoso
Member #3,128
January 2003
|
You need to check where the mouse cursor is, and whether or not the correct button was pressed. You should also keep track of the location of your bitmap so you can use something like this. That code might be wrong, I haven't used 4.2 in a few months. You could also split this into separate functions like bool mouse_in_area(int left, int top, int right, int bottom); etc... Lazy Noob - Blog |
|
Johan Halmén
Member #1,550
September 2001
|
starkiller53861 said: I'm trying to create a menu for a game. Think carefully if you want to do everything from scratch. It might be fun to actually code each thing involved in the user interface. Personally I prefer to use a gui library. That way you take parts of the developing to a higher level and leave the essential fun stuff (like the gameplay) to a lower level of programming. Allegro's own gui is quite good for most needs. But there are better libraries, too. like MasKing. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
Striker
Member #10,701
February 2009
|
Look at the example program exgui. The Allegro GUI is useful, but at some points it is not very easy to get a reaction when the user clicks on that item. For the button there is a derived object "My_Button_proc" to execute a function when the button is clicked. Similar with other GUI objects, like radio buttons. There are no examples how to execute a function when the states of radio buttons have changed. To really use the Allegro GUI it is necessary to fully understand its function, so that you can create derived procs of your own. I did so with a few objects. Dropdownlist and counter object. But there are still some to do. Like an input edit field with more than one line. One thing really helpful ist the Allegro GUI Clinic. There is a basic dropdown list and a clock described. To fit it to your needs you need enhancements of your own. Unfortunally it seems most people think the Allegro GUI is dead and dont want to improve it anymore. But with extensions like AGUP and some own objects you can really get a nice little user interface with it! And for your special problem: how about the bitmap or icon object? You can create a derived object and use msg_click to detect if the object was clicked.
|
|
Timorg
Member #2,028
March 2002
|
The allegro GUI is good for basic buttons and general option setting. But you would be amazed what you can get the allegro GUI to do, just need to know what you are doing, some patience, (and a little beer doesn't hurt.) Here is a List of high scores with multiple columns. Actually looking back at that code, it really does feel like I am just abusing the GUI code for the sake of it. I would suggest starting with the GUI clinic, then come back if you have any questions about it. Striker said: There are no examples how to execute a function when the states of radio buttons have changed I whipped up an example for you 1#include <allegro.h>
2
3
4/* The message that is broadcast when a custom radio button is clicked */
5#define MSG_RADIO_CHANGE MSG_USER
6
7
8/* function prototypes - see below */
9DIALOG *search_dialog(DIALOG *d, int (*proc)(int, DIALOG *, int), int flag);
10void clear_information();
11
12
13/*
14 This is just a classic radio button, inherited so that a click will also
15 broadcast a message to trigger another proc.
16
17 You can supply a function pointer in d2, that is called when this radio
18 button becomes selected. If the button is already selected, this function
19 is not called.
20*/
21int d_custom_radio_proc(int msg, DIALOG *d, int c)
22{
23 int rval = d_radio_proc(msg, d, c);
24 if (msg == MSG_CLICK)
25 {
26 broadcast_dialog_message(MSG_RADIO_CHANGE, d->d1);
27 }
28 return rval;
29}
30
31/*
32 This is a proc the monitors changes in a radio button group. When a button
33 in the group is pressed, the function in d->dp is called. It locates the
34 currently selected button in that group, if that button is a new selection,
35 (as opposed to the currently selected), it calls the function that is pointed
36 to in that buttons dp2 field.
37*/
38int d_radio_change_proc(int msg, DIALOG *d, int c)
39{
40 /* Check if this is the only message that we are interested in */
41 if (msg == MSG_RADIO_CHANGE)
42 {
43 /* check if this group is relevent to us */
44 if (c == d->d1)
45 {
46 /* if there is a function pointer available for the group, call it */
47 if (d->dp != NULL)
48 {
49 (( void (*)() )d->dp)();
50 }
51
52 /*
53 search the active dialog for the selected radio button in our current group
54 if the end of dialog is reached and we didn't find it, exit the function.
55 */
56 DIALOG *found = search_dialog(active_dialog, d_custom_radio_proc, D_SELECTED);
57 if (found == NULL)
58 return D_O_K;
59
60 while (found->d1 != d->d1)
61 {
62 /*
63 if a selected radio button is found, and isnt the right group,
64 continue looking from the next dialog in the array
65 */
66
67 found = search_dialog(found + 1, d_custom_radio_proc, D_SELECTED);
68 if (found == NULL)
69 return D_O_K;
70 }
71
72 /* check if this is a new selection, or the same as the old one */
73 if (found != d->dp2)
74 {
75 /* call the callback function, if one is available */
76 d->dp2 = found;
77 if (found->dp2 != NULL)
78 {
79 (( void (*)() )found->dp2)();
80 }
81 }
82 else
83 {
84 /*
85 if this is the same button as before, clear the outputted callback text
86 (this could be changed to call a callback in found->dp3 if you want to
87 deal with multiple clicks on a single radio button.
88 eg.
89 if (found->dp3 != NULL)
90 {
91 (( void (*)() )found->dp3)();
92 }
93 */
94 clear_information();
95 }
96 }
97 }
98 return D_O_K;
99}
100
101/*
102 This function searches the provided dialog, searching for one that
103 matches the supplied proc, and has the supplied flag set.
104*/
105DIALOG *search_dialog(DIALOG *d, int (*proc)(int, DIALOG *, int), int flag)
106{
107
108 while (d->proc != NULL)
109 {
110 if (d->proc == proc)
111 {
112 if (d->flags & flag)
113 {
114 return d;
115 }
116 }
117 d++;
118 }
119 return NULL;
120}
121
122
123/* call backs for the groups - displays information about the last click */
124void group1() {textprintf_ex(screen, font, 20, 230, makecol(255,0,0), makecol(255, 255, 255), "you clicked radio group 1"); }
125void group2() {textprintf_ex(screen, font, 20, 230, makecol(0,255,0), makecol(255, 255, 255), "you clicked radio group 2"); }
126void click1() {textprintf_ex(screen, font, 20, 240, makecol(255,0,0), makecol(255, 255, 255), "you clicked radio button 1"); }
127void click2() {textprintf_ex(screen, font, 20, 240, makecol(0,255,0), makecol(255, 255, 255), "you clicked radio button 2"); }
128void click3() {textprintf_ex(screen, font, 20, 240, makecol(0,255,0), makecol(255, 255, 255), "you clicked radio button 3"); }
129void clickA() {textprintf_ex(screen, font, 20, 240, makecol(255,0,0), makecol(255, 255, 255), "you clicked radio button A"); }
130void clickB() {textprintf_ex(screen, font, 20, 240, makecol(0,255,0), makecol(255, 255, 255), "you clicked radio button B"); }
131void clickC() {textprintf_ex(screen, font, 20, 240, makecol(0,255,0), makecol(255, 255, 255), "you clicked radio button C"); }
132
133/* clears the displayed information */
134void clear_information()
135{
136 textprintf_ex(screen, font, 20, 230, makecol(255,0,0), makecol(255, 255, 255), " ");
137 textprintf_ex(screen, font, 20, 240, makecol( 0,0,0), makecol(255, 255, 255), " ");
138}
139
140
141DIALOG the_dialog[] =
142{
143 /* (dialog proc) (x) (y) (w) (h) (fg)(bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */
144 { d_clear_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
145 { d_button_proc, 10, 10, 70, 15, 0, 0, 0, D_CLOSE, 0, 0, "Quit", NULL, NULL },
146 { d_custom_radio_proc, 20, 35, 70, 10, 0, 0, 0, 0, 1, 0, "Radio 1", click1, NULL },
147 { d_custom_radio_proc, 20, 50, 70, 10, 0, 0, 0, 0, 1, 0, "Radio 2", click2, NULL },
148 { d_custom_radio_proc, 20, 65, 70, 10, 0, 0, 0, 0, 1, 0, "Radio 3", click3, NULL },
149 { d_radio_change_proc, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, group1, NULL, NULL },
150 { d_custom_radio_proc, 120, 35, 70, 10, 0, 0, 0, 0, 2, 0, "Radio A", clickA, NULL },
151 { d_custom_radio_proc, 120, 50, 70, 10, 0, 0, 0, 0, 2, 0, "Radio B", clickB, NULL },
152 { d_custom_radio_proc, 120, 65, 70, 10, 0, 0, 0, 0, 2, 0, "Radio C", clickC, NULL },
153 { d_radio_change_proc, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, group2, NULL, NULL },
154 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
155};
156
157
158int main()
159{
160 allegro_init();
161 install_keyboard();
162 install_mouse();
163
164 set_color_depth(32);
165 set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
166
167 set_dialog_color(the_dialog, makecol(0, 0, 0), makecol(255,255,255));
168 do_dialog(the_dialog, -1);
169
170 return 0;
171}
172END_OF_MAIN()
I really do enjoy coming up with over-engineered custom widgets. I hope the more solid GUI lib(s) that come out for A5 are as easy to extend the functionality in arbitrary ways like this current A4 one. ____________________________________________________________________________________________ |
|
Johan Halmén
Member #1,550
September 2001
|
Striker said: There are no examples how to execute a function when the states of radio buttons have changed. This is how I do most of the modifying of the procs. I do my own proc and inside it I call the proc that I'm modifying, saving the return value. before the call and after the call I do necessary things for my modification. On line 6 I check the state of the radio button. On line 7 I do the normal radio button call (which will do the initializing, drawing, click handling, whatnot). On line 8 I do what I want, depending on what happened. On line 12 I return what would have been returned if this was a normal radio button. 1int my_radio_proc(int msg, DIALOG *d, int c)
2{
3 int ret;
4 int state;
5
6 state = d->flags & D_SELECTED;
7 ret = d_radio_proc(msg, d, c);
8 if (state == (d->flags & D_SELECTED))
9 {
10 // execute your callback here
11 }
12 return ret;
13}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
Striker
Member #10,701
February 2009
|
Thanks a lot, i will look at the code in the evening. One thing: the examples from GUI Clinic both have a mistake. I will look for the corrected and enhanced versions and post them. The dropdownbox needs this enhancement to be useful, because it doesnt restore the part that was under the dropdown part when it disappears. Naturally it is useless when it destroys parts of the screen... I think it would be really nice to have the old Allegro GUI - with some enhancements and more documentation - as part of further Allegro versions. I like the docs in the style Shawn did it in Allegro.chm from 4.22. There were useful explanations, diagrams and examples, and i think that made a lot of Allegros success, that its a fun and not too difficult library! EDIT: I cant post in this thread now, examples are here:
|
|
|