Free Web Hosting by Netfirms
Web Hosting by Netfirms | Free Domain Names by Netfirms

 

T E X T   V E R S I O N

[a doctor]

Allegro GUI Clinic
Completing the Journey
 
  GUI Clinic Home
 
  What Else Can the GUI Subsystem Do?
Message Boxes | Graphics Mode Chooser Dialog | File Chooser Dialog
Concluding Remarks
 
 

Previous: Extending the System

What Else Can the GUI Subsystem Do?

Well, we're almost done. There are just a few miscellaneous things left to discuss. Much of this is paraphrased from the documentation.

extern DIALOG *active_dialog
This is a global pointer to the currently active dialog, or if there are no active dialogs, whatever dialog was most recently active. This can prove pretty useful in dialog procedures, in case an object needs to communicate with other objects in the same dialog.

extern MENU *active_menu
If a menu callback is executed, this variable will point to the menu item that caused it to run, so callbacks can determine where they were called from.

The GUI also provides a few helper functions that make life easier for its users. I'll just list them here:

int do_dialog(DIALOG *dialog, int focus_obj)
This is the main meat of the GUI. It displays the dialog on-screen and gives the focus to the focus_obj (pass -1 if you don't want any object to have the focus). The dialog will continue to run until one of the dialog procedures in the array tells the GUI manager to close the dialog. This function returns the index of the object that caused it to close.

int popup_dialog(DIALOG *dialog, int focus_obj)
This is almost exactly like do_dialog(), except that it stores the the background and restores it upon returning. It uses the first dialog object in the array to calculate the dimensions of the area to store, so make sure that all the other objects are inside it.

int broadcast_dialog(int msg, int c)
This sends the given message to all the objects in the current dialog. The "c" parameter is given to the dialog procedures, in case they will need it for something. It returns D_O_K, unless one of the objects in the dialog returns something else. In that case, that "something else" is returned.

int dialog_message(DIALOG *dialog, int msg, int c, int *obj)
This is just like broadcast_dialog(), only you can tell it which dialog to send the message to. The return value is the same as broadcast_dialog(), and in the event that it returns something other than D_O_K, obj will point to the index of the object that returned that value.

int gui_textout(BITMAP *bmp, unsigned char *s, int x, int y, int color, int center)
This is how the GUI objects print their text strings. This function is like textout(), except that '&' characters in the string are interpreted as meaning that the next character should be underlined. If "center" is TRUE, then the string will be centered about the x-coordinate. The return value is the width of the printed string in pixels.

int gui_strlen(unsigned char *s)
This function is like text_length(), only it always uses the font pointed to by the global "font" pointer. It ignores '&' characters, since they don't add to the length of the string. The return value is in pixels. This function may be useful for determining how large an object (or parts of an object) need to be. It's also helpful for aligning things.

void centre_dialog(DIALOG *dialog)
This moves every object in the given dialog around so that the dialog is centered on the screen. Note the British spelling of "centre."

void set_dialog_color(DIALOG *dialog, int fg, int bg)
This function changes the fg and bg colors for every object in the given dialog. This is really useful when you want to change the GUI's color scheme on-the-fly.

int find_dialog_focus(DIALOG *dialog)
This returns the index into the array of the object with the input focus. If no object has the focus, it returns -1. This is nice if you're displaying a dialog for the nth time and want to give the focus back to the object that had it last. To do that, you'd call do_dialog(the_dialog, find_dialog_focus(the_dialog)).

The following functions provide lower-level access to the GUI's dialog-playing functionality. You can use them if you want to integrate dialogs into your method of controlling your program.

DIALOG_PLAYER *init_dialog(DIALOG *dialog, int focus_obj)
This function initializes a dialog and returns a pointer to a player object that you can use with the next two functions.

int update_dialog(DIALOG_PLAYER *player)
This routine updates a dialog player object returned by init_dialog(). If the return value is TRUE, the dialog is active. If it returns FALSE, the dialog has requested that it be shut down. When this happens, you can see which object requested shutdown by looking at player->obj.

int shutdown_dialog(DIALOG_PLAYER *player)
This destroys a dialog player object created by init_dialog(). It returns the index of the object that caused the dialog to exit (just like with do_dialog()).

Using these functions, you can create your own dialog player. The documentation provides a simple example:

   int my_do_dialog(DIALOG *dialog, int focus_obj) {

      void *player = init_dialog(dialog, focus_obj);

      while (update_dialog(player))
         ;

      return shutdown_dialog(player);
   }

A few helper functions are cool enough to merit their own discussions. They are the message boxes, the graphics mode chooser, and the file selector.

Message Boxes

All GUIs support some sort of message boxes, and Allegro's GUI isn't any different. There are two functions for providing feedback or getting user input via message boxes.

int alert(char *s1, *s2, *s3, *b1, *b2, int c1, c2)
This is the normal message box. It can contain up to three lines of text, given in s1, s2, and s3 (any of which may be NULL). Make sure these lines aren't too long, or the dialog will look really strange! The b1 and b2 parameters hold the text captions for the two buttons (if b2 is NULL, then there will only be one button). The c1 and c2 parameters contain the buttons' optional keyboard shortcuts. This function returns 1 or 2, depending on which button was clicked. If the Escape key isn't a keyboard shorcut, then it is treated as a click on button 2 (like for the common "OK, Cancel" dialog) if it is pressed.

int alert3(char *s1, *s2, *s3, *b1, *b2, *b3, int c1, c2)
This is just like alert() above, except that it has three buttons, and returns 1, 2, or 3.

For example, say you're trying to access a file, but it isn't found. You could do something like the following:

   sprintf(err_msg, "Error opening %s!", file_name);

   ret = alert(err_msg, "What will you do?", NULL,
               "Abort", "Retry", 0, 0);

   if (ret == 1)
      do_abort();
   else
      do_retry();

These dialogs aren't too flexible. Their main fault is that they can only display three lines of text at most. If you really find that lacking, you can always create your own.

Graphics Mode Chooser Dialog

Allegro supports many different video resolutions and color depths. Often, it is practicle to let the user choose what video mode a program should run in. Creating a dialog full of all the possible choices would be rather daunting. Thankfully, Allegro comes with a prepackaged mode-selection dialog.

int gfx_mode_select(int *card, int *w, int *h)
int gfx_mode_select_ex(int *card, int *w, int *h, int *color_depth)

These two routines display the video mode selection dialog. When it returns, the parameters will be filled with the graphics card, resolution, and for gfx_mode_select_ex(), the color depth. They return zero if the user closed it with Cancel; if the user pressed OK, it returns non-zero.

The gfx_mode_select_ex() function reads the parameters when it initializes, so you can suggest default values if you like.

Here's an example:

   int c, w, h, depth;
   int ret, mode_failure;

   /* supply defaults */
   c = GFX_AUTODETECT;
   w = 800;
   h = 600;
   depth = 24;

   /* ask the user */
   ret = gfx_mode_select_ex(&c, &w, &h, &depth);

   if (ret) {

      /* try to set the mode */
      set_color_depth(depth);
      mode_failure = set_gfx_mode(c, w, h, 0, 0);

      /* if it didn't work */
      if (mode_failure) {
         allegro_exit();
         fprintf(stderr, "Couldn't set mode: %s",
                         allegro_error);
         exit(1);
      }
   }

Make sure you always check the return value from these functions (and set_gfx_mode() as well)!

File Chooser Dialog

Finally, we come to the file chooser dialog. This provides an easy way for Allegro programs to provide file names for loading or saving files.

int file_select(char *message, char *path, char *ext)
Calling this function displays the selector. The dialog caption is given in the "message" parameter. The starting path is provided in "path," and the files are filtered according to the contents of the "ext" string. If ext is NULL, then the dialog shows all files. If you want to show only certain files, pass the extensions of the files you want to show, separated by semicolons. It returns zero if the user pressed Cancel, and non-zero if the user pressed OK.

The filename chosen is returned in the path string, so there had better be enough room. Make it at least 80 characters long.

Here's an example:

   char path[] = "c:/djgpp/allegro/examples";

   /* show only .PCX, .BMP, and .TGA files */
   ret = file_select("Save As...", path, "PCX;BMP;TGA");

   if (ret)
      save_file(path);
   else
      do_not_save_file();

One of the main problems with this (and the gfx_mode_select dialog) is that it only uses the default Allegro GUI objects. There is currently no way to hook into the dialogs and change their appearances, aside from chopping the code out of the Allegro source and using your own GUI objects.

Concluding Remarks

Well, you've survivied the tutorial. I hope it wasn't too boring and verbose.

I started out with the idea that this would be a real "clinic" of sorts. Hence the name of the tutorial. But, I never got around to giving Doctor Inanis a voice, and he pretty much ended up on the title page and stayed there. He never did anything. I suppose he's like the Beatles' Sergeant Pepper that way. Oh, well. I like his picture.

If you have any questions, comments, suggestions, or the like, please contact me.

The tutorial in earnest is over, but as a bonus, I've take the three GUI examples from the Allegro distribution and annotated them. Sometimes, just having the source in front of you isn't enough. Hopefully, these appendices will make things clearer.

Again, thanks for reading, and Happy Programming!

Next: Annotated Example 13

 

About this site

The Allegro GUI Clinic is © 1998 Revin Guillen