[ Pobierz całość w formacie PDF ]
.5.The header for the Globals unit.///////////////////////////////////////// File: Globals.hfile:///D|/DOWNLOAD/charlie_calvert's_borland_c++_builder_unleashed/ch14.htm (18 of 50) [10/10/2000 1:13:44 AM]Ch 14 -- Sessions and Relational Real-World Databases// Project: KdAdd// Copyright (c) 1997 by Charlie Calvert//#ifndef GlobalsH#define GlobalsHAnsiString GetError(int ErrNo, AnsiString &S);#endifListing 14.6.The main module for the Globals unit.///////////////////////////////////////// File: Globals.cpp// Project: KdAdd// Copyright (c) 1997 by Charlie Calvert//#include#pragma hdrstop#include "Globals.h"#define ERR_STRING_SIZE 255AnsiString GetError(int ErrNo, AnsiString &S){S.SetLength(ERR_STRING_SIZE);LoadString(HINSTANCE(HInstance), 1, S.c_str(), ERR_STRING_SIZE);return S;}Listing 14.7.The custom RC file for the project.This is a stub to be filled out later.#include "kderrs.inc"STRINGTABLE{KDERR_CASESTATEMENT, "Command fell through case statement"}file:///D|/DOWNLOAD/charlie_calvert's_borland_c++_builder_unleashed/ch14.htm (19 of 50) [10/10/2000 1:13:44 AM]Ch 14 -- Sessions and Relational Real-World DatabasesListing 14.8.The include file for the project has only one entry.This is a stub to be filled out later.#define KDERR_CASESTATEMENT 1The pages in the TPageControl are hidden from view in Figure 14.1.In Figure 14.3 through Figure 14.6, you cansee the remaining TTabSheet objects.FIGURE 14.3.The tab sheet for the Address table.FIGURE 14.4.The tab sheet for the Phone table.FIGURE 14.5.The tab sheet for the E-mail table.Using the kdAdd ProgramThe kdAdd program has the minimal functionality needed to support the user's needs.For example, you can performInsert, Post, Delete, and Cancel operations on all the tables.Access to these features is provided through both themenus and a speedbar.You can also set the index to the Company, First, or Last fields of the kdNames table.Finally, you can search on either the Company, First, or Last fields.FIGURE 14.6.The tab sheet for Memo.Setting Up the Index for kdAddOne of the hubs around which the kdAdd program revolves involves the code that controls the index for the program.This code is called from several different places in the program.The obvious place to start studying it, however, is inthe response method for the menu items that let the user change the index:void __fastcall TForm1::SetupIndex(TObject *Sender){switch (dynamic_cast(Sender)->Tag){case 100:DMod->NamesTable->IndexName = "idxLastName";break;case 101:DMod->NamesTable->IndexName = "idxFirstName";break;case 102:DMod->NamesTable->IndexName = "idxCompany";break;case 103:DMod->NamesTable->IndexName = "";break;file:///D|/DOWNLOAD/charlie_calvert's_borland_c++_builder_unleashed/ch14.htm (20 of 50) [10/10/2000 1:13:44 AM]Ch 14 -- Sessions and Relational Real-World Databases}}void __fastcall TForm1::IndexClick(TObject *Sender){SetupIndex(Sender);DMod->NamesTable->FindNearest(OPENARRAY(TVarRec, ("AAAA")));}The code has three menu choices for changing the index.The first lets the user set the index to the last name; thesecond, to the first name; and the third, to the company name.All three menu items are attached to the IndexClickmethod shown here.IndexClick calls SetupIndex to do the real work.You use the tag property of the TMenuItem that is clicked todecide which index to choose:switch (dynamic_cast(Sender)->Tag)This way, you can call the function with a simple one-line command:SetupIndex(Sender);After the index has been set up properly, you can search for the first relevant record in the database:DMod->NamesTable->FindNearest(OPENARRAY(TVarRec, ("AAAA")));The goal of this line is to skip over all the records that contain blanks in the field on which you're searching.Forexample, if you switch to the company index, you might find 20, 100, or even 5,000 records in the table that have noinformation in the Company field.To skip over these records, you can search for the first row that begins with theletter A.Searching for RecordsThe program also uses the SetupIndex method when it is conducting searches.As I stated previously, you can usethree possible menu items to start a search.The first searches on last names; the second, on first names; and the third,on a company name.I have assigned the same values to the Tag fields of these TMenuItems that I did to the Tagfields of the TMenuItems concerned with switching indexes.That way, I can set up the index properly with a simplecall to SetupIndex:AnsiString IndexName, S;if (InputQuery("Search for Name", "Enter Name: ", S)){IndexName = DMod->NamesTable->IndexName;SetupIndex(Sender);DMod->NamesTable->FindNearest(OPENARRAY(TVarRec, (S)));DMod->NamesTable->IndexName = IndexName;file:///D|/DOWNLOAD/charlie_calvert's_borland_c++_builder_unleashed/ch14.htm (21 of 50) [10/10/2000 1:13:44 AM]Ch 14 -- Sessions and Relational Real-World Databases}As you can see, the code also saves the current index so that the current state of the index can be restored after thesearch:AnsiString IndexName;IndexName = DMod->NamesTable->IndexName;.// Code omitted hereDMod->NamesTable->IndexName = IndexName;The big point to notice here is how easily you can take care of these chores by using the VCL.BCB makes databaseprogramming easy, even when you're working with a fairly complex program.Inserting Data, Canceling OperationsBecause this database has five tables, you have to devise a technique for specifying the name of the table on which youwant to perform an insertion, deletion, or post.I use the TPageControl to handle these chores.In particular, Iassume that if the user is looking at the Address page, then he or she wants to perform an action on the kdAdds table,and if the user is looking at the first page, then he or she wants to perform an operation on the kdNames table, and soon:void __fastcall TForm1::Insert1Click(TObject *Sender){switch (dynamic_cast(*PageControl1->ActivePage).Tag){case 1:DMod->NamesTable->Insert();break;case 2:DMod->AddressTable->Insert();break;case 3:DMod->PhoneTable->Insert();break;case 4:DMod->EMailTable->Insert();break;}file:///D|/DOWNLOAD/charlie_calvert's_borland_c++_builder_unleashed/ch14.htm (22 of 50) [10/10/2000 1:13:44 AM]Ch 14 -- Sessions and Relational Real-World Databases}As you can see, I have set the Tag field for each of the pages to a unique value so that I can easily determine thecurrent page:switch (dynamic_cast(*PageControl1->ActivePage).Tag)If the user accidentally makes a wrong decision, he or she can undo the most recent operation on the currently selectedtable by clicking Cancel:void __fastcall TForm1::Cancel1Click(TObject *Sender){AnsiString S;switch (dynamic_cast(*PageControl1->ActivePage) [ Pobierz całość w formacie PDF ]