Your pet store has a list of dogs, cats and birds that it has on hand. A picture (we will use one icon for each type of animal) each animal along with its name is shown in the main window. When a visitor wants to know more about a given animal, they click on the animals picture and dialog appears with the name and type of the animal and age. If the customer buys an animal, that animal should be deleted from the list and picture. The owner should be able to add new animals to the list and their picture and name should appear on the screen..
We will have to have a purely virtual class Pet with decendent classes Dog, Cat and Bird. The main window will have an area (on a rectangular grid) set aside for each pet in an array of pet pointers. We will need a file of pets that can be updated. Once we know where each icon is we must associate that rectangle with an entry in the array so we can retrieve information and delete if the pet is sold. The EvPaint function will use an iterator to display items in the array at predetermined places on the screen and invert the rectangle of the selected pet if there is a pet selected. Finally we will have to develop three icons to represent the pictures of the pets. If you don't want to draw or find your own icons, you can download a zipped file of clipart pets from Microsoft by clicking here .
The icons I have provided are 64x64 with 256 colors. The actual picture area of one of these icons is 32 pixels by 32 pixels. I positioned the first icon to the point (10,10) this moved the first picture out of the corner. I also made a 64x64 rectangle for each of the icons so that there would be space between the icons. My grid had for entries per row, so the fifth icon was placed at (10,74). If the user clicks the left mouse button in one of the 64x64 rectangles with an icon, I used the TDC function InvertRect to invert the rectangle (in this case the third item in row 1). All of this required that the position of each rectangle be computed either from the subscript of the Pet or from the coordinates of the point where the click occurred.
I stored the selected rectangle as a class member of the main window, so that I could deselect (by inverting the rectangle again). I also used this information in the EvPaint function to invert the rectangle after redrawing the window. In addition I wanted to intercept clicks that were outside the icon display area. These clicks should be interpreted as a deselect. Before inverting the newly selected rectangle in the left button down handler, I computed the selected item. If it was less than 0 or greater than the number of pets, the click was not on an icon, so the new rectangle was not selected and the selection was set to -1 (no pet selected).
The following is an example of a dialog that could be used to get the information about the new pet. You must create a dialog to do this. The radio buttons should be created as a group .
| Compute the rectangle from point after mouse click | TDC *dc = new TClientDC(*this);
int top = (point.y-10)/64 * 64 + 10;
int left = (point.x-10)/64 * 64 + 10;
if (petSelected >=0)
dc->InvertRect(rectSelected);
rectSelected.Set(left,top,left+32,top+32);
petSelected = (left-10)/64 + 4*(top-10)/64;
if(petSelected >=0 && petSelected < petCollection.numberInArray() )
dc->InvertRect(rectSelected);
else
petSelected = -1;
delete dc; |
| Compute the point where the ith icon is displayed in EvPaint. | int top = 10 + 64 * (i/4);
int left = 10 + 64 * (i%4); |
I wanted each pet type to read itself, so I first read the type of pet as an integer then used an abstract factory to create the pet. Next the pet read itself and finally since I only used three TIcon pointers, I set the icon with much the same technique as creating the pet in the first place.
ifstream in("pets.pet");
Pet* typePtr[] = {&Dog(),&Cat(),&Bird()};
TIcon* icons[]={dog,cat,bird};
int howMany;
in >>howMany;
for (int i = 0; i < howMany;i++)
{
int type;
in>>type; // what type of pet
char dump[25];
in.getline(dump,25); // clear end of line marker
PetPtr pet(Pet::create(typePtr[type])); //use factory to create the pet.
pet->read(in); //pet reads itself
pet->setPic(icons[type]); //add the icon
petCollection.insertItem(pet);
}
in.close();
The write function for the file is much the same as previous write and paint functions. Each pet must write its type as an integer first followed by other information. The main write function, writes the number of pets, and then uses an iterator to write the rest of the file.
Scenarios are do on the Thursday of Week 11