Example 1: A Simple Non-modal Application
This simple application has two non-modal forms on the screen (MOU_MODAL is OFF) and we want the user to be able to switch between them by using the mouse. The first cut at the application might look as follows:
#include <vv_mouse.h>
#include <vv_str.h>
#include <vv_date.h>
#include <vv_des.h>
#include <vv_main.h>
#include "app1.h"
int main()
{
int retval;
FORM1 data1;
FORM2 data2;
DLIBPTR libp;
DFORMPTR fmp1, fmp2;
vv_init();
if (libp = dl_open("app1.vvd"))
{
fmp1 = dl_fmget("form1", &data1, NULLP, NULLP, libp);
fmp2 = dl_fmget("form2", &data2, NULLP, NULLP, libp);
dl_close(libp);
get_data_from_database(&data1, "Otterberg");
get_data_from_database(&data2, "Sullivan");
fm_up(fmp2);
retval = fm_proc(0, fmp1);
fm_dn(fmp2);
fm_free(fmp1);
fm_free(fmp2);
if (retval == AC_EXIT)
{
printf("Writing data to database.\n");
write_data_to_database(&data1);
write_data_to_database(&data2);
}
}
vv_exit();
return(0);
}
|
There are several problems with the above implementation. The user will be able to move between the two forms by using the mouse. However, the F10 and Esc keys will act slightly differently on the two forms.
If the user used the mouse to make fmp2 the active form, when he or she presses F10 or Esc, they are placed back in fmp1. The mouse can still be used to come back to fmp2. If the user is in fmp1 and presses F10 or Esc, fmp1 will be removed from the screen and they will be placed in fmp2.
This is because fm_proc() was called to start editing fmp1. When the processing function for fmp1 detects that the user is leaving because they pressed F10 or Esc, it will automatically take the form down because the form was automatically put up. The user is placed in fmp2 because that is the only other place to go. If the user now presses F10 or Esc while in fmp2, they will leave fmp2 and the call to fm_proc() will now return.
When the call to fm_proc() returns, fmp2 is still on the screen and fmp1 has been taken down. The return value from fm_proc() will be AC_EXIT (if the user pressed F10) or AC_QUIT (if the user pressed Esc). However, this return code applies to fmp2. You have no idea how the user exited from fmp1.
Therefore, the logic to determine when to write the data to the database is faulty. You may be writing data1 back to the database when the user actually pressed Esc for form fmp1.
There are three lessons to be learned from this first attempt:
- Any screen object that is automatically placed on the screen by Vermont Views code will automatically be removed from the screen by Vermont Views when the user exits or aborts. Suspending the current object by using the mouse to move to a new object will not cause the object to be removed from the screen. The functions fm_proc(), wn_proc(), cl_proc(), wn_browse(), and mf_browse() all have this behavior.
- The return value from a processing function only applies to the last screen object that was processed. In the above example, we can only determine how fmp2 was left. We have no idea how the user left fmp1. Furthermore, the application cannot identify the last screen object processed. fmp2 has to be the last object processed because there were only two forms on the screen and fmp1 will always be taken down first. However, if there were more than two forms, there would be no way to determine which was taken down last, and if this application were written correctly, the bug that allows you to determine that fmp1 was taken down first would not occur.
- When you exit or abort a non-modal screen object, Vermont Views will attempt to place you in another screen object. If there are no more screen objects on the screen, the original processing call will return.