Customize your Application for Each User

by Jack Wheeler

They said they only wanted a Main Menu. It turns out they wanted a custom menu for each user! Here's how Jack satisfied his picky clients. You can reach Jack at jwl1@jps.net

What do you do when you have completed a wonderful application done, you are out of time and money, and your client wants to change it?

USE ALPHA FIVE’S OBJECT PROPERTIES

I had just spent over eight months developing and redeveloping an application for this insurance company and I was so happy that it was done when ………..BAM ! They were not happy with the finished product. "What the Heck could they not be happy with?", I asked myself: of all things it was the application's Main Menu. They asked me to customize the Main Menu so that employees in the Accounts Payable department only saw the functions that pertain to them and Data Entry workers only see their respective functions.

There was no way I was going to redesign a separate form for each user, especially since there was 10 machines, each networked with Alpha Five. This was just too much for me to comprehend........Until I remembered that using Xbasic I could change many properties of Buttons and text objects. Here is what I did, the problems I encountered and how I solved them.

We already had developed a logon screen that uses the user's name to fill in many items during data entry or posting operations. This way we could audit all the changes done daily by each employee. This company became very concerned that the user would be absolutely overwhelmed with detail if they saw the entire application. My Main Menu screen uses a Multistate Button to present a list of tasks. If I could change the properties of the Multistate Button I could present each user with a customized Main Menu form.

I redesigned the Main Menu so that the Multi State Button so that initially each button choice had no text: I completely deleted the choices under the menu options and resized the Button to a comfortable size.

FigA

Figure A. Notice the choices for the multistate button are all blank.

I then fill out the choices for each individual user in the form's OnInit event. Remember that the code is for predetermined users and can be customized as you see fit. You will see that I commented out some of the lines depending on who the user is. I could then easily include them if that particular user became more involved in other areas of the company - a very real possiblity!

The button is Named ‘But’ and rep is the Logon global variable

''XBasic
dim f as p
f=parentform.this
if rep="karla".or.rep="kp" then 
but.choice.list.redim(5)
But.choice.list[1].text="Data Entry Choices"
But.choice.list[1].value="New"
'But.choice.list[2].text="Client Observations"
'But.choice.list[2].value="Company"
'But.choice.list[3].text="Past Due"
'But.choice.list[3].value="Pass"
'But.choice.list[4].text="Invoice Preparation"
'But.choice.list[4].value="Invoicing"
But.choice.list[2].text="Calendar for "+var->rep
But.choice.list[2].value="Scheduling"
'But.choice.list[6].text="Contact Manager"
'But.choice.list[6].value="Contact"
'But.choice.list[7].text="Accounts Receivables"
'But.choice.list[7].value="Recievables"
'But.choice.list[8].text="Accounts Payables"
'But.choice.list[8].value="Payables"
'But.choice.list[9].text="Peach Tree"
'But.choice.list[9].value="Peach"
But.choice.list[3].text="Word"
But.choice.list[3].value="Word"
But.choice.list[4].text="Excel"
But.choice.list[4].value="Excel"
But.choice.list[5].text="GoodBye "+var->rep
But.choice.list[5].value="exit"
elseif rep="Marni".or.rep="mf" then 
but.choice.list.redim(8)
But.choice.list[1].text="Data Entry Choices"
But.choice.list[1].value="New"
'But.choice.list[2].text="Client Observations"
'But.choice.list[2].value="Company"
But.choice.list[2].text="Past Due"
But.choice.list[2].value="Pass"
'But.choice.list[4].text="Invoice Preparation"
'But.choice.list[4].value="Invoicing"
But.choice.list[3].text="Calendar for "+var->rep
But.choice.list[3].value="Scheduling"
'But.choice.list[6].text="Contact Manager"
'But.choice.list[6].value="Contact"
But.choice.list[4].text="Accounts Receivables"
But.choice.list[4].value="Recievables"
'But.choice.list[8].text="Accounts Payables"
'But.choice.list[8].value="Payables"
But.choice.list[5].text="Peach Tree"
But.choice.list[5].value="Peach"
But.choice.list[6].text="Word"
But.choice.list[6].value="Word"
But.choice.list[7].text="Excel"
But.choice.list[7].value="Excel"
But.choice.list[8].text="GoodBye "+var->rep
But.choice.list[8].value="exit"
elseif rep="Dan".or.rep="db" then 
but.choice.list.redim(5)
But.choice.list[1].text="Data Entry Choices"
But.choice.list[1].value="New"
'But.choice.list[2].text="Client Observations"
'But.choice.list[2].value="Company"
'But.choice.list[3].text="Past Due"
'But.choice.list[3].value="Pass"
'But.choice.list[4].text="Invoice Preparation"
'But.choice.list[4].value="Invoicing"
But.choice.list[2].text="Calendar for "+var->rep
But.choice.list[2].value="Scheduling"
'But.choice.list[6].text="Contact Manager"
'But.choice.list[6].value="Contact"
'But.choice.list[7].text="Accounts Receivables"
'But.choice.list[7].value="Recievables"
'But.choice.list[8].text="Accounts Payables"
'But.choice.list[8].value="Payables"
'But.choice.list[9].text="Peach Tree"
'But.choice.list[9].value="Peach"
But.choice.list[3].text="Word"
But.choice.list[3].value="Word"
But.choice.list[4].text="Excel"
But.choice.list[4].value="Excel"
But.choice.list[5].text="GoodBye "+var->rep
But.choice.list[5].value="exit"
elseif rep="Silvia".or.rep="sz" then 
but.choice.list.redim(9)
But.choice.list[1].text="Data Entry Choices"
But.choice.list[1].value="New"
'But.choice.list[2].text="Client Observations"
'But.choice.list[2].value="Company"
But.choice.list[2].text="Past Due"
But.choice.list[2].value="Pass"
'But.choice.list[4].text="Invoice Preparation"
'But.choice.list[4].value="Invoicing"
But.choice.list[3].text="Calendar for "+var->rep
But.choice.list[3].value="Scheduling"
'But.choice.list[6].text="Contact Manager"
'But.choice.list[6].value="Contact"
But.choice.list[4].text="Accounts Receivables"
But.choice.list[4].value="Recievables"
But.choice.list[5].text="Accounts Payables"
But.choice.list[5].value="Payables"
But.choice.list[6].text="Peach Tree"
But.choice.list[6].value="Peach"
But.choice.list[7].text="Word"
But.choice.list[7].value="Word"
But.choice.list[8].text="Excel"
But.choice.list[8].value="Excel"
But.choice.list[9].text="GoodBye "+var->rep
But.choice.list[9].value="exit"
elseif rep="Alfonso".or.rep="ap" then 
  but.choice.list.redim(10)
But.choice.list[1].text="Data Entry Choices"
But.choice.list[1].value="New"
'But.choice.list[2].text="Client Observations"
'But.choice.list[2].value="Company"
But.choice.list[2].text="Past Due"
But.choice.list[2].value="Pass"
But.choice.list[6].text="Invoice Preparation"
But.choice.list[6].value="Invoicing"
But.choice.list[3].text="Calendar for "+var->rep
But.choice.list[3].value="Scheduling"
'But.choice.list[6].text="Contact Manager"
'But.choice.list[6].value="Contact"
But.choice.list[4].text="Accounts Receivables"
But.choice.list[4].value="Recievables"
But.choice.list[5].text="Accounts Payables"
But.choice.list[5].value="Payables"
But.choice.list[9].text="Peach Tree"
But.choice.list[9].value="Peach"
But.choice.list[7].text="Word"
But.choice.list[7].value="Word"
But.choice.list[8].text="Excel"
But.choice.list[8].value="Excel"
But.choice.list[10].text="GoodBye "+var->rep
But.choice.list[10].value="exit"
elseif rep="Marni".or.rep="mf" then 
but.choice.list.redim(8)
But.choice.list[1].text="Data Entry Choices"
But.choice.list[1].value="New"
'But.choice.list[2].text="Client Observations"
'But.choice.list[2].value="Company"
But.choice.list[2].text="Past Due"
But.choice.list[2].value="Pass"
'But.choice.list[4].text="Invoice Preparation"
'But.choice.list[4].value="Invoicing"
But.choice.list[3].text="Calendar for "+var->rep
But.choice.list[3].value="Scheduling"
'But.choice.list[6].text="Contact Manager"
'But.choice.list[6].value="Contact"
But.choice.list[4].text="Accounts Receivables"
But.choice.list[4].value="Recievables"
'But.choice.list[8].text="Accounts Payables"
'But.choice.list[8].value="Payables"
But.choice.list[5].text="Peach Tree"
But.choice.list[5].value="Peach"
But.choice.list[6].text="Word"
But.choice.list[6].value="Word"
But.choice.list[7].text="Excel"
But.choice.list[7].value="Excel"
But.choice.list[8].text="GoodBye "+var->rep
But.choice.list[8].value="exit"
elseif rep="Cece".or.rep="ct" then 
but.choice.list.redim(8)
But.choice.list[1].text="Data Entry Choices"
But.choice.list[1].value="New"
'But.choice.list[2].text="Client Observations"
'But.choice.list[2].value="Company"
But.choice.list[2].text="Past Due"
But.choice.list[2].value="Pass"
'But.choice.list[4].text="Invoice Preparation"
'But.choice.list[4].value="Invoicing"
But.choice.list[3].text="Calendar for "+var->rep
But.choice.list[3].value="Scheduling"
'But.choice.list[6].text="Contact Manager"
'But.choice.list[6].value="Contact"
But.choice.list[4].text="Accounts Receivables"
But.choice.list[4].value="Recievables"
'But.choice.list[8].text="Accounts Payables"
'But.choice.list[8].value="Payables"
But.choice.list[5].text="Peach Tree"
But.choice.list[5].value="Peach"
But.choice.list[6].text="Word"
But.choice.list[6].value="Word"
But.choice.list[7].text="Excel"
But.choice.list[7].value="Excel"
But.choice.list[8].text="GoodBye "+var->rep
But.choice.list[8].value="exit"
elseif
rep="Richard".or.rep="RT".or.rep="Amanda".or.rep="ac"
then 
but.choice.list.redim(7)
But.choice.list[1].text="Data Entry Choices"
But.choice.list[1].value="New"
'But.choice.list[2].text="Client Observations"
'But.choice.list[2].value="Company"
'But.choice.list[2].text="Past Due"
'But.choice.list[2].value="Pass"
'But.choice.list[4].text="Invoice Preparation"
'But.choice.list[4].value="Invoicing"
But.choice.list[2].text="Calendar for "+var->rep
But.choice.list[2].value="Scheduling"
But.choice.list[3].text="Contact Manager"
But.choice.list[3].value="Contact"
'But.choice.list[4].text="Accounts Receivables"
'But.choice.list[4].value="Recievables"
'But.choice.list[8].text="Accounts Payables"
'But.choice.list[8].value="Payables"
But.choice.list[4].text="Peach Tree"
But.choice.list[4].value="Peach"
But.choice.list[6].text="Word"
But.choice.list[6].value="Word"
But.choice.list[5].text="Excel"
But.choice.list[5].value="Excel"
But.choice.list[7].text="GoodBye "+var->rep
But.choice.list[7].value="exit"
elseif
rep="Jack".or.rep="Raul".or.rep="rv".or.rep="IT"
then 
but.choice.list.redim(12)
But.choice.list[1].text="Data Entry Choices"
But.choice.list[1].value="New"
But.choice.list[2].text="Client Observations"
But.choice.list[2].value="Company"
But.choice.list[3].text="Past Due"
But.choice.list[3].value="Pass"
But.choice.list[4].text="Invoice Preparation"
But.choice.list[4].value="Invoicing"
But.choice.list[5].text="Calendar for "+var->rep
But.choice.list[5].value="Scheduling"
But.choice.list[6].text="Contact Manager"
But.choice.list[6].value="Contact"
But.choice.list[7].text="Accounts Receivables"
But.choice.list[7].value="Recievables"
But.choice.list[8].text="Accounts Payables"
But.choice.list[8].value="Payables"
But.choice.list[9].text="Peach Tree"
But.choice.list[9].value="Peach"
But.choice.list[10].text="Word"
But.choice.list[10].value="Word"
But.choice.list[11].text="Excel"
But.choice.list[11].value="Excel"
But.choice.list[12].text="GoodBye "+var->rep
But.choice.list[12].value="exit"
elseif rep="zz" then
else
ui_msg_box("NO GO!","You've violated our rules"+chr(10)+chr(13)+"try again")
IF IS_OBJECT("REP") THEN
 :REP.SHOW()
 :REP.ACTIVATE()
 end
 eLSE
 :FORM.DIALOG("REP")
 :REP.CLOSE()
 END 
END IF
end if
this.maximize()

Script 1. The Main Menu form's OnInit script.

This is what you will see as the logon screen changes:

Fig1      Figure 1. The initial screen is empty of all choices.

Fig2  Figure 2. The logon screen popups in front of the empty main form.

Fig3     Figure 3. Karla logs in.

Fig4  Figure 4. This application has so many options that I had to design a custom Data Entry form as well.

Fig5

Figure 5. When I log in, all the buttons are visible!

Fig6

Figure 6. I even customize the text on the buttons to show the user name.

I will not show all the coding for the Choice form but it is included for download on this site. Here is the Text Changer part of the code:

elseif
Rep="Jack".or.rep="Raul".or.rep="rv" then
twostbtn1.choice.list.redim(11) 
Choices:Twostbtn1.font.size=8
Twostbtn1.choice.list[1].text="Member New Changes"
Twostbtn1.choice.list[1].value="Standard"
Twostbtn1.choice.list[2].text="Provider Data Entry"

Script 2. Part of the Text Change code.

All was still not well! They then asked me to eliminate the Logon Screen altogether and have my application look up the Windows user name!

Now how was I supposed to do this? I spent about a week trying to get the name using Declare and Declarestruct commands from Xbasic. I emailed acouple of you programmers out there and no one seemed to have done this successfully. I therefore changed my way of thinking and came up to this approach:

Use another program as an addon!

I found this little gem called ‘GroundControl’. And what a find it is! This shareware program sells for $39.95. I used its commands to get the Windows user id and wrote it to a text file that Alpha Five can then read.

This is what the log.txt file actually looks like. You can see how the code works with this text:
01/02/00 10: 41: 25 User Name: Jack
word 1 2 3 4 5 6 7

Here are the codes for both programs:

dim global rep as c
dim file_Pointer as p
dim filename as c
filename="c:\log.txt"
IF FILE.EXISTS("c:\log.txt") THEN
 FILE.REMOVE("c:\log.txt") 
END IF
sys_shell("C:\GroundControl\gc.exe /r c:\logontext.gc")
file_pointer=file.open(filename,FILE_RW_SHARED)
text=file_pointer.read_line()
file_pointer.close()
rep=word(text,7)
IF REP="" THEN
 rep="zz"
END IF

Script 3. My autoexec script. This script launches GroundControl to get the user id in a text file.

Here is the groundcontrol code, always called *.gc. It is included in the download as well:

Fig7

Figure 7. The GroundControl code.

    Here are some of the problems I had with System commands and Windows variables that GroundControl takes charge of:

  1. All system variables, resources, computer name, user name etc
  2. Send keys commands. Alpha Five is fairly slow in sending keystrokes to other programs and Ground Control is incredibly fast.

Please note: in the GroundControl code in Fig 7 I had to use some delay commands so that each application could finish its tasks.

Ira Perlow has suggested an alternative to the use of GroundControl. He simply writes a text file to each user's computer with the user name. He then makes the text file read-only, and Alpha Five reads this file on start-up. Unfortunately, in my application more than one user can be on any given machine in the course of a day, so Ira's approach wouldn't work for me.

Click here to download the graphs, scripts and sample data for this article!

1/2/00

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

Return to home