[AD] A possibly useful variation on d_keyboard_proc

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


I needed to use a function key as a shortcut in my GUI, but apparently shortcuts are only handled as ASCII codes.

d_keyboard_proc accepts scancodes, but I didn't want to write a wrapper function for every new shortcut. So I wrote this function, which is similar to d_keyboard_proc except that instead of calling a function (pointed to by dp), it sends a MSG_KEY to a DIALOG (pointed to by dp). Put differently, it's an invisible object that forwards keypresses corresponding to its shortcut or to a scancode (in d1 or d2) to the DIALOG pointed to by dp.

Additionally, this function allows using multiple shortcuts for the same DIALOG easily. Not that I would recommend that kind of design though.

The code for an example is at the end of this message. Adding the function to Allegro would just be a matter of copying d_keyboard_forward_proc into allegro/guiproc.c, and the prototype to gui.h.

Maybe there's already some way to do the same thing but I didn't found one although I read the docs thoroughly. Why aren't scancodes supported as shortcuts? As DIALOG.key is an int, we could store a scancode in addition to the ASCII code using the readkey() format. This would be better than nothing and shouldn't break compatibility, except where reading shortcuts from DIALOGs is involved, which shouldn't happen often. What do you think?

There is a problem with my function though. Not all keys will work. Function keys, cursor keys, "extra cursor keys", numpad keys, esc, tab, enter and print screen work, but shifts, controls, alts, windows, caps lock, pause and scroll lock don't. I have no idea why, but I don't know if it's worth examining the issue.

PS I'm not subscribed to this list but I will watch this space for any follow-ups of course.



#include <allegro.h>

// This is the interesting function.
// The code is very similar to d_keyboard_proc in allegro/guiproc.c.
// I retained the same coding style for this function.
int d_keyboard_forward_proc(int msg, DIALOG *d, int c)
{
  int ret = D_O_K;
  switch (msg) {

     case MSG_START:
	 d->w = d->h = 0;
	 break;

     case MSG_XCHAR:
	 if (((c>>8) != d->d1) && ((c>>8) != d->d2))
	    break;

	 ret |= D_USED_CHAR;
	 /* fall through */

     case MSG_KEY:
	 ret |= object_message((DIALOG*) (d->dp), MSG_KEY, 0);
	 break;
  }

  return ret;
}

void menu_play() {
	DIALOG widgets[8];

widgets[0] = (DIALOG) {d_clear_proc, 0, 0, SCREEN_W, SCREEN_H, 0, 255, 0, 0, 0, 0, NULL, NULL, NULL}; widgets[1] = (DIALOG) {d_check_proc, 0, 0, SCREEN_W, 32, 0, 255, 'C', 0, 1, 0, "&Checkbox (F1)", NULL, NULL}; widgets[2] = (DIALOG) {d_button_proc, 0, 32, SCREEN_W, 32, 0, 255, 'B', 0, 0, 0, "&Button (F2 or home)", NULL, NULL}; widgets[3] = (DIALOG) {d_button_proc, 0, 64, SCREEN_W, 32, 0, 255, 'X', D_EXIT, 0, 0, "E&XIT", NULL, NULL}; widgets[4] = (DIALOG) {d_keyboard_forward_proc, 0, 0, 0, 0, 0, 255, 0, 0, KEY_F1, 0, &widgets[1], NULL, NULL}; widgets[5] = (DIALOG) {d_keyboard_forward_proc, 0, 0, 0, 0, 0, 255, 0, 0, KEY_F2, KEY_HOME, &widgets[2], NULL, NULL};
	widgets[6] = (DIALOG) {d_yield_proc};
	widgets[7] = (DIALOG) {NULL};

	popup_dialog(widgets, -1);
}

int main() {
	allegro_init();
	install_keyboard();
	install_mouse();
	if (set_gfx_mode(GFX_SAFE, 640, 480, 0, 0)) {
		allegro_message("Error; set_gfx_mode");
		return 1;
	}

	menu_play();

	return 0;
}
END_OF_MAIN();

_________________________________________________________________
Bloquez les fenêtres pop-up, c'est gratuit ! http://toolbar.msn.fr





Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/