The purpose of this course is to apply the techniques learned in 266371to the construction of large programming projects. We will follow a set of guidelines that will lead us through the process of creating such projects. Each step in this process requires new tools. These tools range from simple new techniques in c++, problem solving patterns, interface design techniques, to more complex Windows techniques.
Once you have a general idea of the scope of a project, the first step is to create an interface for the program. This allows the user to decide if you have achieved all that they require in the project and also make critical comments about the applicability of the interface (does this interface meet standard requirements of the user such as standard forms used in professions).
The user interface for a program frequently starts its life as a series of drawings, cut outs and other very childish looking objects. This is because the group that designs the interface is often composed of designers and programmers who want to be free to quickly change the look of the interface after consulting with the client. Experts on interface design often declare that programmers should not create interface designs since they are not design experts. The problem with this that except in large projects (programs created for large scale distribution), the budget for projects seldom includes an interface expert.
With this in mind programmers should learn as much as possible about standard interface designs and learn to prototype interfaces to get user feedback. In addition, you should learn how to package frequently used interface items so they can be easily reused. Dialogs such as those use to retrieving standard the name and address of a person should be the same every time they are used in a suit of programs. Before designing a interface we will consided the class structure of information.
In your first lab you are asked to create a class person composed of a name object and an address class object. Both the name and the address will have an interface associated with them, and these interface objects should be used in constructing person. In the case of address, there will be a change of address dialog box. This box should be available to person so that change of address for a person will look the same as change of address for a business (another class that would use the address class).
We will consider design of classes and interface in a simplified course listing program. Each course will have a number and a professor (no students to begin with). Our program will have a list box with all courses listed. We will start by designing the professor class and the dialog boxes needed to maintain members of this class.
First we need a dialog box that will retrieve information about a professor. It has been determined that we will need a first name, last name, middle initial, rank, office and phone. This dialog should provide a method for gathering that data. There are a few new items in this box. First notice that the ok button appears to be greyed out. This indicates that it has been disabled. We want all of the fields to be filled in before the user can click ok, so we have added a set of functions that will disable ok until the fields have been filled. In addition, there are only three choices for the rank of a professor. We could have used a set of radio buttons for these choices, but chose instead to use a TComboBox (pull down listbox with a choice appearing at the top) to display the choices. We will use this again to display the list of professors when we create a new course listing. |
|
When the combo box arrow is selected, the entire list of choices appears, and whichever is selected will appear as the sole entry in the box after selection. |
Also notice that only part of the phone number is collected, since all phones at the school have area code 920 and exchange 465. This means the data returned from the dialog must me manipulated to add the constant parts, or whenever the data is printed these parts must be added. I have just stored the complete number, but this may not always be the best solution.
First create your dialog box as you did in the past. The new feature is the combo box. When inserting the combo box make sure to pull the bottom of the box far enough down to show at least some of your choices. If you don't do this, selecting the arrow will not display any choices. |
|
| Make sure to use the following options for your ComboBox. |
The first change in the code is an instance variable for the ok button. We treat the button as a window when we write code for the BN_DISABLE message. |
|
| The button disable command is found under the ok button. |
The code checks to see if each of the fields contains a non-trival string.
void ProfDlg::OkBNDisable ()
{
// INSERT>> Your code here.
int ok = _firstName->GetWindowTextLength() > 0 &&
_lastName->GetWindowTextLength() > 0 &&
_initial->GetWindowTextLength() > 0 &&
_phone->GetWindowTextLength() > 0 &&
_office->GetWindowTextLength() > 0;
okButton->EnableWindow(ok);
}
Finally to make sure this function is called whenever one of the fields is updated, for each field we add a handler for the EN_CHANGE message. This message is found under each instance variable. Each of these handlers consists of a call to OkBNDisable. |
The use of transfer buffers in this dialog is pretty standard. The new item is the combo box, _rank. The index of the selected item is the same as the value of the rank in the class Professor. AddString is used to prime the combo box. The second parameter is a boolean indicating whether or not the item is the current selection. The default is false. Once again remember that the area code and exchange for the phone number is constant and must be appended to the value stored in the professors class. One could also handle this as a software problem and append when information is requested. Notice that I tested the results by displaying the new information using a MessageBox. This code is commented out after the test is complete.
void Week1_98ListBox::cmAddProf ()
{
// INSERT>> Your code here.
ProfDlgXfer tb;
tb._firstName[0]='\0';
tb._initial[0]='\0';
tb._lastName[0]='\0';
tb._phone[0]='\0';
tb._office[0]='\0';
tb._rank.AddString("Assistant",true);
tb._rank.AddString("Associate");
tb._rank.AddString("Full");
if (ProfDlg(&tb,this).Execute()== IDOK)
{
int rank = tb._rank.GetSelIndex();
char phone[255];
strcpy(phone,"920-465-");
strcat(phone,tb._phone);
Professor p(tb._lastName,tb._firstName,tb._initial,tb._office,phone,rank);
/* Test prof info before going on
char buff[255];
p.completeList(buff);
MessageBox(buff,"New Prof"); */
_professors.insertItem(p);
}
}
Our professor information dialog box can be used for editing the information about a professor, but before we can edit that information, we have to find the professor and get the current information into the dialog. In this section we add a second dialog box used to select the professor, learn how to handle double clicks in listboxes, and see how existing information is loaded into our information dialog.
This dialog contains only a list box and you can view it if you download the complete project. The list box is not sorted, so that when you select an item, the index you have selected is the same as the subscript of the item in the array of professors.
| Create a handler for Double Click of the listbox instance variable in the dialog. | |
| This handler must call the same handler as the ok button. This handler is listed in the header file for dialog boxes (bc45/include/owl/dialog.h) as CmOk. |
void ProfListDlg::LBNDblclk ()
{
// INSERT>> Your code here.
CmOk();
} |
This dialog is used both in editing and deleting faculty members. Deleting is fairly straight forward and you can see this by downloading the whole program. The editing code follows:
void ProfWindow::cmEditProf ()
{
// INSERT>> Your code here.
int which = _professors->GetSelIndex();
if (which >=0)
{
Professor p =(*_profList)[which];
ProfDlgXfer tb;
strcpy(tb._firstName,p.first().c_str());
strcpy(tb._initial,p.initial().c_str());
strcpy(tb._lastName,p.last().c_str());
strcpy(tb._phone,p.phone().c_str());
strcpy(tb._office,p.office().c_str());
tb._rank.AddString("Assistant");
tb._rank.AddString("Associate");
tb._rank.AddString("Full");
tb._rank.Select(p.rank());
if (ProfDlg(&tb,this).Execute()== IDOK)
{
int rank = tb._rank.GetSelIndex();
char phone[255];
strcpy(phone,"920-465-");
strcat(phone,tb._phone);
Professor p(tb._lastName,tb._firstName,tb._initial,tb._office,phone,rank);
(*_profList)[which]=p;
Invalidate();
}
}
else
MessageBox("Must select an item before editing");
}
}
In this section we discussed the use of combo boxes and the double-click message used in implementing this interface. The interface was used in a simple problem, but in a large problem, you might implement the entire interface without creating the application classes. To see if the interface meets the user's needs, you can create the operation handlers and create classes for each dialog. Call dialogs from the handlers that will use them and let user see the effect.
Click here to get the code to this point. The rest of this problem is discussed in Week 2.