Here you find some very simple programs on how you can use the XForms library. This isn't meant as real world examples (or as a tutorial) but just should demonstrate "how it works" in principle.
The following short program opens up a window that contains a single button with the label "Hello world". If you click on the button the window gets closed again and the program ends (as I warned you, it's a very sinple program;-)
#include <forms.h> int main(int argc, char **argv) { FL_FORM *form; fl_initialize(&argc, argv, 0, 0, 0); form = fl_bgn_form(FL_UP_BOX, 230, 100); fl_add_button(FL_NORMAL_BUTTON, 20, 20, 190, 60, "Hello world"); fl_end_form(); fl_show_form(form, FL_PLACE_MOUSE, FL_FULLBORDER, "Hello, world!"); fl_do_forms(); fl_hide_form(form); fl_finish(); return 0; }
The first function called in the program, fl_initialize()
,
initializes the XForms library (and extracts command line arguments
meant for XForms). That out of the way a "form" is defined (which
ofter corresponds to a window to be shown) and populates it with a
single button. Once the form is defined it gets drawn on the screen
with a call of fl_show_form()
.
Now follows the main loop of the program in which we wait for
something the user does. This happens in the function
fl_do_forms()
. Since this is a very simple program
not much can happen - the only thing the user can do is to click on
the button. If that happens the function returns and the program
ends after closing the window.
(Please note: the borders around the window may look a bit different on your system from what's shown in the picture above - they aren't created by XForms but by the window manager, a program running in the background which, beside other things, puts "decorations" around the windows of other programs. How these decorations look like thus depends on the window manager being used.)
Because it gets a bit boring to have just a single button that doesn't do anything else than ending the program here's a slightly more complicated example, featuring two buttons:
#include <stdio.h> #include <forms.h> int main(int argc, char **argv) { FL_FORM *form; FL_OBJECT *obj; fl_initialize(&argc, argv, 0, 0, 0); form = fl_bgn_form(FL_UP_BOX, 230, 180); obj = fl_add_button(FL_NORMAL_BUTTON, 20, 20, 190, 60, "Hello world"); fl_add_button(FL_NORMAL_BUTTON, 70, 100, 90, 60, "Quit"); fl_end_form(); fl_show_form(form, FL_PLACE_MOUSE, FL_FULLBORDER, "Hello, world!"); while (fl_do_forms() == obj) printf("Hello world\n"); fl_finish(); return 0; }
As it's easy to see the main differences are that instead of one
button two are generated and that the return value of
fl_do_forms()
is used. The program also demonstrates that
the function for adding a button, fl_add_button()
, does
return something useful, a pointer to a structure of type
FL_OBJECT
. All objects in a GUI you create with XForms
are of this type and uniquely identify the object.
This is now used in the main loop of the program.
fl_do_forms()
returns a pointer to the object that was
clicked on by the user. If it was the button with the label "Hello word"
now the string "Hello world\n"
is printed to standard
output and the loop is restarted. Only if the button labeled "Quit" is
pressed the loop and thus the program ends.
While this program is still extremely simple, it demonstrates nicely the typical way programs with a graphical user interface are written: after creating the GUI they go into a loop in which they wait for user interactions, doing some specific work for each event initiated by the user.
If you have more than a very small number of objects comparing them to
what fl_do_forms()
returns each time becomes quite tedious
(and your program would probably look rather horrible). Thus there's a
more powerful mechanism to tell XForms to execute some code on an event
for an object, callbacks. Lets rewrite the above program using a
callback for the first button.
#include <stdio.h> #include <forms.h> static void button_cb(FL_OBJECT *obj, long data) { printf("Hello world\n"); } int main(int argc, char **argv) { FL_FORM *form; FL_OBJECT *obj; fl_initialize(&argc, argv, 0, 0, 0); form = fl_bgn_form(FL_UP_BOX, 230, 180); obj = fl_add_button(FL_NORMAL_BUTTON, 20, 20, 190, 60, "Hello world"); fl_set_object_callback(obj, button_cb, 0); fl_add_button(FL_NORMAL_BUTTON, 70, 100, 90, 60, "Quit"); fl_end_form(); fl_show_form(form, FL_PLACE_MOUSE, FL_FULLBORDER, "Hello, world!"); fl_do_forms(); fl_do_forms(); return 0; }
This program behaves exactly as the previous one (and its window looks
the same, too). But instead of analyzing the return value
of fl_do_forms()
we now make sure
that fl_do_forms()
won't return when the first
button is pressed. Instead we have created a
function, button_cb()
, to be called when this button is
pressed and, by using fl_set_object_callback()
, associated
it with the object for the first button. This takes care of making
XForms call our function button_cb()
whenever this button
is pressed. Thus fl_do_forms()
will only return when the
second button, labeled "Quit", gets pressed.
(When you look at the callback function you will notice that it has
two arguments (which aren't used in this example). The first one is
a pointer to the object the callback function is invoked for and the
second one is additional data that can be set in
fl_set_object_callback()
(as its final argument). Thus a
single callback function can be used for more than one object.)
The exact method for compiling these programs may depend a bit on the system you are using. Thus here we can only show how it's done one UNIX-like systems. If the XForms library has been installed all you should need is a single command like
cc -o xftest xftest.c -lforms -lX11
This, of course, assumes that you have stored the code of the example
program in a file called xftest.c
.
While we have only used buttons in the above examples (and then only a single type of button, but XForms comes with 9 different types of them) there are, of course, a lot more types of objects. The most simple ones are static objects like boxes, frames, text objects, bit- and pixmaps, (analog and digital) clocks and objects for displaying charts (like pie charts etc.), most of them coming with a number of sub-types.
Then there are objects that allow the user to adjust values, like sliders, scrollbars, dials, counters, thumbwheels and more. To be able to enter texts, numbers or dates there are several different input objects. If you want the user to select one out of several alternatives you can use select, menu and popup objects. Then there are also browser objects in which you can display text or whole files (scrollable if necessary) and the user can select single or multiple lines. Further, there are also so-called "container" objects, e.g. tab folders, into which you can put several forms and the user can select which form (s)he wants to work with by selecting it via tab riders at the top. And, of course, there's also a canvas object, i.e. an object into which you draw freely whatever you want. And if that's still not enough there's support writing your own objects to do something which isn't implemented yet.
And, of course, for very common tasks there are the so-called "goodies". They include file selectors, boxes for messages or selections between up to three alternatives.
Got curious? Go straight to the documentation of the XForms library.
Last modified: January 6, 2014 by Jens Thoms Törring |