Automate An Application's Menus

by Jack Wheeler (jwl1@jps.net)

Jack's application has a "Main Menu" form which shows each user the actions appropriate for that user's security level.  In the past, Jack had to recode the application if a user's security privileges changed. In this article Jack discovers a way to allow the client to change user-specific menus without Jack's intervention!

Do you think it is possible to design a procedure that will allow different users to see only their permitted actions within an application? Can you then allow the system administrator at the client site to easily change user privileges and thereby modify the menu choices each user can see?

I did not think this was possible. I could not even imagine such an alternative. One of the beauties of Dr Wayne's web site is the feedback I get when I submit a tip or article. This is the case with my article on Customizing Your Application for Each User. Robert emailed me and gave me a BRAINSTORM of a tip. He uses a Menu table to base all his menus on. This idea so simplifies application development that I am still thankful someone has shared it with me! I now use it for all my menus that may be different depending on department, user or family member. Here is my new design, which can now be downloaded and implemented 100% (just change the text and values as they pertain to you).

In my previous method of controlling access within my application, it became very clear that when my client decided to add another user or change the restrictions of a current user, it would have to be Jack that did the changes. Everything was coded in the forms design. I estimated that I would take about an hour to update a menu. Not too efficient! I was lead to a different way of looking at my original problem and solution. Once I understood this I quickly redesigned my security issures this way… I created a MenuItem table.

tp6b

You will see that the table has two main fields:

Wow, this seems so simple, I wonder why I had not figured this out on my own! I proceeded in designing the ‘Menu Audit’ form. All that was needed two sections, one for each menu I was using. I then included a description line and the field that will allow the user to use it or not. Since I was going to apply my codes to a button I decided to include a sample button for each menu choice. Once the form was done and functioning I would have all the codes I could need.

tip6

Robert advised me to place my code in a global script and not on the form. At first I was not sure why, but then I remembered an article by Steve Workings where he said the same thing: his point was that if you did this you could edit all and any scripts without needing access to any tables or forms.

The code seemed so easy at first: simply get the name of the field in the table and add the choice to the multistate button. But how do we populate the multistate button with the proper values?

Now we will discover the POWER of Alpha’s eval() function. (You should check out Peter Wayne's article explaining the eval() function, very powerful!) Here is the script for the Menu Audit forms button:

dim nbr as n
dim f as p
dim i as n
dim number as n
dim text1 as c
dim text2 as c
dim text3 as c
dim text4 as c
dim text5 as c
dim text6 as c
dim text7 as c
dim text8 as c
dim text9 as c
dim text10 as c
dim text11 as c
dim text12 as c
dim filename as c
dim fieldobj as p
f=parentform.this
'debug(1)
nbr = 0
if f:Accounts_Receivables.value="Y" then
 nbr1= nbr+1
 nbr=nbr1
 filename="text"+alltrim(str(nbr))
 eval(filename)="Account Receivables"
 end if
if f:Accounts_Payables.value="Y" then
 nbr2= nbr+1
 nbr=nbr2
 filename="text"+alltrim(str(nbr))
 eval(filename)="Account Payables"
 end if
if f:Data_entry.value="Y" then
 nbr3= nbr+1
 nbr=nbr3
 filename="text"+alltrim(str(nbr))
 eval(filename)="Data Entry"
 end if
if f:Past_due.value="Y" then
 nbr4= nbr+1
 nbr=nbr4
 filename="text"+alltrim(str(nbr))
 eval(filename)="Past Due"
 end if
if f:Invoice_prep.value="Y" then
 nbr5= nbr+1
 nbr=nbr5
 filename="text"+alltrim(str(nbr))
 eval(filename)="Invoice Preparation"
 end if
if f:Observation.value="Y" then
 nbr6= nbr+1
 nbr=nbr6
 filename="text"+alltrim(str(nbr))
 eval(filename)="Client Observation"
 end if
if f:Contact_manager.value="Y" then
 nbr7= nbr+1
 nbr=nbr7
 filename="text"+alltrim(str(nbr))
 eval(filename)="Contact Manager"
 end if
if f:Calendar.value="Y" then
 nbr8= nbr+1
 nbr=nbr8
 filename="text"+alltrim(str(nbr))
 eval(filename)="Appointments Calendar"
 end if
if f:Peach_tree.value="Y" then
 nbr9= nbr+1
 nbr=nbr9
 filename="text"+alltrim(str(nbr))
 eval(filename)="Peach Tree"
 end if
if f:Excel.value="Y" then
 nbr10= nbr+1
 nbr=nbr10
 filename="text"+alltrim(str(nbr))
 eval(filename)="Excel"
 end if
if f:word.value="Y" then
 nbr11= nbr+1
 nbr=nbr11
 filename="text"+alltrim(str(nbr))
 eval(filename)="Word"
 end if
if f:Good_bye.value="Y" then
 nbr12= nbr+1
 nbr=nbr12
 filename="text"+alltrim(str(nbr))
 eval(filename)="Good Bye"
 end if
 IF NBR=0 THEN
 f:twostbtn1.choice.list.redim(1)
f:twostbtn1.choice.list[1].text=""
 END 
 END IF
 f:twostbtn1.choice.list.redim(nbr)
 for i = 1 to nbr
 f:twostbtn1.choice.list[i].text=eval("text"+str(i)) 
 next
if nbr>7 then
 f:Twostbtn1.font.size=12
end if

This is what the final menu will look like:

tip6a

Here are the problems I ran into while designing these forms and techniques:

  1. In the Menu Audit form, I needed to update the sample button on the bottom as the system administrator checked and unchecked privileges for the user. I used the OnChange event of each field to update the form and presto……the button updated every time I changed any field!
  2. When I needed to enter a new user, every checkbox in the Menu Audit form took on the Windows background color and showed a check mark in the box. The field had no value associated with it and when you clicked on the field it would need two clicks to activate it. I decided to set all the values to "N" (the false value) when I pushed the ‘Add User’ button. The code is this parentform:checkbox1.value="N" etc. (you will find this code within the action of ‘New User’ button)
  3. It was difficult to select the proper appearance of the buttons on the Menu Audit form. I kind of left that as a small flaw. It works well enough to show all the buttons that will show up. They just don’t match what will be on the actual Main Menu forms, since the Main Menu form is larger.
  4. I use the computer's user name as the user of Alpha. There is a field for a password but we don’t use this. Therefore I use an optional program that I referred to in my previous article on multistate buttons. Dr. Wayne has done wonders with API calls you can also get the user name using an API call. The article on pie charts shows the use of the GetUserName API call.

We are using this form now and it really is a nice tool. You can see how effective it would be to create many of your user forms like this. Think of your Print option forms, or running saved operations... the list gets bigger and bigger. I have found that most users love the forms that have buttons as objects. This is why this form has become so popular with my users.

I hope this little demo will give you a cleaner and clearer approach to customizing your application menus! You can download sample files to see how it's done!

3/25/00

Don't forget, we need your feedback to make this site better!

Return to home