The Main Screen


So that we can add options like "Create exam," "Modify exam," "Run reports ," and so forth sometime later, let's add another button: Administration . And while we're at it, let's change the ENTER button to EXAMS :

graphics/13fig74.gif

I know you'll want to run your creation from a shortcut. Here's how you do it: Create a shortcut, and then enter "D:\GUERRILLA_ORACLE\CWE1P_MAIN .fmx" in the Target field and "D:\GUERRILLA_ORACLE" in the Start in field:

graphics/13fig75.gif

The icon probably won't work because your system does not have a program associated with .fmx files, so you'll have to make the connection.

You'll find the executable (IFRUN60.EXE) in the ORACLE_HOME/ORANT/BIN directory. Make the association (and make it permanent ), and off you go!

Calling Forms from Forms

Now we'll learn how to call forms from forms. This is actually how systems are done: The user clicks on a button that triggers events that usually bring the user to another form.

We want our users to be able to do two things from the main form: exit or take a test. When a user clicks on the EXAMS button, the next screen has to be the user ID screen, where we check that the user is a valid user, and we prompt the user to select an exam. We also check whether the user has already taken that exam, and if so, prevent the user from going any further. If the user can take the exam, the next screen will be the warning that once the test has started, the user will be logged as having taken the exam, so this is the last chance to decide not to take the test.

If a user decides to take the test, the user record is updated and the exam questions are displayed. At the end the user hits the FINISHED (Exit) button, and the system calculates and displays the results, and then closes the test.

Using the Forms

Now we need to build the next set of forms and learn how to do some editing. Then I'll tie the whole thing together.

Our users can do three things from the main form: exit, do administrative tasks , or take the exams. Let's start with the sign-in screen for taking a test, which will be the first one the user will see after clicking on EXAMS . Remember that the forms we've worked with so far have been data block forms , where each form was related directly to one table. From here on, we'll be working with unique forms , where the data will be drawn from as many tables as needed and then manipulated through various SQL commands. A form that grabs data from more than one table is called a control form , and that's what we'll be working with next.

It's going to get interesting. I hope you realize by now that I'm taking you a step at a time into the rather intricate world of Forms. By now you have a good handle on using the wizard, and you should be comfortable with some of the basics of Object Navigator, so you're ready for another big step.

After deciding to take an exam, the user's next step is to choose a test. Here's what we're going to build next:

graphics/13fig76.gif

Hitting F9 with the cursor in the Test ID box brings up a list of available tests, and the user can select one of them:

graphics/13fig77.gif

Building a Control Form

Note

Here is the overall sequence we'll follow to build a control form:

  1. Build a new form.

  2. Create the control block.

  3. Have fun with Layout Editor!


To build a control form, start another Form Builder session. Next go through the following steps:

  1. Click on FILE NEW FORM or highlight FORM and click on the green plus sign.

  2. Rename the form from "MODULE1" to "CWE1P_SELECT_TEST".

  3. Save the form in your CWE1P_PROJECT folder. You now have another .fmb record!

  4. Click on View , and then Visual View .

  5. Click on the plus sign next to WINDOWS to open the drop-down list. Now change the name of the default window to "CWE1P_SELECT_TEST_WINDOW".

  6. Click on CANVAS and then the green plus sign to make a new canvas, and then rename it "CWE1P_SELECT_TEST_CANVAS".

  7. Change the CWE1P_SELECT_TEST_WINDOWproperties: Right-click on the window, select Property Palette , change the name to "GUERRILLA EXAMS", the resize and max size options to "No", the width to 580, and the height to 375.

  8. Go back to the canvas, select Property Palette , and change the width and height to match the window.

  9. Now make the control block itself, by selecting View and then Ownership View .

  10. Select Data Blocks under your new form: CWE1P_SELECT_TEST_FORM (make sure you're in the right form!).

  11. Click on the green plus sign to create a new block, select the manual option, and then change the name to "CWE1P_SELECT_TEST_BLOCK". Note that this block is not tied to any particular table.

  12. Now right-click on your new block, and select Layout Editor .

You should now be at this screen:

graphics/13fig78.gif

Building Screen Items

We're going to use some of the fantastic editing features to build the screen items, and then I'll show you how to create a list of values (LOV) so that the user can select the right exam.

Message Box

First select the giant T , and put the cursor somewhere at the top of the screen in the middle. You will see a small rectangular box. Change the font size to 18, and type in "Please Select an Exam". Your screen should look something like this:

graphics/13fig79.gif

Now click on the text you have just typed in ("Please Select an Exam") until you see the black marks around it. Notice that at the very bottom of the tool palette on the left side of the screen are three colorful icons. If you put your cursor on them, the names Fill Color for the paint bucket, Line Color for the paintbrush, and Text Color for the "Aa" icon will appear. Right-click on the paint bucket, and change the color to white:

graphics/13fig80.gif

If you don't like white, then change it to any color that appeals to you. Just have some fun!

Data

Now we'll add the data fields. Change the font size back to 8, and then select the "abc" text item icon from the left side, and create three boxes. Then right-click on each box, select Property Palette , and make the following changes (you will have to scroll pretty far down to find the Prompt selection):

graphics/13fig81.jpg

What you have now done is tell Forms 6 i that the boxes will be getting their data from fields from various tables. How do we get that data? First we'll let the system do it for us, by using a list of values. Then we'll return to the property palette for the three boxes we just created and we'll tell each box where to find its data.

To create a list of values (LOV), select Tools LOV Wizard , and then New Record Group based on a query :

graphics/13fig82.gif

Connect to the database and type in the SQL query statement shown here:

graphics/13fig83.gif

Click the Check Syntax... box, and you should see this message:

graphics/13fig84.gif

Click OK , select all three columns , and then fill in the Return value column:

  1. Click on the first Return value box, for the column named Test_ID.

  2. Click on the Look up return item box.

  3. Select the correct column from the list ( CWE1P_SELECT_TEST_BLOCK. TEST_ID ), and it will pop into the Return value column.

  4. Repeat steps 1 through 3 for the other two items ( TEST_NAME and TYPE_DESC ).

graphics/13fig85.gif

graphics/13fig86.gif

You have just told Forms 6 i to return the data from these columns into these boxes on your new screen. Just make sure you match the fields, or the results will be confusing! Forms 6 i will put the data where you tell it, so be careful.

Click Next , give your form the title "Available Tests", and then accept the 20-row default for retrieval of the data:

graphics/13fig87.gif

graphics/13fig88.gif

Lists of Values

Now we come to the LOV Wizard. It wants to know which item or items will have an LOV (list of values). Since we're going to give the test takers the ability to select a test, obviously we will want the list of values to be active for only the first selection, TEST_ID . So select only the TEST_ID column, and click Finish :

graphics/13fig89.gif

graphics/13fig90.gif

Now for the big test: running your new form. To do this, as you probably know by now, just select Program Run Forms Client/Server . And this is what you should see after you put the cursor in the Test ID box and hit F9 :

graphics/13fig91.gif

Now go have some fun. Return to Layout Editor. Right-click anywhere on your screen except in a text box, select Property Palette , and change the colors to anything you like. Do the same with the boxes: Go into the property palette and change some of the attributes to see what happens. Add a couple of buttons Continue , EXIT , whatever you feel like. Just remember to periodically save your work. As you experiment, you will see how easy it is to correct mistakes. If you do end up with several conflicting lists of values, go to Object Navigator and delete them. Then just make a new LOV!

Congratulations! You have built another form. If you want, go back to SQL and add another test or two so that you can see that the list of values really works. Or if you're really ambitious, and we encourage thiscreate a quick and dirty form to enter new tests. You can probably make such a quick and dirty form in a matter of minutes now.

Triggers

Now I'm going to push you to take a rather big step. What I will have you do in the next series of instructions is modify what you've done so that it looks like this:

graphics/13fig92.jpg

All we're going to do is add a few more fields at the top, add what's called a trigger function , and move the items around a bit. It's not as hard as it seems! The purpose is to check for a valid ID before letting someone register for a test. In other words, if you are not in the database, you cannot take an exam, and you will get an error (shown in the lower-left corner) if your ID is not valid. Here are the steps:

  1. Move the existing items to the bottom of the screen to make space at the top. Then add a couple of new items at the top:

  2. Create four new text items, for user ID, first name, middle initial, and last name; a text field that says, "1. Please enter your ID, then click Sign In"; and a new button labeled Sign In . You should know how to do this.

  3. Arrange the parts into a symmetrical, eye-pleasing layout.

  4. Make the necessary changes to the property palette for each of the items:

    graphics/13fig93.jpg

Table 1..

Item

Name

Size

Prompt

User_ID

User_ID

9, NUMBER

Enter your user ID:

First_Name

First_Name

15, CHAR

no prompt

MI

MI

1, CHAR

no prompt

Last_Name

Last_Name

20, CHAR

no prompt

For example, here's the property palette for User_ID:

graphics/13fig94.gif

graphics/13fig95.gif

graphics/13fig96.gif

Now that you have added the text items, have changed the label names in Property Palette , and have played around with sizes and positions , you are ready to take action. Just right-click on the Sign In button, select SmartTriggers

WHEN-BUTTON-PRESSED , and enter this code:

 select f_name, M_I, L_Name into :cwe1p_select_test_block.first_name,  :cwe1p_select_test_block.MI, graphics/1_icon.gif :cwe1p_select_test_block.last_name  from students  where students.student_id :cwe1p_select_test_block.user_id; graphics/2_icon.gif 

(1) Important: The names you use here have to match the names you put into the property palette for each item. For example, we called the middle-initial box "MI" in the property palette.

(2) A colon is needed in front of the block name.

You also have to go back to Object Navigator and change the name of the button you just created. Just click on it and change it to "Sign_In":

graphics/13fig97.jpg

graphics/13fig98.gif

This is the type of error you get when your names do not match what you put into the property palette:

graphics/13fig99.gif

When you're done, click on Compile , clean up any errors (you will have spelling errors), and then hit CLOSE . OK, you're probably asking, where did these funny names come from?

If you go back to your friend Object Navigator, you will see your data block and the names of the items that you just created. Your names may be different from what is shown, but that's OK. Note that you should move the USER_ID item to the top of the items list so that the cursor defaults there when the screen opens:

graphics/13fig100.gif

Note

Working with Forms is complex but very rewarding ! Just stick with it, and you'll get it eventually. As I've said already, you will have many, many errors, most of the time as a result of syntax problems. Be patient.

I'm trying to give you some experience with the major parts of Forms in this chapter, and you're about halfway there. Don't give up!


Let's move on and finish this screen. The next step is to test, so select Program Compile Client/Server . Now enter an ID, hit the Sign In button, and see what happens. If the ID is not nine digits long, you should get an error message in the lower left-hand corner telling you that the field is not completely filled. If the ID is not valid, you should see an error referring to an "unhandled exception," followed by an "ORA-xxx" error message:

graphics/13fig101.gif

graphics/13fig102.gif

Note

You're rightour original design had the students create their own record. However, the specs have changed, and the director now wants only those already in the database to be able to take the test. Good eyes for those who caught this change! This is how the real world operates.


OK, I tricked you a bit. Now you have to go back to SQL*Plus and enter a couple of valid users, some tests, questions, and so forth. This should be easy for you now. If it isn't, check the CD for scripts on building and loading the tables. I do not give you a script to load users; I figure that's where you can be really creative and add your friends and others. You have to have a valid user in your database for the sign-in to work properly.

When it does work, you'll see the user name. Then the user will go to the Test ID field, hit F9 , select the test from the drop-down list, and decide whether to continue. Here's what it looks like when all the parts are working:

graphics/13fig103.gif

All we have left is to program the two buttons: Register and Continue to Test and EXIT and CANCEL Registration .

For registration we want to add a record that this person started this test. To exit, we just want to end the program because so far nothing has been written to the student's record. So again, we use smart triggers. Exit is easy, but the "continue" screen needs somewhere to go, and right now we don't have another screen. We will in a couple of minutes though. So let's wrap up the EXIT button. Go back to Layout Editor, right-click on the EXIT button, select SmartTriggers WHEN_BUTTON_PRESSED , and type "EXIT_FORM;" (note the semicolon!):

Compile, hit Close , then test. Click on the EXIT button, and the form should simply close. Now to the more complicated part.

Don't forget to save your work!

Handling Errors

At this point, you're probably wondering what we're going to do about error messages. For our purposes, we're going to let Forms display them in the lower left corner. You can go to the Oracle error manual pages (all 2,000 of them!) to look up the "ORA-xxx" errors, and use Forms help for Forms ("FRM-xxx") errors. Although there is more than enough horsepower in Forms to build in error-handling code, I am not going to cover that in this book. It is somewhat complex, even more complicated than what we've covered so far!

But you're right. A fully functioning system has to trap errors and produce clear messages, and I advise you at some future time to obtain some of the Forms 6 i reference manuals on the market and work with the PL/SQL code and logic to handle errors. For now, let's get moving.

Creating the Test Form

We have only a couple more things to do. We're going to add another canvas because we're out of room on this one. The new canvas will be for the actual testyes, we've finally gotten that far! The last step will be to change some of the toolbars and what you see at the top of the screen.

Note

In creating the "take test" canvas, you're going to learn about masterdetail relationships, one of the neatest features in Forms 6 i . What this means is that you will have a master table in a data block, and on the same canvas will be a detail block that is linked to the master. We're going to use this relationship to tie the questions and answers together. Each question has four possible answers, so the question is the master, and the answers are the details.


Make sure you're in your SELECT_TEST form. If not, open it. Then do the following steps:

  1. Create the canvas: Go to Object Navigator, highlight Canvases , and then click on the green plus sign to create a new canvas. Then change the name to "CWE1P_TAKE_TEST_CANVAS":

    graphics/13fig104.gif

    graphics/13fig105.gif

    Tip

    The order of the canvases doesn't make any difference. Data blocks, however, are displayed in the order they appear in Object Navigator.

  2. Left-click on the new canvas to get into Layout Editor. Make sure that at the top, in the canvas display, it says "CWE1P_TAKE_TEST_CANVAS". If it doesn't, change to the correct canvas, or else you're in for a big, nasty surprise in a couple of minutes!

Here's what we're going to build: a screen where the user selects a question at the top, the possible answers automatically display at the bottom, and the user clicks on an answer choice and then hits SAVE My Answer! When done, the user just clicks the FINISHED (Exit) button to exit the form:

graphics/13fig106.gif

You can see that there are four main parts, plus the artistic efforts to add colors and graphics if desired:

  1. Create the master block and the F8 query function.

  2. Create the detail block and link it to the master block.

  3. Create the four radio buttons so that the user can make a selection.

  4. Create the "FINISHED" button, which is really a glorified exit button. (All you have to do is put the ending time into the file for this user for this test.)

The Master Block

You're in Layout Editor, right? Select Tools Data Block Wizard , skip the welcome screen, and select Table or View :

Save your work!

graphics/13fig107.gif

Now I'm going to stop you in your tracks. Because these tables are for display only, and because we want to keep things simple, you now have to go to SQL*Plus and create two views: one for questions and one for answers. You see, we're not going to update either the QUESTIONS or the ANSWERS table here, so let's make two views out of tests, questions, and answers and come up with columns that link the two together. Then, create a public synonym for the viewuse the same name. The syntax is as follows :

 CREATE OR REPLACE VIEW VQUESTIONS2   as select question_id, question, test_id from questions,          test_id, test_questions_link   where test_id = link_test_id and   question_id = link_question_id; Create public synonym vquestions2 for vquestions; Synonym created  View created.  

Now add values to the TEST_QUESTIONS_LINK table. This is the table, remember, that ties the tests and questions together:

 SQL> insert into test_questions_link values (1,1,1); graphics/1_icon.gif 1 row created. 

(1) The three values represent test number, question number, and weight.

Keep going to add all ten questions for Test 1. Of course, you can add as many questions as you want, as long as you have these in your QUESTIONS table. (If you have already loaded more than one test in the TEST_ID table and feel very creative, go ahead and load additional values to the TEST_QUESTIONS_LINK table.)

Note that if you try to add the same record twice, or a record that does not have a match in the TEST_ID and QUESTIONS tables, you will get constraint errors. Remember these? These are the primary key and referential integrity constraints we built in way back when. Obviously it would be a disaster if there were tests without questions! For example, you get an error if you enter:

 SQL> run   1* insert into test_questions_link values (1,8,1) insert into test_questions_link values (1,8,1) *  ERROR at line 1:  graphics/2_icon.gif  ORA-00001: unique constraint (SYSTEM.SYS_C002978) violated  

(2) Duplicate key error.

And if you try to add a record in which the question number is greater than what's in the QUESTIONS table, you will get another error:

 SQL> run   1* insert into test_questions_link values (1,8,1) insert into test_questions_link values (1,8,1) *  ERROR at line 1:  graphics/3_icon.gif  ORA-00001: unique constraint (SYSTEM.SYS_C002978) violated  

(3) Referential integrity violated! Record not in QUESTIONS table!

Once you're done, go back to the Data Block Wizard and just follow the instructions on the screen.

Select the view you just created, VQUESTIONS2 , and the two items ( QUESTION_ID and QUESTION ), hit Next , and uncheck the Auto-join data blocks box:

graphics/13fig108.gif

graphics/13fig109.gif

graphics/13fig110.gif

Go to the Layout Wizard by selecting Create the data block, then call the Layout Wizard ; skip the welcome screen; and then make sure you select the test canvas. This is very important!

graphics/13fig111.jpg

graphics/13fig112.gif

On the next two screens, select both items and accept the default sizes:

graphics/13fig113.gif

graphics/13fig114.gif

Then select Form , give it the title "QUESTIONS" and one record to display, click on Display Scrollbar , then accept the congratulations, and hit Finish :

graphics/13fig115.gif

graphics/13fig116.gif

graphics/13fig117.gif

Your new canvas now looks like this:

graphics/13fig118.gif

I'm sure that now you want to test, but first you have to go back to the SELECT_TEST canvas and activate the last button.

Now here's something to consider. When I work with forms, I create a new test form for every screen. This way I can test my logic, layout, block relationships, and so forth without blowing up the working form. I recommend that you consider doing the same. Once you have things working, just redo them in the main form.

Another technique is to use multiple forms instead of having multiple canvases in one form. Using multiple forms is great when you have several programmers working on the same system. It's also excellent when a particular application lends itself to being divided into several major parts. But that's advanced Forms 6 i ; I just want to get you started and enthused!

Here's another editing hint. When you create data block items on a canvas, you usually want to move them around a bit. That's fine, until you actually resize the entire block by pulling on one of the corners. Then the items will jump back to their original places. To prevent this, click on the block's outline, then on Property Palette , and change Update Layout to "Manually":

Save your work!

graphics/13fig119.jpg

If you go into Object Navigator, your form should look like this:

graphics/13fig120.gif

Go back to the SELECT_TEST canvas in Layout Editor. It's easy: At the top of the screen, the block (and canvas) that you're in is shown. Just use the down arrow next to the Canvas box to get a list, click on SELECT_TEST , and you'll go right back to that canvas.

Now right-click on the Continue button, select SmartTriggers WHEN- BUTTON-PRESSED , and type "GO_ITEM ('vquestions2.question_id');". Compile, then close and test.

Tip

If you get an error like "Error 357 at . . . Table, View" or "Sequence reference 'vquestions2.question_id' not allowed in this context", most likely you did not put the single quotes around the vquestions2.question_id command.


You should now be able to click on the Continue button and go to the new canvas, where you can click on F8 and see the questions. Congratulations, you're close to being done! If you put the cursor in the Question Id field and hit F8 , here's what you should see:

graphics/13fig121.gif

You can also now use the up and down arrows, and the Page Up and Page Down keys. Have fun running your form. (Note that you should see only ten questionsmore if you've been very creative!) Now exit this screen, and let's move on.

The Detail Block

The next step is to add the detail block, which will be really easy now that you've done the master. Go back to the TAKE_TEST canvas, start up the Data Block Wizard, and this time selectuh oh, I forgot ! Go back to SQL and create a view from ANSWERS: Create or replace view VANSWERS2 as select answer_question_id, answer_id, answer from ANSWERS . Now create a public synonym for the view, using the same name as the view. Run the new view, and 40 rows should be returned10 questions, each with 4 answers. (If you've added more answers to the ANSWERS table, you will, of course, get more results.)

Done? OK. We're going to use the Data Block Wizard again. So get into Layout Editor and, as always, check the top of the screen to make sure you have the right canvas:

graphics/13fig122.gif

Now just click on Tools Data Block Wizard Table or View and select your new view, VANSWERS2, and all three columns.

On the next screen, uncheck the Auto-join data blocks box, and click on Create Relationship... . Then on the Relation Type screen, choose Based on a join condition :

graphics/13fig123.gif

graphics/13fig124.gif

The only other table on this canvas so far is your VQUESTIONS2 view, so select that when it pops up, and the next screen will let you build the relationship:

graphics/13fig125.gif

graphics/13fig126.gif

Remember that we want to tie all the answers to each question. So we create a join by picking ANSWER_QUESTION_ID for the detail item, and then picking QUESTION_ID for the master item. Forms 6 i then creates the code:

graphics/13fig127.jpg

Click Finish , go to the Layout Wizard (this should look a little familiar by now), and just be careful to stay on the correct canvas:

graphics/13fig128.gif

We want to show only two of the items, so select ANSWER and ANSWER_ID , skip the next screen, and then select Form :

graphics/13fig129.gif

graphics/13fig130.gif

Give the form the title "Answers", with four records showing:

graphics/13fig131.gif

Then accept the congratulations offered , and your canvas should look like this:

graphics/13fig132.gif

You can go ahead and test by selecting Program Run Client/Server . Remember? When you get to your new canvas, make sure the cursor is in the Question Id field, then hit F8 , and you should get the first question with its answers below. (Notice that I added instructions for F8 .)

graphics/13fig133.gif

OK, you're saying, what if this doesn't work? I've been telling you to test at every step, so you know that the only change you've made is to add the detail block. To test what you did in building the relationship, go to SQL*Plus and run the same code to see what results you get. Here are several things that can cause problems:

  • You have canvas items outside the boundaries.

  • Some of your canvas items have incorrect settings.

  • Your views are not valid.

  • Your tables don't have any data.

As a last resort if you just cannot resolve the problems, you can always delete the new block and all its items and start again. Be warned , however, that you must also go into Object Navigator and delete the data block information . For example, if we just couldn't get the master detail to work, we could stay in Layout Editor and delete the new detail block containing the answers. We would then have to go to Object Navigator and delete the data block VAN- SWERS2 . We do this by highlighting the block and then clicking on the red X in the left-hand column of icons:

Save your work!

graphics/13fig134.gif

Tip

An easy way to get to Layout Editor for a canvas is simply to click on the canvas when you're in Object Navigator.


Buttons

What's left with this canvas? We have to add the button to finish, add the instructions to use F8 , and most importantly, give the users a way to select an answer. Here's where I'll introduce you to what's called a radio button group .

Groups such as radio buttons or drop-down lists are handy when there are a limited number of choices. Radio buttons are great for five or fewer selections, and by nature they are mutually exclusive; that is, the user can click on only one of them. You then take that value and write it to the database, as you'll see, and you now have a record of the student's answers for each question for this particular test. See how it's all coming together? Building an Oracle system is like getting a long freight train moving: It takes time, but once it's rolling, it goes sweetly.

Let's create the last data block. Again, make sure you're on the right canvas (TAKE_TEST), and select the Data Block Wizard. This time the table is STUDENT_ANSWER_HISTORY, where you'll select only one field: STUDENT_ANSWER . On the next screen, uncheck Auto-join data blocks . If you see data from your previous work when you created a join relationship, just click the Delete Relationship button:

graphics/13fig135.gif

graphics/13fig136.gif

Go on to the Layout Wizard; the canvas is TAKE_TEST_CANVAS. Change the data block to VANSWERS2, then select the one field, and this time change Item Type to Radio Group , giving it any title you like:

graphics/13fig137.jpg

graphics/13fig138.gif

The canvas now has a funny-looking line for the new block, so just pull on the black tabs to expand it:

graphics/13fig139.gif

Now add the radio buttons by clicking on the icon, then putting the cursor (which is now a crosshatch), in the new block. You will be asked which radio group you want to place the button in. Click OK to select STUDENT_ ANSWER , and you will then see the new radio button in the new block:

graphics/13fig140.gif

graphics/13fig141.gif

Now add three more radio buttons, and change the properties of each:

graphics/13fig142.gif

Here's what your canvas should look like:

graphics/13fig143.gif

Now we set the initial value. Again, this is done in the property palette, so go back to Object Navigator and find the radio button group. It has a symbol next to it that looks like two small circles arranged vertically:

graphics/13fig144.jpg

Next add a command button named SAVE! or SAVE My Answer! and create a smart trigger for WHEN_BUTTON_PRESSED that has the following code (which deletes any previous answer for this question and replaces it with the new answer):

  DELETE  STUDENT_ANSWER_HISTORY where student_answer_history.test_id = :cwe1p_select_test_block.test_id and student_answer_history.student_id = :cwe1p_select_test_block.user_id and student_answer_history.question_id = vquestions2.question_id;  insert  into student_answer_history    values (:cwe1p_select_test_block.user_id,:cwe1p_select_test_block.test_id,   :vquestions.question_id,   :student_answer_history_block.student_answer);  COMMIT;  

graphics/13fig145.gif

Tip

Some of your block names may be different, so just make changes if you get syntax errors.


Tip

A message like "STUDENT_ANSWER_HISTORY not defined" means simply that you are not logged onto the database. Hence, Forms 6 i cannot find the table. Log on and you'll be all set.


Save your work!

The last step is to add the "FINISHED" button at the bottom of the canvas. You should know how to do that by now, so create the button, rename it, and add the following code for a smart trigger for WHEN_BUTTON_PRESSED :

 -- Notice that we've hard-coded the test results. In a -- production -- system you would have a routine to calculate the actual score -- and so forth. My goal here is to show you how to update the -- student record. Here would be your routine to calculate the -- score and total test times. -- Now update the record for this student for this test. UPDATE test_history   SET SCORE = 100,     END_TIME = '113011'   WHERE    test_history.test_id = :cwe1p_select_test_block.test_id    and    test_history.student_id = :cwe1p_select_test_block.user_id; COMMIT; 

graphics/13fig146.gif

Don't forget to go back to Object Navigator and change the names of your new buttons to make them more readable. You don't have to, but it is good practice.

Tracking IDs

There's just one more step. For testing purposes, we have not kept track of student IDs taking a test. Remember the ruleonly one shot at a test? As you've surely realized by now, we have not enforced that rule simply for ease of testing. When your system is done, you will have to add the following code on the SELECT_TEST canvas, under the Register and Continue to the test button trigger:

 -- Create a new record for this student for this test. Remember -- that the -- rules are that a student can only take a test once! -- You should add a routine to check if there is a student -- record -- for this test, and if so, throw up a message to stop the -- user from -- continuing. That's for the next book! But, you should be -- able to try it on your own. -- insert into test_history values (:cwe1p_select_test_block.test_id,                 :cwe1p_select_test_block.user_id,                  0,                  sysdate, '091500', '0', 'Main Lab'); go_item ('vquestions.question_id'); graphics/1_icon.gif 

(1) This line already existed. Remember?

What about a duplicate record? When a user tries to take enter a test that he or she has already taken, Forms 6 i throws up an error message in the bottom left corner we've seen this alreadyso you do not have to process for errors!

Note

You're probably wondering what is going on with these views. Why did we wait until now? Are more coming? You see, views are pretty straightforward, yet they can become very sophisticated. Instead of showing them to you as an isolated exercise, I put them here so that you could get an idea of the kind of processing they're good for. Let me give you another example. Suppose that you want to show all the questions and their answers, but not allow anyone to see questions greater than, say, 100 because those are for advanced students. You would create a view like this:

 create or replace view QA_VIEW     as (select question_id, question, answer_id, answer     from questions, answers     where answer_question_id = question_id and question_id < 101); 

Now anyone in your department who has rights can simply run this view and get a list of all questions and answers, without being able to change anything! So a view is a great way to combine selective data from various tables for your customers.


Linking the Forms

Let's see where we are. By now you should have two forms and a couple of icons for the splash screen and main screen (if you added other icons, that's OK):

graphics/13fig147.gif

The .fmx files are the compiled programs that are run, and the .fmb files are the source files that you work with in Object Navigator and Layout Editor.

I'm showing you this because we're getting close to finishing, and it should be on your mind that somehow we have to tie the two forms together. You already know how to go from one canvas to another within a form. Now I'll show you how to jump from form to form. Then we have to finish up some of the buttons, and finally, change the top toolbars and menu bars.

Forms 6 i provides several ways to navigate among various forms:

  • CALL_FORM immediately jumps to the next form; it can pass parameters.

  • OPEN_FORM opens another form, but it doesn't immediately jump to it.

  • NEW_FORM opens another form and immediately closes the one it came from.

We're going to use CALL_FORM to get to the CWE1P_SELECT_TEST form, and you already know about the EXIT_FORM trigger we'll put on the main screen. As you've probably imagined, we can also close specific forms as needed. The command that we would use in the trigger is CLOSE_FORM .

Let's change the main canvas now and add a trigger to jump to the CWE1P_SELECT_TEST form, as well as a trigger to exit in case the user decides not to take a test.

Start Form Builder. Select Open an existing form , and then CWE1P_ MAIN.fmb :

graphics/13fig148.gif

graphics/13fig149.gif

Then open CWE1P_CANVAS with the three buttons:

graphics/13fig150.gif

Remember how to create a trigger? Right-click on the EXAMS button, select SmartTriggers WHEN-BUTTON-PRESSED , and type "CALL_FORM (:GLOBAL.PROJECT_PATH 'CWE1P_SELECT_TEST');".

Note

If you put your icons into another folder, you will have to declare another global path .


To add another global path, go to Object Navigator for the CWE1P_MAIN form, select the PRE-FORM trigger, and enter a second global path:

Save your work!

graphics/13fig151.gif

graphics/13fig152.gif

Now just add the EXIT_FORM code for the smart trigger for the EXIT button, and test. You should be able to get to the CWE1P_SELECT_TESTform and take an exam. (Forget how? First create the button and change the name to "EXIT". Then right-click on the button, select SmartTriggers WHEN_BUTTON_PRESSED , type in "EXIT_FORM;" don't forget the semicolon!and then compile and close. Now run a quick test.)

Note

Again, this reminder: Save your work at every step of the way. That's why Oracle has put the diskette icon everywhere!


If you run into problems, take a close look at the errors in the bottom left corner. Sometimes there's an error in your new global path. Often the problem is just a misspelling or a missing comma. It is interesting that the trigger function picks up a lot of the syntax errors, but not all of them. If you get a message like "Procedure or Function xxxx not declared", usually either you have missed a colon (:) or you have misspelled the name of a block.

We're in the home stretch now. All we have to do is clean up the top of the screenthat is, work on the menus .

Menus

This is the final piece, and it is what will make your screens look absolutely professional. I'll show you how to replace the Forms menu bar at the top of the screen with your own. Instead of the default itemssuch as Action , Edit , Query , Block , and so forthyou will have items that match some of the things the user can do on your screens, and only those things!

These are the steps:

  1. Create a menu module.

  2. Create the menu items (parent and child items).

  3. Activate the items.

  4. Put the menus on the CWE1P forms.

Note

Custom menus can be attached only to a form, not a specific canvas. Thus some forethought is required to make sure everything works together.


Creating a Menu Module

Let's start with some of the main ideas. A menu item , contrary to what you may be thinking, is the entire set of horizontal menu selections across the top of the screen. Any menu module can have several menu items that are attached to different screens.

A menu item has both parent and child items, as you will see. And a menu module is a distinct object, not a form. We will save our menu module as CWE1P_MENU.mmb . (Yes, the related .mmx file is the compiled module!)

Here are the steps for creating a menu module:

  1. Start Forms.

  2. On the welcome screen, select Cancel .

  3. Go to Object Navigator.

  4. Click on the MODULE1 node and delete it by clicking on the red X (we don't need a form).

  5. Select the Menus node, click the green plus sign, and rename the node "CWE1P_MENU".

  6. Now select the Menus node under your new CWE1P_MENU node, again click the green plus sign, and rename it "CWE1P_MAIN_MENU".

  7. Save CWE1P_MENU.mmb in the Oracle_Guerrilla folder:

    graphics/13fig153.gif

Your Object Navigator screen should look like this:

graphics/13fig154.jpg

Creating Menu Items

Now we go to the menu editor to build the contents of our first menu item. Just double-click either the menu module icon or the menu item icon, and the editor screen will appear:

graphics/13fig155.gif

The rules are pretty simple: The highest level, or parent, items are created first, from left to right.

Just select the default menu item ( <New_Item> ), and double-click on the button that has an arrow pointing to the right:

graphics/13fig156.gif

Now just highlight the items one at a time and change the names by rightclicking on each item, selecting Property Palette (remember that from your work with forms?), and changing the label:

graphics/13fig157.gif

Although we don't have any child items for ADMINISTRATION , we can add them now; we just won't activate them. Highlight the ADMINISTRATION item, then click several times on the icon that has an arrow pointing downward and change the labels:

graphics/13fig158.gif

You may have noticed that in the property palette, under the Functional node you have choices for some of the variables :

graphics/13fig159.gif

All menu items are Plain by default, which means that they have text labels, and a trigger will fire when the user selects any Plain item. This is the most common type. Check means that the item has a property that can be disabled or enabled. Radio means that the choices are like radio buttons: Only one can be selected at a time. Separator means just that: This item is a separator bar in the menu. Magic refers to specific types that are predefined in Forms: Cut , Copy , Paste , Clear , Undo , About , Help , Quit , and Window . Some of these can have user code associated with them.

Note

I hope you're getting a good idea of the power of Forms. Although I am just introducing you to Forms for our purposes of presenting the guerrilla exams, it would be great if you took the initiative and expanded your expertise by experimenting with these other features.


Let's use a Magic type. Go to the Exit menu item, open Property Palette , and change Menu Item Type to "Magic" and Magic to "Quit":

graphics/13fig160.gif

OK, you've seen what's missing. Go ahead and add the Help parent menu item. (And in the Functional node of its property palette, don't forget to change Menu Item Type to "Magic" and Magic Item to "Help".)

Now just a couple of sentences on access keys , those keys that you can hit instead of clicking on a menu item. For example, you can type "X" for Exit . All menu items have the first letter as the default access key. If you want to change the default for a particular item, go to that item's property palette (yes, again!) and put an ampersand (&) in front of the letter you want. For example, to make "X" the access key for Exit , type in "E&XIT". When that menu item is highlighted, the user can either hit the X key or click on Exit to exit.

Activating the Menu Items

Let's activate the menu items we just created and bring one of our screens to life. For our first screen, the ADMINISTRATION items are not enabled. You can just change the value in the property palette for those menu items to "Enabled", but I'm going to show you how to pop up a message instead. Just create a trigger for each ADMINISTRATION child item that has this code (right-click on the menu item, then select PL/ SQL Editor to create the PL/SQL code):

 MESSAGE ('This item is not active at this time'); 

The EXIT button is easy: Just create the trigger to EXIT_FORM. The EXAMS selection has to call the main form, so create a trigger that says

 CALL_FORM (:GLOBAL.PROJECT_PATH'CWE1P_main.FMX'); 

Your Object Navigator screen should now look like this:

graphics/13fig161.gif

The next big step is to compile. Now don't just run off and try to compile the menu like a form! Instead, select File Administration Compile and correct any errors.

Eventually, or immediately if you've lucked out, you will see the message "Module built successfully" in the lower left-hand corner. Once you get this message, you're ready to move on.

Tip

One of the most important things to remember is that every time you make a change to a menu, you have to compile the menu, then go to the form that uses it and compile that form also. If you don't, you will get what look like very strange errors. So get in the habit of the following steps: change menu, compile menu, go to form, compile form, test form. This little mantra will save you a lot of headaches .


Adding Menus to a Form

Now we tie the menu to a form:

  1. Close your menu and open your main form (CWE1P_MAIN)yes, go back to Object Navigator and open the property palette for the form. Then change the Menu Module item to the full path:

     D:\GUERRILLA_ORACLE_EXAM\CWE1P_PROJECT\CWE1P_MENU: 

graphics/13fig162.gif

Tip

The global path variable does not work here, so be careful if you ever move your menu files.


We've reached the last step! To make your project look professional, you have to have a custom menu for your last two canvasesthe ones where the student selects and then takes the test, remember? This is the SELECT_TEST.fmb form that we created a little while ago, and this is the form that needs the custom menu.

Note

Remember, custom menus can be tied only to a form, not a canvas.


This step is a little complex because it has two canvases, or two screens. So we have to make sure that the menu item we create fits both. That is, both the screen where the user selects the test and the screen where the user takes the test will have the same menu item you make.

The only menu item that seems to comfortably fit both screens is the nonfunctioning HELP item, right? We can't really run code from menu items. Menu items have to hop to a form, and we want the user to make choices on the screens, such as which test, which answer, and so forth. So about the only thing that makes sense is some kind of help item. Everything else is already on the canvases because you did such a great job.

You should know the drill by now. You have to create one new menu item that will be called HELP . Then right-click on the item, then on Property Palette , and disable the item by entering "No" in the Enabled field of the Functional node:

graphics/13fig163.gif

Warning

You must save each one of the menu items: File Save As <name>! And you must compile each one!

Here's what your GUERRILLA_ORACLE folder should look like:

graphics/13fig164.gif


Finally, we have to attach the menu items to the form. You know how to do this: Go to the form, select Property Palette , go down to the Functional node, and for Menu Module type the path: "D:\GUERRILLA_ORACLE\CWE1P_ PROJECT\CWE1P_HELP":

graphics/13fig165.gif

Then test. You should get the following error:

graphics/13fig166.gif

At first it looks like your system has failed. However, if you check the Oracle error, you'll find that your system has worked perfectly . An "ORA00001" error means that you have violated a unique constraint. Remember that a person is allowed to take an exam only once? Well, we already have a record for this user for this test, so we should get an "ORA-00001" error, and we did. So it's working!

To continue testing, either delete the history record for this person or create a couple of new users. However, notice that the menu has changed to the simple one you created. You always get a Window item, and all we wanted was a nonfunctioning Help item.

graphics/13fig167.gif

So there it is. You have your running system, using all the major components of Forms 6 i . Because there is so much more in Forms, I strongly encourage you to get a couple of books and refine your system. Add the administration functions, error handling, security, toolbars with icons, and pop-up menus.

Congratulations! You've mastered some of the intricacies of Forms 6 i .Go show off what you've done.

One Last Tip

Always build your forms and menus a piece at a time. Add one thing, compile, then test and debug. Do too many things at once, and you're dead! Forms is just too complex to rush through.


OK, One More Tip

You can find all the "FRM-xxx" errors in the Help index. Just go to Help Topics and find the FRM error you want, then click on the error to get the explanation:

graphics/13fig168.gif

graphics/13fig169.gif


For information on Forms 6 i security issues, see Appendix A.



Guerrilla Oracle
Guerrilla Oracle: The Succinct Windows Perspective
ISBN: 0201750775
EAN: 2147483647
Year: 2003
Pages: 84

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net