plik


ÿþRozdziaB 11 Formularze W tym rozdziale zbudujemy pozostaBe formularze do wprowadzania i edycji danych na potrzeby programu RENTMAN. Bd obsBugiwaBy tabele TENANT, PROPERTY, CALL, LEASE i WORDER. Skonstruowanie szerokiego wachlarza ró|nych formularzy powinno by dobrym wstpem do pózniejszej samodzielnej pracy z narzdziami Delphi. Formularze do edycji tabel TENANT i PROPERTY ró|ni si od innych u|yciem komponentu DBControlGrid. SBu|y on do wy[wietlania, w sposób tabelaryczny, wielu rekordów tego samego zbioru. Ró|nica midzy standardowym DBGrid a DBCtrlGrid polega na tym, |e w przeciwieDstwie do pierwszego, drugi umo|liwia przedstawienie jednego rekordu tabeli w kilku wierszach ekranu. Formularzy korzystajcych z komponentu DBGrid u|yjemy do tabel CALL i WORDER. Formularz TENANT Poniewa| formularz TENANT dziedziczy wBa[ciwo[ci fmControlGridForm, to z menu Delphi wybieramy opcj File\New, klikamy na stronie Forms w okienku dialogowym New Items, nastpnie wybieramy fmControlGridForm, klikamy kolejno opcj Inherit i zatwierdzamy przyciskiem OK. Formularz o nazwie fmControlGridForm1 powinien pojawi si w wizualnym projektancie Delphi. Zmieniamy nazw formularza (Name) na fmRTENCGD0 i nagBówek (Caption) na Tenant Edit Form (formularz do edycji tabel TENANT). Z menu File wybieramy opcj Use Unit i dwukrotnie klikamy na li[cie w pozycji RENDATA. Dziki temu systemowy formularz moduBu danych (fmRENTMAN) bdzie dostpny dla nowego formularza. 326 Cz[ II UWAGA Je[li kontrolki fmControlGridForm lub jakiegokolwiek jego rodzica zostaBy zabezpieczone, to bd oczywi[cie zabezpieczone w projekcie potomnym. Mo|emy chcie je odbezpieczy, aby uBatwi sobie ich adjustacj. Nale|y wówczas zaznaczy formularz, wybra opcj Lock Controls z oferty Edit i usun zaznaczenie. Kontrolki musz by odblokowane jedynie wtedy, gdy wcze[niej zostaBy zabezpieczone albo w formularzu, albo w jednym z formularzy nadrzdnych. Domy[lnie dostp do wszystkich elementów jest odblokowany. Pierwsz rzecz do wykonania jest zmiana rozmiarów formularza. Ustalamy wysoko[ na 400 i szeroko[ na 565. UBatwiamy w ten sposób umieszczenie na blankiecie wielu pól tabeli TENANT. Usuwanie elementów dziedziczonych Na blankiecie znajduj si trzy przyciski dodane do fmEditForm. Poniewa| formularz jest przeznaczony do szybkiego wprowadzania danych, nie bd potrzebne. Mimo to nie mo|na ich usun, gdy| Delphi nie pozwala na likwidacj dziedziczonych elementów kontrolnych. Istnieje jednak sposób umo|liwiajcy ukrycie ich praktycznie we wszystkich zastosowaniach i wykorzystanie do innych celów zajmowanego przez nie miejsca na formularzu. Klikamy panel [rodkowy i ustawiamy wBa[ciwo[ci Enabled i Visible na False. Poniewa| panel peBni rol kontenera przechowujcego trzy przyciski, to jego wyBczenie wyBczy równie| jego elementy. Panel wyBcza si tylko wtedy, gdy zaistnieje potrzeba usunicia przycisków z formularza. Ustawiamy wyrównanie panela (wBa[ciwo[ Align) na alNone, by przestaB sobie ro[ci wyBczne prawo do [rodkowej cz[ci formularza. Kolejno ustawiamy wBa[ciwo[ Align panelu górnego na alClient i koDczymy, klikajc prawym klawiszem myszy na panelu [rodkowym, wybierajc z podrcznego menu opcj Send to Back. Panel [rodkowy i jego przyciski powinny znikn z formularza. Wyja[nijmy jeszcze, dlaczego nie mo|na wyBczy samych przycisków. Przede wszystkim postawmy sobie pytanie: czy musimy rezygnowa z klawiszy szybkiego dostpu, nawet gdy odpowiadajce im elementy nie s widoczne? Otó| bez wzgldu na to, czy przyciski wida, czy nie, ich klawisze szybkiego dostpu s aktywne, dopóki nie zostan wyBczone. Oznacza to, |e wci[nicie przycisku jest równowa|ne z u|yciem klawisza. Zasadniczo przycisk nie powinien by usuwany caBkowicie, a co najwy|ej ukryty. Takie uzasadnienie mo|na przyj do wiadomo[ci, cho trudno nie zgodzi si z opini, |e nie powinno si u|ywa ukrytych lub nieoznaczonych funkcji. Je[li jaka[ procedura jest rzeczywi[cie wa|na, to powinna by uwidoczniona na ekranie. Formularze 327 Konfiguracja DBCtrlGrid Nastpujce czynno[ci sBu| do skonfigurowania komponentów nowego formularza: 1. Uruchomi serwer bazy danych InterBase (o ile jeszcze nie dziaBa). 2. Wcisn kombinacj klawiszy SHIT+F12, aby uaktywni okienko dialogowe View Form (widok formularza) i dwukrotnie klikn na module danych dmRENTMAN. Zarejestrowa si na serwerze swoim identyfikatorem i hasBem. 3. Powróci do formularza, wciskajc ponownie klawisze SHIFT i F12 oraz wybierajc z listy odpowiedni formularz. 4. Wybra komponenty DBCtrlGrid iDBNavigator oraz zmieni ich wBa[ciwo[ DataSource na dmRENTMAN.dsTENANT; odznaczy kontrolk DBNavigator. 5. Tabela TENANT liczy jedena[cie pól. Dziesi z nich podlega edycji, a jedna dostpna jest jedynie w trybie do odczytu. Umie[ci na pierwszym z trzech paneli DBCtrlGrid jeden komponent DBText i dziesi komponentów DBEdit. Nie umieszcza niczego na panelach przekre[lonych po przektnej szarymi liniami. 6. Ustawi wysoko[ ka|dego komponentu nale|cego do DBCtrlGrid na 19. 7. Umie[ci na formularzu DBCtrlGrid jedena[cie komponentów etykiet i poukBada je nad ka|d z wstawionych kontrolek. 8. ZakoDczy ustawianie komponentów zgodnie ze wskazaniami tabeli 11.1 oraz rysunkiem 11.1. WSKAZÓWKA Aby umie[ci powtarzajce si kontrolki bez wielokrotnego wracania do palety komponentów, nale|y po wklejeniu ka|dego elementu: 1. Wcisn i trzyma klawisz SHIFT. 2. Klikn odpowiedni element palety (mo|na zwolni klawisz SHIFT). 3. Klikn na formularzu tyle razy, ile kopii skBadnika potrzebujemy. 4. Klikn na ikonce ze strzaBk palety komponentów, aby zakoDczy tryb powtarzalnego wklejania skBadników. 328 Cz[ II Tabela 11.1. Komponent DBCtrlGrid i jego atrybuty nazwa komponent szeroko[ Pole tabeli etykieta dteTENANT_NUMBER DBText 30 TENANT_NUMBER No. Nr dedNAME DBEdit 121 NAME NAME (Nazwisko) dedHOMEPHONE DBEdit 90 HOMEPHONE HomePhone Telefon domowy dedWORKPHONE DBEdit 90 WORKPHONE WorkPhone Telefon sBu|bowy dedICEPHONE DBEdit 90 ICEPHONE Emergency Phone Telefon alarmowy dedEMPLOYER DBEdit 121 EMPLOYER Employer Pracodawca dedEMPLOYERADRESS DBEdit 121 EMPLOYERADRESS Employer Adress Adres pracodawcy dedEMPLOYERCITY DBEdit 121 EMPLOYERCITY City Miasto dedEMPLOYERSTATE DBEdit 25 EMPLOYERSTATE State Stan dedEMPLOYERZIP DBEdit 90 EMPLOYERZIP Zip Kod dedCOMMENTS DBEdit 530 COMMENTS Comments Uwagi Rysunek 11.1 ilustruje koDcowy wygld formularza Formularze 329 Rysunek 11.1. Nowy formularz z komponentem DBCtrlGrid. WSKAZÓWKA Je[li chcemy zmieni jak[ wBa[ciwo[ kilku komponentów jednocze[nie, to mo|na to zrobi nastpujco: 1. Klikn na pierwszym komponencie. 2. Wcisn i trzyma klawisz SHIFT. 3. Wybra kolejne komponenty. 4. Wcisn klawisz F11, aby przenie[ si do Inspektora Obiektów. Na li[cie bd tylko wBa[ciwo[ci wspólne dla wszystkich zaznaczonych komponentów. Zmiana jednej warto[ci spowoduje zmian we wszystkich zaznaczonych elementach. 5. Mo|na równie| klikn prawym klawiszem myszy na dowolnym z zaznaczonych komponentów, aby otrzyma menu, umo|liwiajce dziaBanie na wszystkich wybranych elementach. UWAGA Kontrolka DBEdit, która nie jest podBczona do |adnego otwartego zbioru danych, wy[wietla swoj nazw w okienku edycji i nie ma sposobu, aby j usun w czasie projektowania formularza. Dopiero podczas pracy, kontrolka oczy[ci swoje pole edycji. Inaczej zachowuj si komponenty Edit. Ich okna edycyjne mo|na oczy[ci podczas projektowania, usuwajc zawarto[ wBa[ciwo[ci Text. 330 Cz[ II Wyrównanie komponentów Do szybkiego i dokBadnego wyrównywania oraz dokonywania zmian rozmiaru elementów sterujcych najlepiej jest u|ywa podrcznego menu, rozwijajcego si po klikniciu prawym klawiszem myszy. Menu kontekstowe projektanta formularzy (Form Designer) umo|liwia Batw zmian wielko[ci oraz wyrównywanie komponentów zarówno w pionie, jak i poziomie. WSKAZÓWKA Chcc wyrówna kilka skBadników naraz, nale|y najpierw klikn element stacjonarny. Powodem jest oczekiwanie przez projektanta formularzy na  odwoBanie si do oznaczonego najpierw komponentu i wyrównanie pozostaBych komponentów w odniesieniu do niego. Ustawianie kolejno[ci tabulacji (Tab Order) Po umieszczeniu na swoim miejscu wszystkich komponentów, trzeba sprawdzi, czy prawidBowo jest ustawiona kolejno[ tabulacji (wBa[ciwo[ TabOrder). Przy pomocy edytora porzdku tabulacji (Tab Order editor) mo|na modyfikowa kolejno[ tabulacji jednocze[nie dla wszystkich komponentów. Edytor uruchamia si, wybierajc opcj Tab Order z menu Edit. Zmiany w kolejno[ci skBadników dokonuje si, wciskajc przyciski strzaBek (powodujce obni|anie lub podnoszenie elementu na li[cie). Dostpna jest równie| technika  przecignij i upu[ . Po ustaleniu kolejno[ci tabulacji nale|y zachowa formularz pod nazw RTENCGD0.PAS (R- od RENTMAN system, TEN- od nazwy tabeli TENANT i CGD- od dbControlGriD; 0- element oznaczajcy wersj formularza). WSKAZÓWKA Prawie wszystko co mo|na zrobi w Delphi przy pomocy myszy, daje si wykona klawiatur. Tablica 11.2 wylicza niektóre u|yteczne skróty klawiszowe. Nale|y zwróci uwag, |e u|ywanie klawiatury, której ukBad odbiega od ustawienia domy[lnego Delphi, nie gwarantuje aktywno[ci skrótów. Tablica 11.2. Niektóre skróty klawiszowe wspólne dla elementów Delphi. Skrót Funkcja F11 PrzeBcznik do Inspektora obiektów (Object Inspector). F12 PrzeBcznik do edytora kodu lub projektanta formularzy (symetryczny na zasadzie  tam i z powrotem ). Formularze 331 Skrót Funkcja CTRL+ENTER Odpowiada podwójnemu klikniciu w inspektorze obiektów. ALT+ Rozwija list w inspektorze obiektów. TAB, StrzaBki Przenosi midzy wBa[ciwo[ciami lub elementami sterujcymi. CTRL+StrzaBki Przesuwa komponent wybrany w projektancie formularzy. SHIFT+StrzaBki Zmienia rozmiar komponentu wybranego w projektancie formularzy. SHIFT+F12 Zaznacza formularz. ALT+0 Zaznacza okno. F9 Uruchamia program. F1 W projektancie formularzy wywoBuje pomoc dotyczc bie|cego elementu. F5 Uaktywnia/dezaktywuje puBapk programow (breakpoint) zakBadan w bie|cej linii. CTRL+TAB Przej[cie do nastpnego pliku kolejki edytora kodu. CTRL+SHIFT+TAB Przej[cie do poprzedniego pliku kolejki edytora kodu. RENTMAN i pola automatycznie inkrementowane Tylko jedno zadanie dzieli nas od mo|liwo[ci przetestowania utworzonego formularza. Zauwa|my, |e formularz nie powinien umo|liwia edycji pola TENANT_NUMBER. Allodium oczekuje, aby podczas dodawania do bazy informacji o nowym lokatorze system automatycznie generowaB numer najemcy. Czynno[ wypeBniania rubryki TENANT_NUMBER mo|e wykonywa sama aplikacja, ale oznacza to bdzie, |e poprawne rekordy tablicy TENANT bdzie mo|na wprowadza jedynie za pomoc programu RENTMAN. Jak stwierdzono w rozdziale 20, najlepszym miejscem na oprogramowanie reguB przetwarzania jest serwer. ReguBy zaimplementowane na serwerze s dostpne wszystkim aplikacjom, nie tylko tym utworzonym przy pomocy Delphi. {danie, aby elementy pola byBy sekwencyjnie ponumerowane, jest oczywi[cie ograniczeniem mieszczcym si w definicji reguBy przetwarzania. Poniewa| system CASE, u|yty do budowy bazy RENTMAN, nie tworzy obiektów INTERBASE zdolnych do wymuszenia automatycznego wypeBniania kolumn, to 332 Cz[ II musimy skonstruowa je sami. Bdziemy potrzebowa dwóch nowych obiektów bazy RENTMAN: generatora i procedury zdarzenia. Generator InterBase jest u|ywany do tworzenia sekwencji liczb, które bd wstawiane do kolumny tabeli. Faktyczne wstawianie warto[ci wystpuje w czasie dziaBania procedur inicjowania i zachowywania. W tym przypadku procedura zdarzenia bdzie u|ywana do uzupeBniania warto[ci rubryki TENANT_NUMBER. Procedura zdarzenia bdzie dziaBaBa przez caBy czas wprowadzania rekordu do tabeli TENANT. Po uruchomieniu bdzie wywoBywaBa funkcj GEN_ID(), aby dostarczyBa kolejnej warto[ci generatora. Funkcja powikszy wewntrzny licznik i po kolejnym wywoBaniu zwróci nastpn warto[. Allodium chce, by oprócz tabeli TENANT równie| inne zbiory danych aplikacji zawieraBy pola wypeBniane automatycznie. Oznacza to, |e generator i procedura zdarzenia bdzie potrzebna dla ka|dego z nich. Jedynym wyjtkiem jest tabela WODETAIL, ale jej specyfik omówimy troch pózniej. Zamiast oddzielnie definiowa nowe obiekty, lepiej jest utworzy je jednocze[nie, u|ywajc skryptu SQL. Procedur mo|na napisa w edytorze kodów Delphi, który zawiera atrakcyjne narzdzia, uBatwiajce pisanie programów SQL. Po wprowadzeniu kodu skryptu nale|y go uruchomi narzdziem Windows ISQL systemu Inter Base. PowstaBe w ten sposób obiekty utworzone zostan w bazie danych RENTMAN. Ni|ej opisana procedura pozwala stworzy generator i procedur zdarzenia dla programu RENTMAN: 1. Wybra z menu opcj File\New. W okienku dialogowym New Item wybra Text i zatwierdzi klawiszem OK. W edytorze kodu Delphi powinien otworzy si nowy plik. 2. Zachowa zbiór pod nazw RSYSTRG0.SQL. Zapisanie zbioru przed rozpoczciem wprowadzania kodu pozwoli korzysta z uBatwieD skBadniowych, które uruchamiaj si dziki rozszerzeniu SQL. 3. Wprowadzi do pliku skrypt zawarty w listingu 11.1 i zapisa go na dysku. Upewni si, |e deklaracja CONNECT wskazuje [cie|k dostpu do systemu RENTMAN. 4. Uruchomi InterBase Windows ISQL. W ofercie ISQL Script wybra opcj File\RUN. W okienku zachty wpisa nazw pliku zawierajcego skrypt. 5. Na pytanie, czy umie[ci wynik dziaBania skryptu w oddzielnym pliku odpowiedzie: nie. Dziki temu informacja bdzie wy[wietlona natychmiast w Windows ISQL. 6. Po krótkiej przerwie na ekranie powinien ukaza si komunikat, |e skrypt zostaB wykonany bezbBdnie. Generator i procedura zdarzenia s utworzone. Formularze 333 7. Zamkn Windows ISQL i powróci do Delphi. 8. Wcisn kombinacj SHIFT+F12, aby uaktywni okienko dialogowe View Form (widok formularza). Klikn dwukrotnie na module danych dmRENTMAN. 9. Klikn dwukrotnie na komponencie daTENANT, aby wywoBa edytor pól (Fields editor). 10. W inspektorze obiektów zmieni na False wBa[ciwo[ Required kolumny TENANT_NUMBER i zamkn edytor pól. Dziki temu RENTMAN nie bdzie oczekiwaB wprowadzania warto[ci do rubryki. WypeBnianie kolumny przejmie InterBase za po[rednictwem nowo utworzonego generatora i procedury zdarzenia. 11. Powtórzy proces ustawiania warto[ci False wBa[ciwo[ci Required dla pozostaBych tabel. Nale|y pamita, |e gBówny klucz tabeli WODETAIL skBada si z dwóch oddzielnych kolumn: WORDER_NUMBER i WODETAIL_ LINE_ NUMBER. Obie kolumny powinny wypeBnia si automatycznie. 12. W inspektorze obiektów wybra stron event i dwukrotnie klikn zdarzenie AfterPost. Przy pomocy edytora wpisa kod: taTENANT.Refresh; WywoBanie metody Refresh (od[wie|) jest niezbdne, aby powiadomi program RENTMAN, o automatycznie wygenerowanej przez serwer warto[ci pola TENANT_NUMBER. 13. W ten sam sposób oprogramowa zdarzenia PostAfter pozostaBych, wymagajcych tego kolumn. Nale|y si upewni, |e |adna tabela nie zostaBa pominita. Listing 11.1 zawiera tekst skryptu sBu|cego do utworzenia generatora i procedury zdarzenia. WSKAZÓWKA Delphi potrafi importowa wikszo[ wizów i reguB logiki aplikacji bezpo[rednio z serwera SQL. Oznacza to midzy innymi, |e zdefiniowane na serwerze domy[lne warto[ci lub wizy pól mog by przeniesione do sBownika danych Delphi, a std do odpowiedniej aplikacji. Nie mo|na, niestety, skutecznie importowa w ten sposób automatycznego wypeBniania kolumn. DokBadniej mówic, kolumny zostan przeniesione, ale aplikacja nie bdzie widzie, |e serwer automatycznie 334 Cz[ II wypeBniB pole tabeli. ZnalazBszy si w sytuacji, gdy Delphi nie rozpoznaje dokBadnie warto[ci wprowadzanych przez serwer dla odczytania wBa[ciwych warto[ci rekordu, nale|y wywoBa odpowiedni metod od[wie|ania zbioru danych. Uruchomienie metody Refresh powinno doprowadzi do powiadomienia aplikacji o zmianach zrealizowanych przez serwer. WywoBanie poprzez zdarzenie AfterPost jest rozwizaniem dobrym, poniewa| odbywa si po zakoDczeniu wprowadzania zmian do rekordu. Listing 11.1. Skrypt SQL tworzcy generatory i procedury zdarzeD. CONNECT 'C:\DATA\RENTMAN\RENTMAN.GDB' USER 'SYSDBA' PASSWORD ¥''masterkey'; CREATE GENERATOR TENANT_NUMBER_GEN; CREATE GENERATOR PROPERTY_NUMBER_GEN; CREATE GENERATOR LEASE_NUMBER_GEN; CREATE GENERATOR CALL_NUMBER_GEN; CREATE GENERATOR WORDER_NUMBER_GEN; CREATE GENERATOR EMPLOYEE_NUMBER_GEN; CREATE GENERATOR WORK_TYPE_CODE_GEN; COMMIT WORK; SET TERM !! ; CREATE TRIGGER TENANTInsert FOR TENANT BEFORE INSERT POSITION 0 AS BEGIN NEW.TENANT_NUMBER = GEN_ID(TENANT_NUMBER_GEN, 1); END !! CREATE TRIGGER PROPERTYInsert FOR PROPERTY BEFORE INSERT POSITION 0 AS BEGIN NEW.PROPERTY_NUMBER = GEN_ID(PROPERTY_NUMBER_GEN, 1); END !! CREATE TRIGGER LEASEInsert FOR LEASE BEFORE INSERT POSITION 0 AS BEGIN NEW.LEASE_NUMBER = GEN_ID(LEASE_NUMBER_GEN, 1); END !! CREATE TRIGGER CALLInsert FOR CALL BEFORE INSERT POSITION 0 AS BEGIN NEW.CALL_NUMBER = GEN_ID(CALL_NUMBER_GEN, 1); Formularze 335 END !! CREATE TRIGGER WORDERInsert FOR WORDER BEFORE INSERT POSITION 0 AS BEGIN NEW.WORDER_NUMBER = GEN_ID(WORDER_NUMBER_GEN, 1); END !! CREATE TRIGGER EMPLOYEEInsert FOR EMPLOYEE BEFORE INSERT POSITION 0 AS BEGIN NEW.EMPLOYEE_NUMBER=GEN_ID(EMPLOYEE_NUMBER_GEN, 1); END !! CREATE TRIGGER WORKTYPEInsert FOR WORKTYPE BEFORE INSERT POSITION 0 AS BEGIN NEW.WORK_TYPE_CODE= GEN_ID(WORK_TYPE_CODE_GEN, 1); END !! CREATE TRIGGER WODETAILInsert FOR WODETAIL BEFORE INSERT POSITION 0 AS DECLARE VARIABLE NumLines INTEGER; BEGIN SELECT MAX(WODETAIL_LINE_NUMBER)+1 FROM WODETAIL WHERE WODETAIL.WORDER_NUMBER = ¥' NEW.WORDER_NUMBER INTO :NumLines; IF (NumLines IS NULL) THEN NEW.WODETAIL_LINE_NUMBER = 1; ELSE NEW.WODETAIL_LINE_NUMBER = NumLines; END !! SET TERM ; !! COMMIT WORK; WSKAZÓWKA Warto[ pocztkow zwracan przez generator InterBase mo|na okre[li przy pomocy komendy SET GENERATOR. Na przykBad: 336 Cz[ II SET GENERATOR TENANT_NUMBER_GEN TO 1000 spowoduje rozpoczcie numeracji od 1001. Podobnie SET GENERATOR TENANT_NUMBER_GEN TO 0 wyzeruje generator do ustawienia wyj[ciowego. Odnotujmy jeszcze specyfik kodu sBu|cego do wypeBniania odpowiednich kolumn tabeli WODETAIL. Specjalne potraktowanie tablicy wynika po prostu z konieczno[ci numerowania jej elementów bez zachowania naturalnej kolejno[ci. Zbiór WODETAIL przechowuje pozycje wykazów prac. Ka|dy wykaz zawiera z kolei swój wBasny zbiór ponumerowanych kolejno linii. Nie chcemy, aby pierwsza pozycja drugiego wykazu miaBa numer osiem tylko dlatego, |e pierwszy miaB siedem elementów. Poprawne rozwizanie polega na rozpoczynaniu od pocztku numerowania pozycji ka|dego wykazu prac. Zwrómy jeszcze uwag na wykorzystanie deklaracji COMMIT WORK do zachowywania bazy danych. Jest to godna polecenia metoda postpowania w skryptach InterBase SQL, gdy| zamyka transakcje rozpoczte przez serwer i zapisuje zmiany na dysku, co zabezpiecza przed utrat danych. Po powierzeniu dyskowi wyników transakcji, ISQL - zgodnie ze skryptem - uruchamia kolejne dziaBania systemu. DoBczenie formularza do aplikacji Aby przetestowa nowy formularz, musimy zakotwiczy go w gBównym menu systemu. W tym celu, w wizualnym projektancie formularzy, nale|y uruchomi gBówne okno programu- fmRSYSMAN, nastpnie w menu Tables klikn dwukrotnie na pozycji Tenants, by w koDcu przy pomocy edytora kodów wprowadzi nastpujc lini: fmRTENCGD0.Show; Pozostaje jeszcze wcisn klawisz F12, by powróci do projektanta formularzy. Formularze 337 Testowanie formularza TENANT UWAGA Zachowywanie projektu przed uruchomieniem jest bardzo dobrym zwyczajem. W razie problemów z aplikacj chroni przed niebezpieczeDstwem utraty wyników pracy. Aby system Delphi automatycznie zachowywaB zmiany w projekcie, nale|y w jego menu wybra opcj Tools\Environment Options\Preferences, a nastpnie zaznaczy pozycj przeBcznika Autosave options\Editor files Zmiany mo|na równie| zapisywa, u|ywajc przycisku Save Project z paska narzdziowego Delphi lub wybierajc opcj Save All z menu File. Majc zaznaczony fmRSYSMAN0, wybieramy z menu opcj File\Use Unit, a nastpnie z listy pozycj RTENCGD0. Aczymy w ten sposób moduB, zawierajcy formularz fmRTENCGD0, z gBównym oknem aplikacji RENTMAN. Od tej chwili formularz TENANT mo|e by wywoBywany z menu systemowego. Po zachowaniu zmian w projekcie mo|na przystpi do jego uruchomienia. Po zainicjowaniu aplikacji wciskamy klawisz F5, aby uaktywni nowy formularz. Sprawdzamy jego dziaBanie, klikajc w pasku DBNavigator-a przycisk wstawiania rekordów (oznaczony +). Przy wprowadzaniu linii sprawdzamy prawidBow realizacj wizów naBo|onych na baz danych (na przykBad pole State zawiera jedynie warto[ci Tx lub OK). W koDcu wstawiamy do bazy danych trzy nowe rekordy. Wygld nowego formularza ilustruje Rysunek 11.2. Rysunek 11.2. Formularz TENANT w czasie dziaBania programu. Ustawianie SpeedButton Przed zakoDczeniem prac nad formularzem, uaktywnimy na pasku narzdziowym aplikacji przycisk, umo|liwiajcy szybki dostp do tego formularza. Je[li aplikacja 338 Cz[ II jeszcze pracuje, to nale|y j wyBczy. W wizualnym projektancie formularzy musimy otworzy gBówne okno programu- fmRSYSMAN i klikn komponent SpeedButton (sbTenants), ustanowiony dla formularza TENANT. Przy pomocy klawisza F11 przeBczamy si do inspektora obiektów, a nastpnie wybieramy stron Events. Z rozwijalnej listy zdarzenia OnClick wybieramy pozycj Tenants1Click. Jest to nazwa zdarzenia, jak system Delphi utworzyB po dwukrotnym klikniciu opcji Tables\Tenants gBównego menu systemu (por. akapit  DodBczenie formularza do aplikacji ) Ustawiajc na Tenants1Click procedur obsBugi zdarzenia OnClick naszego przycisku, mo|emy by pewni, |e system zadziaBa na jego wci[nicie, tak samo jak na wybranie odpowiedniej pozycji menu. W rozdziale 13 zostanie omówiony sposób doBczania do przycisku  dymka obja[niajcego jego funkcj. W ten sposób zakoDczyli[my, na jaki[ czas, prac nad formularzem TENANT. Kolejnym obiektem naszego zainteresowania bdzie formularz tabeli PROPERTY. Formularz PROPERTY Z gBównego menu Delphi wybieramy opcj File\New, a nastpnie stron Forms w okienku dialogowym New Item. Klikamy ikon fmControlGridForm, potem opcj Inherit i zatwierdzamy klawiszem OK. W projektancie formularzy powinien ukaza si nowy formularz, dziedziczcy wBa[ciwo[ci klasy fmControlGridForm. Naszym najbli|szym celem bdzie przeksztaBcenie go tak, aby mógB sBu|y do edycji tabeli PROPERTY. Modyfikacj obiektu rozpoczynamy do zmiany nazwy na fmPROCGD0 oraz nagBówka na inny, odpowiedniego typu:  Formularz do edycji tabeli PROPERTY . Zachowujemy formularz w zródBowym katalogu aplikacji pod nazw RPROCGD0.PAS. Konfiguracja DBCtrlGrid Z dwudziestu dwóch pól tabeli PROPERTY siedem jest typu logicznego (boolean), a pozostaBe s polami tekstowymi lub numerycznymi. W nastpujcy sposób ustawiamy górny panel formularza: 1. Na górnym panelu umie[ci komponent DBText. 2. Wstawi jedena[cie elementów DBEdit oraz trzy komponenty kombinowane DBComboBox i rozmie[ci je na prawo i poni|ej skBadnika DBText. Formularze 339 3. Do kolejnych pozycji wBa[ciwo[ci Items pierwszej kontrolki DBComboBox wstawi nastpujce warto[ci, które bd obsBugiwa pole City tabeli PROPERTY: Oklahoma City Norman Edmond Dallas Richardson Plano 4. Do kolejnych pozycji wBa[ciwo[ci Items drugiego komponentu typu DBComboBox wstawi warto[ci, które bd wspóBpracowa z polem ADDITION tabeli PROPERTY: Deerfield Firewheel Legacy Hills Switzerland Estates Sherwood Rocknoll 5. Do kolejnych pozycji wBa[ciwo[ci Items trzeciego komponentu DBComboBox wstawi nastpujce warto[ci, które bd obsBugiwa pole City tabeli PROPERTY: Putnam City Oklahoma City Richardson Edmond Garland Dallas Plano 6. Skonfigurowa wBa[ciwo[ Style wszystkich trzech komponentów jako csDropDownList. Chroni to u|ytkownika przed mo|liwo[ci wpisania do pola nowej warto[ci i zmusza do dokonania wyboru spo[ród pozycji wprowadzonych w poprzednich punktach. 7. W ostatnim wierszu panela umie[ci siedem komponentów logicznych DBCheckBox. 8. Zaznaczy komponenty wstawione w punkcie siódmym i ustawi ich wBa[ciwo[ci ValueChecked oraz Valueunchecked odpowiednio na T i F. 9. Nad ka|dym z elementów utworzonych w poprzednich krokach umie[ci po jednej etykiecie. 10. Kontrolka DBText powinna by umieszczona w lewym górnym rogu panelu. PoBo|enie pozostaBych komponentów ilustruje rysunek 11.3. 340 Cz[ II Rysunek 11.3. Pierwsze ujcie formularza PROPERTY. UWAGA Nale|y ostro|nie umieszcza komponenty wyBcznie na panelu górnym DBCtrlGrid. PozostaBe panele powinny pozosta niedostpne. Komponent DBText bdzie sBu|yB do wy[wietlania (ale nie do edycji) pola PROPERTY_NUMBER, elementy DBEdit i DBComboBox bd umo|liwiaBy dostp do tabeli PROPERTY, pozostaBe elementy nadaj swoim polom warto[ci logiczne. PoBczenie komponentów z tabel PROPERTY Aby poBczy komponenty do wprowadzania danych z odpowiednimi polami tabeli PROPERTY nale|y: 1. Wybierajc opcj Use Unit z menu File, a nastpnie klikajc dwukrotnie na nazwie RENDATA z listy moduBów, poBczy moduB danych dmRENTMAN z nowym formularzem. 2. Ustali wBa[ciwo[ci DataSource komponentów DBCtrlGrid oraz DBNavigator na dmRENTMAN.dsPROPERTY. 3. Zgodnie z tablic 11.3, przyporzdkowa ka|demu komponentowi formularza odpowiednie pole tabeli PROPERTY - nale|y zaznaczy kolejno ka|dy z elementów i nada wBa[ciw warto[ wBa[ciwo[ci DataField. Formularze 341 WSKAZÓWKA Pola tablicy mo|na przeciga i umieszcza w formularzu bezpo[rednio z edytora pól Delphi. Powstan w ten sposób domy[lne komponenty, poBczone z wBa[ciwymi polami. Automatycznie utworz si etykiety elementów o nagBówkach adekwatnych do odpowiednich nazw kolumn tabeli. Ta prosta metoda pozwala omin konieczno[ rcznego ustawiania komponentów do sterowania danymi. Tabela 11.3. Komponenty formularza DBCtrlGrid i ich atrybuty Nazwa Komponent Szeroko[ Pole danych Etykieta dteProperty_Number DBText 40 PROPERTY_NUMB No. ER dedAddress DBEdit 121 ADDRESS Address dcbCity DBComboBox 100 CITY City dadState DBEdit 40 STATE State dedZip DBEdit 70 ZIP ZIP dcbAddition DBComboBox 115 ADDITON Addition dcbSchoolDistrict DBComboBox 142 SCHOOLDISTRICT SchoolDistrict dedRent DBEdit 50 RENT Rent dedDeposit DBEdit 50 DEPOSIT Deposit dedLivingAreas DBEdit 30 LIVINGAREAS Living dedBedRooms DBEdit 30 BEDROOMS Bed dedGarageType DBEdit 30 GARAGETYPE Garage dedLastLawnDate DBEdit 60 LASTLAWNDATE LastLawn dedLastSprayDate DBEdit 60 LASTSPRAYDATE LastSpray dckCentralAir DBCheckBox 65 CENTRALAIR CentralAir dckCentralHeat DBCheckBox 75 CENTRALHEAT CentralHeat dckGasHeat DBCheckBox 65 GASHEAT GasHeat dckRefrigerator DBCheckBox 73 REFRIGERATOR Refrigerator dckRange DBCheckBox 53 RANGE Range dckDishWasher DBCheckBox 73 DISHWASHER DishWasher dckPrivacyFence DBCheckBox 84 PRIVACYFENCE PrivacyFence 342 Cz[ II Wy[wietlanie danych podczas projektowania Po poBczeniu komponentów edycyjnych z odpowiadajcymi im polami powinni[my widzie w czasie dalszego projektowania formularza pierwszy rekord tabeli, poniewa| tabela PROPERTY jest otwarta (wszystkie tabele dmRENTMAN zostaBy otwarte podczas ich konstruowania), a projektant formularzy Delphi wy[wietla prawdziwe dane natychmiast po podBczeniu elementów edycyjnych do otwartego zbioru danych. Elementy te wy[wietlaj dane, a nie nazwy pól (tak jak zazwyczaj podczas projektowania). Nie wypeBnione pola oznaczaj, |e odpowiednie rubryki tabeli s puste. Ustawienie kolejno[ci tabulacji Je[li zajdzie potrzeba zmiany kolejno[ci tabulacji elementów formularza, to nale|y wybra opcj Tab Order z menu Edit i, po zaznaczeniu nazwy odpowiedniego komponentu, przesuwa go w gór lub w dóB przy pomocy przycisków strzaBek (dostpna jest równie| technika  przecignij i upu[ ). Porzdek tabulacji powinien odpowiada fizycznemu poBo|eniu elementów na formularzu, tak aby tabulacja przenosiBa dziaBanie od jednego skBadnika do drugiego, zgodnie z oczekiwaniem u|ytkownika. Szybki dostp W |adnym formularzu, projektowanym w tym rozdziale, nie wyznaczamy w etykietach liter szybkiego dostpu, zawieraj one bowiem zbyt wiele skBadników i jest maBo prawdopodobne, aby kto[ chciaB korzysta z takiej formy dostpu do elementów. Testowanie formularza PROPERTY Po zaprojektowaniu komponentów i skonfigurowaniu ich wBa[ciwo[ci formularz jest gotowy do testów. Nale|y rozpocz od podBczenia formularza do gBównego okna aplikacji- fmRSYSMAN. PodBczenie formularza PROPERTY do programu RENTMAN Wczytujemy formularz fmRSYSMAN i wybieramy opcj Use Unit z menu File. Klikamy dwukrotnie na li[cie pozycj moduBu PROCGD0. Od tego momentu nazwa formularza PROPERTY jest dostpna z oferty gBównego okna aplikacji. Kolejny krok polega na wybraniu w gBównym oknie programu menu Tables i dwukrotnym klikniciu na pozycji Property. W udostpnionym w ten sposób przez Delphi edytorze wpisujemy lini kodu zródBowego: Formularze 343 fmPROCGD0.Show; Po dwukrotnym klikniciu na opcji Property z menu Tables, system Delphi utworzyB w swoim edytorze kodów (Code editor) metod klasy (procedur lub podprogram) o nazwie Property1Click, która jest wywoBywana w momencie kliknicia w menu programu pozycji Property. Po wywoBaniu procedura uruchamia metod Show formularza fmPROGDC0, powodujc wy[wietlenie go w oknie programu. Kolejnym krokiem bdzie poBczenie procedury z przyciskiem sbPROPERTY paska narzdziowego. Konfigurowanie przycisku wywoBujcego formularz Je[li na ekranie mamy jeszcze edytor kodu, to przy pomocy klawisza F12 wracamy do projektanta formularzy. Wybieramy przycisk sbPROPERTY, znajdujcy si na górze formularza. Aby przej[ do inspektora obiektów, wciskamy klawisz F11 i wybieramy stron Events. Na rozwijalnej li[cie zaznaczamy zdarzenie OnClick, a nastpnie wybieramy pozycj Property1Click. W ten sposób spowodujemy, |e wBa[ciwo[ci sbPROPERTY przycisku i Property1Click odpowiedniej pozycji oferty bd identyczne. Takie postpowanie jest wydajniejsze, ni| proste wywoBanie procesu Property1Click poprzez program sbPropertyClick (nie ma potrzeby u|ycia oddzielnej metody). Pozostaje ju| tylko zachowa wyniki pracy i uruchomi aplikacj. Po wywoBaniu systemu RENTMAN wciskamy klawisz F4, by przywoBa okienko dialogowe Property. Wygld otrzymanego formularza mo|na porówna z obrazem na rysunku 11.3. Mo|na równie| doda do tabeli kilka rekordów w celu sprawdzenia formularza w dziaBaniu. Na rysunku zilustrowano przykBadowe dane. Formularz LEASE Z gBównego menu Delphi wybieramy opcj File\New, a nastpnie stron Forms w okienku dialogowym New Item. Klikamy ikon fmControlGridForm, potem opcj Inherit i zatwierdzamy klawiszem OK. W projektancie formularzy powinien ukaza si nowy formularz, dziedziczcy wBa[ciwo[ci klasy fmControlGridForm. PrzeksztaBcimy go, aby mógB sBu|y do edycji tabeli LEASE. Modyfikacj obiektu rozpoczynamy od zmian nazwy na fmRLEACGD0 oraz nagBówka - na przykBad na: Formularz do edycji tabeli Lease. Zachowujemy formularz w zródBowym katalogu aplikacji pod nazw RLEACGD0.PAS. 344 Cz[ II Konfiguracja DBCtrlGrid Z dwunastu kolumn tabeli LEASE dziewi jest elementami tekstowymi lub numerycznymi, jedna jest typu logicznego (boolean), a dwie s kluczami zewntrznymi. Te dwa ostatnie elementy bd obsBugiwane poprzez pola przegldowe (lookup fields) w komponencie tablicy taLEASE. Górny panel formularza nale|y przeksztaBci w nastpujcy sposób: 1. Umie[ci na górnym panelu komponent DBText oraz dwa typu DBLookupComboBox. 2. Wstawi poni|ej umieszczonych wcze[niej skBadników osiem elementów DBEdit. 3. Umie[ci w ostatnim wierszu panela komponent logiczny DBCheckBox. 4. Ustawi wBa[ciwo[ ValueChecked oraz Valueunchecked odpowiednio na T i F. 5. Umie[ci po jednej etykiecie nad ka|dym z elementów utworzonych w poprzednich krokach. 6. Sterownik DBText powinien by umieszczony w lewym górnym naro|niku panelu. PoBo|enie pozostaBych komponentów ilustruje rysunek 11.4. Komponent DBText bdzie wy[wietlaB elementy pola LEASE_NUMBER. Elementy DBEdit i DBLookupComboBox posBu| do edycji tablicy LEASE lub kolumn tekstowych; skBadnik DBCheckBox obsBuguje pole z warto[ciami logicznymi. WSKAZÓWKA Wprowadzanie hasBa u|ytkownika SYSDBA systemu InterBase przy ka|dej próbie modyfikacji jest uci|liwe, nale|y wic uaktywni formularz dmRENTMAN i podwójnie klikn komponent Tdatabase, by otworzy edytor baz danych, w którym mo|na wyszczególni domy[lne hasBa do poszczególnych komponentów. Osadzanie haseB w formularzach Delphi Mo|e by ryzykowne, gdy| uBatwia podejrzenie haseB podczas przegldania plików. Aczenie komponentów z tabel LEASE Przed poBczeniem narzdzi do edycji danych z odpowiednimi polami trzeba jeszcze doda par pól przegldowych do obiektu taLEASE. . Te komponenty pozwol na ustawianie pól TENANT_NUMBER i PROPERTY_NUMBER przy u|yciu nazw, zamiast warto[ci liczbowych. Formularze 345 Pola przegldowe tabeli taLease mo|na ustawi w nastpujcy sposób: 1. Wcisn kombinacj klawiszy SHIFT+F12, aby obejrze list formularzy. Klikn dwukrotnie na pozycji dmRentalMan, by zaznaczy ten moduB danych. 2. Otworzy edytor pól, klikajc dwukrotnie na komponencie taLEASE. 3. Klikn prawym klawiszem myszy na li[cie pól i wybra New field (CTRL+N). 4. Nazwa nowe pole TENANT_NAME, okre[li jego typ jako String i ustali rozmiar na 30. 5. Klikn opcj Lookup, a nastpnie wprowadzi do pozycji Key Fields warto[ TENANT_NUMBER ( w obszarze okienka dialogowego sBu|cego do definicji Lookup). 6. Wybra taTENANT w zbiorze danych pola lookup, nastpnie ustawi wBa[ciwo[ Lookup Key na TENANT_NUMBER. Ustawi element Result Field na pole NAME tabeli TENANT i klikn OK. W opisany wy|ej sposób okre[la si relacj przegldania (lookup) midzy komponentami taLEASE i taTENANT. Musimy ustanowi podobne poBczenie pomidzy skBadnikami taPROPERTY i taLEASE: 1. Klikn kombinacj CTRL+N, aby doda nowe pole do taLEASE. 2. Nowe pole nazwa PROPERTY_ADDRESS, okre[li jego typ jako String i ustali rozmiar na 30. 3. Klikn opcj Lookup, a nastpnie wprowadzi do pozycji Key Fields warto[ PROPERTY_NUMBER ( w obszarze okienka dialogowego sBu|cego do definicji Lookup). 4. W zbiorze danych pola lookup wybra taPROPERTY, nastpnie ustawi wBa[ciwo[ Lookup Key na PROPERTY_NUMBER. 5. Ustawi element Result Field na pole ADDRESS komponentu taPROPERTY i klikn OK. Dziki ustanowionym poBczeniom mo|na w taki sposób traktowa zbiór danych taLEASE, jakby rubryki TENANT_NAME i PROPERTY_ADDRESS byBy fizycznie cz[ciami tabeli. 346 Cz[ II UWAGA W powy|szym przykBadzie dodano dwa nowe pola wyszukiwania do tabeli taLEASE, zamiast ustawi wBa[ciwo[ci zwizane z wyszukiwaniem komponentów DBLookupComboBox, gdy| podstawowym przeznaczeniem wBa[ciwo[ci ListSource i ListField komponentu DBLookupComboBox jest otworzenie przegldanych pól. DBCtrlGrid nie pozwala ustawi omawianych wBa[ciwo[ci rezydujcych w nim obiektów typu DBLookupComboBox. Z ró|nych powodów jest to po prostu niedozwolone. Poniewa| elementy DBLookupComboBox s wystarczajco inteligentne, by wiedzie, kiedy wy[wietlaj predefiniowane pole wyszukiwania i odpowiednio je traktowa, mo|emy doda z wyprzedzeniem pola wyszukiwania (lookup fields) do zbioru danych taLEASE. Pola wyszukiwania (Lookup) Pole TENANT_NAME faktycznie nie istnieje w tabeli PROPERTY; w rzeczywisto[ci jest polem wyszukiwania. Omawiany rodzaj pola jest specjalnym typem póB u|ywanym do pozyskiwania danych poBo|onych w innej tabeli. W naszym przypadku kolumna TENANT_NUMBER tabeli PROPERTY jest u|ywana do przegldania rubryki NAME tablicy TENANT. U|ywajc pól wyszukiwania mo|na Batwo wskazywa warto[ci innych tabel, bez konieczno[ci pisania choby linijki kodu. Komponenty DBGrid, DBCtrlGrid, DataListBox i LookupComboBox umiej obsBugiwa pola wyszukiwania i w miar potrzeby bd je automatycznie aktualizowa. Do obsBugi pól zdefiniowanych jako wyszukiwania, DBGrid i DBCtrlGrid dostarczaj list rozwijalnych. Oznacza to, |e mo|liwe jest ogldanie nie tylko wBa[ciwego pola, ale dostpne s równie| odpowiednie kolumny bie|cej tabeli. Inne kontrolki (na przykBad DBEdit) nie umiej automatycznie aktualizowa pól wyszukiwania; w razie konieczno[ci u|ycia ich do obsBugi takich pól, od[wie|anie trzeba wykonywa  rcznie . Z powrotem do tabeli Po ustawieniu pól wyszukiwania wracamy do fmRLEACGD0 i w nastpujcy sposób Bczymy komponenty do edycji danych z wBa[ciwymi polami tabeli: 1. Wybierajc opcj Use Unit z menu File, a nastpnie klikajc dwukrotnie na nazwie RENDATA z listy moduBów, poBczy nale|y moduB danych dmRENTMAN z nowym formularzem. 2. Ustali wBa[ciwo[ci DataSource komponentów DBCtrlGrid oraz DBNavigator na dmRENTMAN.dsLEASE. Formularze 347 3. Zgodnie z tabel 11.4. przyporzdkowa ka|demu komponentowi formularza odpowiednie pole tablicy PROPERTY. W tym celu zaznaczy kolejno ka|dy z elementów i nada wBa[ciw warto[ jego wBa[ciwo[ci DataField. Tabela 11.3. Komponenty formularza DBCtrlGrid i ich atrybuty Nazwa Komponent Szeroko[ Pole danych Etykieta dteLease_Number DBText 40 LEASE_NUMB No. ER dlcbTenant_Name DBLookupComboBox 145 TENANT_NAM Tenant) E dlcbProperty_Address DBLookupComboBox 145 PROPERTY_ Property ADDRESS dedBeginDate DBEdit 64 BEGINDATE Begin dedEndDate DBEdit 64 ENDDATE End dedMovedInDate DBEdit 64 MOVEDINDAT MovedIn E dedMovedOutDate DBEdit 64 MOVEDOUTDA MovedOut TE dedRent DBEdit 50 RENT Rent dedDeposit DBEdit 50 DEPOSIT Deposit dedPetDeposit DBEdit 50 PETDEPOSIT PetDeposit dedRentDueDay DBEdit 40 RENTDUEDAY DueDay dckLawnService DBCheckBox 85 LAWNSERVICE LawnServic e dedComments DBEdit 355 COMMENTS Comments Testowanie formularza LEASE Po zaprojektowaniu komponentów i skonfigurowaniu ich wBa[ciwo[ci formularz jest gotowy do testów. PodBczmy go najpierw do gBównego okna aplikacji fmRSYSMAN. PodBczenie formularza LEASE do aplikacji RENTMAN Wczytujemy formularz fmRSYSMAN i wybieramy opcj Use Unit z menu File. Klikamy dwukrotnie na li[cie pozycj moduBu PROCGD0, dodajc w ten sposób wBa[ciwy zapis do deklaracji moduBu USES. Od tego momentu formularz LEASE mo|e by wy[wietlany z gBównego menu okna aplikacji. 348 Cz[ II Kolejny krok polega na wybraniu - w gBównym oknie programu- menu Tables i dwukrotnym klikniciu na pozycji Lease. W udostpnionym w ten sposób przez Delphi edytorze wpisujemy lini kodu zródBowego: fmRLEAGD0.Show; Po dwukrotnym klikniciu na opcji Tables\Lease Delphi utworzyBo w swoim edytorze kodów (Code editor) metod (procedur lub podprogram) o nazwie Lease1Click. Jest ona wywoBywana w momencie kliknicia w ofercie programu pozycji Lease. Po wywoBaniu procedura uruchamia metod Show formularza fmPROGDC0, powodujc wy[wietlenie go w oknie programu. Podobnie jak dla poprzednich formularzy, poBczymy procedur wy[wietlania z przyciskiem sbLEASE paska narzdziowego. Konfigurowanie przycisku wywoBujcego formularz Wracamy do projektanta formularzy. Wciskamy przycisk sbLEASE, znajdujcy si na górze okna. W inspektorze obiektów wybieramy stron Events. Na rozwijalnej li[cie zaznaczamy zdarzenie OnClick, a nastpnie klikamy pozycj Lease1Click. Tak jak formularze TENANT i PROPERTY i ten bdzie wywoBywany przyciskiem za pomoc tej samej metody, wyzwalanej wyborem odpowiedniej opcji oferty. Po zakoDczeniu konfiguracji przycisku zachowujemy wyniki pracy i uruchamiamy aplikacj. WywoBujemy system RENTMAN, wciskamy klawisz F6, by przywoBa okno dialogowe Lease Edit Form. Wygld otrzymanego formularza mo|na porówna z rysunkiem 11.4. Dodajemy kilka rekordów do tabeli, by sprawdzi formularz w dziaBaniu. Na rysunku zilustrowano przykBadowe dane. Rysunek 11.4. Formularz Lease. Konstrukcja formularzy TENANT, PROPERTY i LEASE ró|ni si szczegóBami. Budujc je, zdobyli[my niezbdne do[wiadczenie, by tworzenie formularzy, a szczególnie tych wykorzystujcych DBCtrlGrid, byBo Batwiejsze. W kolejnej Formularze 349 cz[ci rozdziaBu bdziemy budowa okna dialogowe obsBugujce tabele WORDER i CALL. Ka|da z nich potrzebuje dwóch formularzy, szeroko wykorzystujcych komponent DBGrid. Formularze tabeli WORDER i WODETAIL Formularze te wyró|niaj si spo[ród innych jednoczesnym wy[wietlaniem danych zawartych w dwóch tabelach (WORDER i WODETAIL), bdcych w relacji. Na poziomie bazy danych tabele zwizane s reguBami integralno[ci - ich wizualne przedstawienie powinno zachowywa wzajemne stosunki pomidzy komponentami Table moduBu danych dmRENTMAN. Je[li aplikacja RENTMAN jeszcze pracuje, to nale|y j wyBczy. Z menu Delphi wybieramy opcj File\New. W oknie dialogowym New Item zaznaczamy ogóln klas formularzy fmGridForm i opcj dziedziczenia (Inherit). Do wizualnego projektanta Delphi powinien zainstalowa si formularz o nazwie fmGridForm1, który zobaczymy zaraz po wyborze z gBównej oferty RENTMAN opcji Work Order. Przy pomocy tego okienka dialogowego zdecyduje on o wstawianiu, usuwaniu lub edycji rekordu tabeli WORDER. Po wybraniu opcji wstawiania lub edycji, wy[wietli si formularz fmRWORDER0, przedstawiajcy równocze[nie tabele WORDER i WODETAIL z wizualnie zobrazowan relacj podstawowy/ szczegóBowy. Formularz tabelaryczny (Grid Form) tabeli WORDER Formularz tabelaryczny pozwala spojrze na tabel WORDER z lotu ptaka. Umo|liwia u|ytkownikowi szybkie przejrzenie zestawienia prac, co mo|e by u|yteczne samo w sobie. Formularz kombinowany pozwala na edycj pojedynczego rekordu tabeli WORDER razem z odpowiadajcymi mu rekordami tabeli WODETAIL. NiezwykBo[ formularza polega równie| na tym, |e nie wszystkie jego elementy edycyjne korzystaj z tego samego zródBa danych. Elementy umieszczone na górze okienka dialogowego poBczone s z tabel WORDER, natomiast te z doBu wspóBpracuj z WODETAIL. Gdy umie[cimy drugi komponent DBNavigator w formularzu kombinowanym i skojarzymy go z tabel WORDER, nie musimy wówczas tworzy formularza tabelarycznego. Nie jest to jednak korzystna sytuacja ze wzgldu na konieczno[ nieustannych negocjacji midzy rekordami tabel, co dla klienta chccego dokona szybkiego przegldu informacji jest zjawiskiem niepo|danym. Poza tym obecno[ dwóch elementów DBNavigator w jednym okienku dialogowym mo|e prowadzi do pomyBek. 350 Cz[ II Zmieni nazw formularza na fmRWORGRD0 i wymy[li nagBówek, na przykBad Formularz wyboru zestawienia prac. Zachowa zbiór pod nazw RWORGRD0.PAS. Budowa i uruchomienie formularza nie bdzie kosztowa zbyt du|o pracy. Rozpocz nale|y od utworzenia dwóch pól wyszukiwania do sprowadzania informacji opisowych z innych tabel. Na koniec trzeba bdzie odpowiednio ustawi zródBa danych (wBa[ciwo[ DataSource) dla komponentów formularza. Tworzenie pól wyszukiwania Najpierw tworzymy dwa pola wyszukiwania dla tabeli WORDER. W tym celu wykorzystamy pole PROPERTY_NUMBER tablicy WORDER do wywoBania odpowiedniego pola ADDRESS tabeli PROPERTY. Nastpujca procedura opisuje proces tworzenia pola wyszukiwania: 1. W projektancie formularzy wywoBa moduB danych dmRENTMAN i uruchomi edytor pól, klikajc dwukrotnie na tabeli taWORDER. 2. Wcisn klawisze CTRL+N, aby utworzy nowe pole i nazwa je PROPERTY_ADDRESS. 3. Wybra dla pola typ String i ustawi jego rozmiar na 30. 4. Klikn opcj Lookup, a nastpnie wprowadzi do pozycji Key Field warto[ PROPERTY_NUMBER. 5. Ustawi taPROPERTY w DataSet pola wyszukiwania, po czym ustawi wBa[ciwo[ Lookup Key na PROPERTY_NUMBER. 6. Ustawi ADDRESS w polu Result Field. Klikn OK i opu[ci okienko dialogowe. 7. Pole ADDRESS bdzie odczytywane z tabeli PROPERTY, a jego warto[ci bd skBadowane w polu wyszukiwania PROPERTY_ADDRESS tabeli WORK ORDER. Nowo dodane pole mo|na zobaczy na dole listy pól WORDER. 8. Wcisn znowu kombinacj klawiszy CTRL+N, aby utworzy drugie pole. Tym razem zostanie zdefiniowane pole wyszukiwania do sprowadzania pola NAME tabeli EMPLOYEE. Umo|liwi ono wy[wietlanie nazwiska pracownika, dla którego przeznaczony jest okre[lony zakres prac. 9. Nowe pole nazwa EMPLOYEE_NAME, wybra mu typ String i ustawi jego rozmiar na 30. 10. Ustawi stosowne wBa[ciwo[ci pola przegldowego, podobnie jak dla pola PROPERTY_ADDRESS. Wybra opcj Lookup i ustawi warto[ pola klucz (Key Field) na EMPLOYEE_NUMBER. Formularze 351 11. W DataSet pola wyszukiwania wybra taEMPLOYEE, nastpnie ustawi wBa[ciwo[ Lookup Key na EMPLOYEE_NUMBER. 12. Ustawi NAME w polu Result Field, klikn OK i opu[ci okienko dialogowe. W ten sposób pole NAME bdzie aktualizowaBo dane z tabeli EMPLOYEE, u|ywajc kolumny EMPLOYEE_NUMBER obu tabel. Warto[ci bd skBadowane w polu przegldowym EMPLOYEE_NAME tabeli WORDER. Ustanawianie relacji podstawowy/szczegóBowy (Master/Detail) Majc otwarty moduB danych aplikacji, nale|y ustanowi relacj podstawowa/ szczegóBowa miedzy tabelami WORDER i WODETAIL. Umo|liwi to budow kombinowanego formularza (master/detail), w którym dwie tablice bd obrazowane synchronicznie. Tabele Bczymy w sposób nastpujcy: 1. Klikn tabel WODETAIL i wcisn klawisz F11, aby przeBczy si do inspektora obiektów. 2. Ustawi wBa[ciwo[ MasterSource dokBadnie na dsWORDER. 3. Klikn wyBcznik (ellipsis) po prawej stronie wBa[ciwo[ci MasterField, by uaktywni projektanta poBczeD pól (Delphi s Field Link Designer). 4. U|y wizualnego narzdzia do ustanowienia relacji midzy tabelami WORDER i WODETAIL. Lewy panel okienka dialogowego zawiera list pól tabeli WODETAIL, a prawy tabeli WORDER. Wybra nazw pola WORDER_NUMBER na obu listach, a nastpnie klikn przycisk Add (dodaj). (por. rysunek 11.5). Klikajc wyBcznik OK, opu[ci projektanta poBczeD. Rysunek 11.5. Projektant poBczeD midzy polami programu Delphi. Klikajc na obu listach wspóln nazw kolumn: WORDER_NUMBER tworzy si poBczenie midzy dwiema tabelami, zawierajcymi rubryk WORDER_ NUMBER. Tabela szczegóBowa (podrzdna) bdzie si zachowywa tak, jakby zawieraBa jedynie te rekordy, które wskazuje pole WORDER_NUMBER tabeli podstawowej. W ten sposób na formularzu kombinowanym, który za chwil zbudujemy, obie tabele bd chwilowo poBczone wizualnie. Skojarzenia tabel 352 Cz[ II mo|na dokona bez u|ycia projektanta Field Link Designer, opisujc po prostu odpowiednie wBa[ciwo[ci MasterFields i IndexFieldNames. Na formularzu mog by wy[wietlane jedynie te rekordy tabeli podrzdnej, które s skojarzone z odpowiednim elementem tabeli nadrzdnej. Wynika std, |e zawsze, gdy do tabeli szczegóBowej dodaje si now lini, musi ona przyswoi dokBadn warto[ bie|cego klucza z tabeli nadrzdnej. Inaczej nie mo|na bdzie zobaczy nowo utworzonego rekordu. Poni|szy kod umo|liwia przeniesienie klucza WORDER do tabeli WODETAIL, ilekro jest do niej dodawany nowy wiersz. Zdarzenie OnNewRecord obiektu taWODETAIL powinno zawiera nastpujcy fragment kodu: taWODETAILWORDER_NUMBER.Value:=taWORDERWORDER_NUMBER.Value; Wprowadzanie domy[lnych warto[ci do pól w czasie dziaBania programu Majc otwarty formularz dmRENTMAN, zajmiemy si jeszcze zdarzeniem OnNewRecord tabeli WORDER. Chocia| w czasie projektowania bazy danych nie zaplanowali[my wprowadzania warto[ci domy[lnych do kolumny StartDate, to w wielu przypadkach bdzie tam pozostawiana bie|ca data. Klikamy na komponencie taWORDER, a nastpnie dwukrotnie na zdarzeniu OnNewRecord w inspektorze obiektów. Do edytora kodu wprowadzamy: taWORDERStartDate.value:=Date; Dziki temu w czasie dodawania nowego rekordu do tabeli do pola StartDate bdzie wprowadzana bie|ca data. Okre[lenie wBa[ciwo[ci DataSource Nale|y ustawi odpowiednie warto[ci DataSource dla komponentów DBGrid i DBNavigator formularza Work Order. W tym celu nale|y przeBczy si z powrotem do formularza WORDER (fmRWORGRD0). Z menu File projektanta formularzy wybieramy opcj Use Unit i dwukrotnie klikamy moduB RENDATA, ustanawiajc w ten sposób poBczenie midzy nowym formularzem a moduBem danych. Zaznaczamy nastpnie (jednocze[nie) komponenty DBNavigator i DBGrid i uruchamiamy inspektora obiektów. KoDczymy zmieniajc wBa[ciwo[ DataSource obu elementów na dmRENTMAN.dsWORDER. Nowy formularz jest gotowy do edycji danych. Konfiguracja kolumn przeznaczonych do wy[wietlania przez formularz Jedyn rzecz, jaka pozostaBa do wykonania przy formularzu tabelarycznym utworzonym dla tabeli WORDER, jest zaprogramowanie, które kolumny tabeli bd wy[wietlane na ekranie. Nie ma potrzeby wy[wietlania niektórych kolumn tabeli WODETAIL, gdy| s ju| gdzie[ widoczne na ekranie. Nie chcemy równie| Formularze 353 prezentowa jednocze[nie klucza pola wyszukiwania i pola wynikowego; wystarczy pole wynikowe. Na koniec nie chcemy, aby pole wynikowe byBo prezentowane jako kolumna koDcowa, lecz aby znajdowaBo si na miejscu mo|liwie najbardziej reprezentacyjnym: Uporzdkujemy formularz, wykonujc nastpujce czynno[ci: 1. Klikamy dwukrotnie na komponencie DBGrid, aby wywoBa edytor kolumn, nastpnie wciskamy przycisk Add All Fields i dodajemy wszystkie pola tabeli WORDER jako kolumny formularza. 2. Dwa zdefiniowane pola wyszukiwania s umieszczone na dole listy. Poniewa| tabela WORDER przechowuje wykaz prac konserwacyjnych zwizanych z wynajmem nieruchomo[ci, to pole opisujce adres powinno znajdowa si tak wysoko, jak to jest mo|liwe. 3. Przecign pole wyszukiwania PROPERTY_ADDRESS do góry, by zajBo miejsce bezpo[rednio po kolumnie WORDER_NUMBER. 4. Przecign kolumn EMPLOYEE_NUMBER do góry i umie[ci j zaraz po PROPERTY_ADDRESS. 5. Zaznaczy jednocze[nie PROPERTY_NUMBER oraz EMPLOYEE_NUMBER i klikn przycisk Delete, aby je usun. Likwidacja kolumn w taki sposób usuwa je jedynie z DBGrid; kolumny pozostaj nadal w zbiorze danych. Po zakoDczeniu konfiguracji zamkn edytor. Edytor kolumn DBGrid ilustruje rysunek 11.6. Rysunek 11.6. Do konfiguracji kolumn wy[wietlanych przez formularz DBGrid stosuje si edytor kolumn (DBGrid Columns editor). UWAGA Dziki sensownej konwencji, u|ywanej do nazywania pól, nie byBo potrzeby ustawiania specjalnych nagBówków dla kolumn wy[wietlanych przez formularz DBGrid ( mo|na to zrobi przy u|yciu strony Title Properties edytora kolumn ). Stosowanie czytelnych nagBówków pól i nazywanie ka|dej kolumny inaczej oszczdza pracy, a przy konieczno[ci konserwacji aplikacji mamy jeden problem mniej. 354 Cz[ II Aczenie formularza tabelarycznego z aplikacj Nasz formularz jest ju| w stanie umo|liwiajcym na doBczenie go do programu RENTMAN. WywoBujemy gBówne okno aplikacji fmRSYSMAN i dwukrotnie klikamy pozycj Work Order z menu Tables. W edytorze kodu, tak jak w kilku poprzednich przypadkach, wpisujemy wywoBanie metody Show dla formularza fmRWORGRD0. Na wszelki wypadek poni|sza linia przypomina wBa[ciwe polecenie: fmRWORGRD0.Show; Przy okazji konfigurujemy odpowiedni przycisk z paska narzdziowego. Wciskamy F12, by wróci do projektanta formularzy. W pasku narzdziowym klikamy komponent sbWorkOrders. W inspektorze obiektów wybieramy stron Events, klikamy na li[cie rozwijalnej na zdarzeniu OnClick. Z listy wybieramy WorkOrders1Click (wci[nicie  gorcego przycisku powinno by równowa|ne wyborowi odpowiedniej opcji z menu). Nastpnie dodajemy, za pomoc opcji File\Use Unit, deklaracj u|ycia moduBu RWORGRD0 w RSYSMAN0 (deklaracja Uses ..). Testowanie formularza Przed uruchomieniem aplikacji RENTMAN, nale|y si upewni, |e komponent Table moduBu danych ma ustawion na True wBa[ciwo[ Active. Zachowujemy projekt, kompilujemy go (klawisz F9) i uruchamiamy. Po zgBoszeniu si okna programu wciskamy F7, aby zobaczy formularz tabeli WORDER. UWAGA Dobrze jest mie kilka rekordów wprowadzonych do tabeli EMPLOYEE, aby móc wybra okre[lonego pracownika z formularza WORDER. Wzbogacanie formularza Nowy formularz ma jedn oczywist wad. Chocia| jest zaprojektowany do wybierania zestawów prac, posiada bardzo maBe okno przeznaczone na tabel WORDER. Je[li ma by rzeczywi[cie porczny, to powinien umo|liwia wy[wietlanie wszystkich mo|liwych rekordów tabeli. Ponadto powinien pozwala na ogldanie jak najwikszej liczby kolumn i na Batwe odró|nianie jednego wiersza od drugiego. Je[li spróbujemy powikszy okno formularza w czasie pracy programu, to zobaczymy, |e panel [rodkowy ro[ci sobie prawo do zbyt du|ej przestrzeni, natomiast DBGrid nie wy[wietla ani jednego rekordu wicej ni| poprzednio Przy pomocy projektanta formularzy zajmiemy si teraz Formularze 355 powikszeniem okienka dialogowego oraz dostosowaniem proporcji powizanych ze sob paneli. W tym celu wyBczamy aplikacj i wracamy do Delphi. Celem poni|szych czynno[ci jest uporzdkowanie formularza WORDER: 1. W wizualnym projektancie wybra komponent formularza (ze wzgldu na trudno[ kliknicia w jego obszarze, mo|e zaistnie konieczno[ wykorzystania listy rozwijalnej inspektora obiektów) i przy pomocy inspektora obiektów zmieni wBa[ciwo[ WindowsState na wsMaximized. 2. Powróci do projektanta i powikszy formularz do peBnego okna. 3. Wybra komponent [rodkowy (paMiddle) i ustawi jego wBa[ciwo[ Align na AlBottom. Nale|y zwróci uwag na wzajemne uBo|enie paneli [rodkowego i dolnego, które wyrównane s przy u|yciu wBa[ciwo[ci paBottom. W przyszBo[ci mo|na wykorzysta to do[wiadczenie, aby ustawi panele jeden nad drugim. 4. Zmniejszy wysoko[ panelu [rodkowego cignc w dóB za jego górn krawdz dotd, a| panel przybierze rozmiary niewiele przekraczajce wysoko[ zawartych w nim elementów. 5. Wybra komponent górny i ustawi jego wBa[ciwo[ Align na alClient. W ten sposób panel górny zajmie caB dostpn przestrzeD, a rezydujcy na nim DBGrid, który równie| jest wyrównany opcj alClient, bdzie zajmowaB caB powierzchni panelu. 6. Wygld formularza po wykonaniu powy|szych instrukcji ilustruje rysunek 11.7. Rysunek 11.7. Wygld formularza tabelarycznego WORDER w czasie dziaBania programu. 356 Cz[ II PrzeksztaBcenie DBGrid na  tylko do odczytu Zanim uznamy, |e praca nad formularzem tabelarycznym WORDER jest zakoDczona, musimy rozwa|y jeszcze jedn rzecz. Poniewa| formularz zostaB pomy[lany jako narzdzie wyboru rekordów tabeli, to nie powinien umo|liwia edycji pól. Ponadto ze wzgldu na wzajemne powizania, narzdzie do edycji tabeli WORDER powinno umo|liwia jednoczesn edycj tabeli WODETAIL. Takim narzdziem bdzie skonstruowany niedBugo fmRWORMD0. Nasz formularz powinien pozwala jedynie na wybór odpowiedniego rekordu. Wziwszy pod uwag powy|sze spostrze|enia, musimy wykorzysta inspektora obiektów i ustawi na True wBa[ciwo[ci ReadOnly formularza DBGrid. W ten sposób zabezpieczamy dane przed edycj za pomoc komponentu DBGrid. Informacje s wy[wietlane, lecz nie mo|na ich zmieni. Modyfikacja dziaBania komponentu DBNavigator Kiedy formularz tabelaryczny posiada ju| atrybut  tylko do odczytu , nale|y dwukrotnie klikn na komponencie DBNavigator. Przy pomocy edytora wpisa nastpujcy kod: With DBNavigator do case Button of nbInsert: begin DataSource.DataSet.Insert; fmRWORMDE0.ShowModal; end; nbEdit : begin DataSource.DataSet.Edit; fmRWORMDE0.ShowModal; end; end; Powy|sza metoda modyfikuje dziaBanie przycisków nbInsert i nbEdit nawigatora baz danych. Je[li u|ytkownik u|yje którego[ z tych narzdzi, to zostanie wywoBany formularz kombinowany fmRWORMDE0. Takie podej[cie umo|liwia przekazanie odpowiedzialno[ci za edycj danych z formularza tabelarycznego na formularz fmRWORMDE0. Na tym etapie nie mo|emy skompilowa projektu do czasu utworzenia formularza kombinowanego fmRWORMDE0. Formularze 357 UWAGA Przypomnijmy, ze przyciski Add, Edit i Delete zostaBy wprowadzone do formularza, aby umo|liwi u|ytkownikowi modyfikacj zbioru danych zarówno przy pomocy myszy oraz komponentu DBNavigator-a, jak i przy u|yciu klawiatury. Przyciski sBu| tylko do wywoBania metody BtnClick kontrolki DBNavigator, symulujc u|ycie myszy. Dziki temu u|ytkownik, chcc dokona edycji, usunicia lub dodania rekordu, mo|e u|y przycisku lub skrótu klawiaturowego, zamiast klika na odpowiednim elemencie nawigatora baz danych. Nie musimy obecnie modyfikowa |adnej metody obsBugujcej wci[nicie którego[ z trzech dodanych przycisków, chocia| zupeBnie zmienili[my zachowanie si formularza w przypadku próby edycji, usuwania lub dodawania rekordu. Wci[nicie dowolnego przycisku wywoBuje odpowiedni metod DBNavigatora. Formularz kombinowany (Master/Detail) tabeli WORDER Skonstruujemy teraz formularz, który umo|liwi jednoczesn edycj tabel WORDER i WODETAIL. Dziki relacji podstawowa/szczegóBowa midzy dwiema tablicami, umo|liwi on wy[wietlanie wszystkich rekordów tabeli WODETAIL, które  nale| do wybranego w poprzednim formularzu rekordu tabeli WORDER. Odpowiedni wiersz tabeli WORDER bdzie umieszczony w górnej cz[ci okna, a wszystkie korespondujce z nim rekordy tablicy WODETAIL zostan wy[wietlone w jego fragmencie dolnym. Pocztek budowy formularza: 1. Z menu Delphi wybra opcj File\New, a nastpnie okienko dialogowe New Item. 2. Klikn kolejno: ikonk fmMasterDetailForm, opcj Inherit i przycisk OK. 3. Zmieni nazw formularza na fmRWORMDE0 oraz wymy[li nagBówek, np. Formularz do edycji tabeli Work Order. Zapisa nowy formularz do zbioru RWORMDE0.PAS Pola wyszukiwania Zanim cokolwiek zrobimy z nowym formularzem, zdefiniujemy pole wyszukiwania tabeli taWODETAIL, sBu|ce do uaktualniania pola DESCRIPTION tablicy WORKTYPE. Aby to zrobi, musimy postpowa nastpujco: 358 Cz[ II 1. W wizualnym projektancie formularzy wywoBa moduB danych dmRENTMAN i dwukrotnie klikn na zbiorze danych taWODETAIL. Po otworzeniu edytora pól wcisn kombinacj klawiszy CTRL+N, aby doda nowe pole. 2. Nowe pole nazwa WORKTYPEDESCRIPTION, okre[li typ danych jako String i ustali rozmiar pola na 30. 3. Klikn przycisk opcji LOOKUP i wprowadzi WORK_TYPE_CODE do Key Field. 4. Ustawi warto[ DataSet na taWORKTYPE, a warto[ Lookup Key na WORK_TYPE_CODE (ta sama, co dla Key Fields). 5. Okre[li warto[ Result Field na DESCRIPTION i klikn OK, aby opu[ci okienko dialogowe. W ten sposób w tabeli WODETAIL pole WORK_TYPE_CODE bdzie wykorzystywane do pobierania komentarzy z tabeli WORKTYPE. Warto[ pola WORK_TYPE_CODE z tabeli WODETAIL bdzie zamieniana na formularzu na odpowiedni warto[ pola DESCRIPTION. 6. Po zdefiniowaniu nowego pola, zamkn edytor i zainstalowa ponownie nowy formularz do projektanta formularzy. Ustawianie wBa[ciwo[ci DataSource Zanim na nowym formularzu umie[cimy pierwszy komponent, nale|y w opisany ni|ej sposób okre[li zródBa danych dla komponentów DBGrid i DBNavigator: 1. Z menu File wybra opcj Use Unit, nastpnie z listy wybra RENDATA, aby umo|liwi dostp do kontrolek bazy danych na formularzu moduBu danych. 2. Zaznaczy komponenty DBGrid i DBNavigator i zmieni ich wBa[ciwo[ DataSource na dmRENTMAN.dsWODETAIL. Po zakoDczeniu projektowa- nia formularza na jego górnej cz[ci bdzie wy[wietlany bie|cy rekord tabeli WORDER, a na dolnej odpowiednie wiersze tabeli WODETAIL. Komunikacja rekordów szczegóBowych z tabel nadrzdn Dwoista natura formularza wymaga zaprogramowania specjalnej procedury, odpowiedzialnej za przesyBanie przed dodaniem do tabeli rekordu podrzdnego numeru oczekiwanego przez rekord gBówny. NaBo|ona na WODETAIL reguBa integralno[ci wymaga, aby odpowiednia warto[ pola WORDER_NUMBER istniaBa w tabeli WORDER, zanim zostanie zapisany rekord podrzdny. Serwer nie bdzie widziaB nowego wiersza, dopóki tabela WORDER nie zostanie poinformowana o wBa[ciwym numerze WORDER_NUMBER. Dla tabeli szczegóBowej oznacza to niemo|no[ zapisania rekordu, do czasu a| rekord nadrzdny zostanie zapisany do bazy. Formularze 359 Rozwizanie problemu mo|na opisa nastpujcymi krokami: 1. Klikn dwukrotnie komponent DBNavigator, co umo|liwi edycj metody DBNavigator1Click w edytorze kodu Delphi. 2. Wprowadzi nastpujcy fragment programu: with dmRENTMAN.taWORDER do if (State in [dsEdit, dsInsert]) and (Modified) then begin Post; Edit; end; with DBNavigator1.DataSource.DataSet do case Button of nbEdit: Edit; nbInsert: Insert; end; UWAGA Aby móc skompilowa ten fragment programu, musimy doda moduB DB do deklaracji Uses w pliku moduBu formularza kombinowanego. Chocia| w formularzu fmRWORDMDE0 jest kilka elementów do modyfikacji danych, to nie mo|na w |aden sposób doBczy deklaracji automatycznie i trzeba to zrobi rcznie. Napisany wy|ej fragment kodu powoduje sprawdzenie stanu tabeli WORDER i je[li jest to edycja lub wstawianie, to przesyBa wszystkie oczekiwane zmiany. Nastpnie tabela jest natychmiast przywracana do trybu edycji, co umo|liwia edycj bie|cego rekordu. Poniewa| taWORDER i taWODETAIL s poBczone relacj nadrzdna/szczegóBowa, to po wykonaniu metody Post komponent taWODETAIL powraca do trybu przegldania. Instrukcja case ma za zadanie okre[li, który przycisk byB w rzeczywisto[ci wci[nity i w zale|no[ci od tego uruchomi wBa[ciwe polecenie edit lub insert. UWAGA Z technicznego punktu widzenia nie jest konieczne sprawdzanie stanu zbioru taWORDER. Jest on zawsze albo w trybie edycji, albo w trybie wstawiania, takie jest przeznaczenie formularza kombinowanego. Tym niemniej jest bardzo po|dane, aby przed u|yciem metody Post sprawdzi stan zbioru danych. Je[li jest inny ni| edycja lub wstawianie, to wywoBanie metody Post powoduje wygenerowanie wyjtku. 360 Cz[ II Konfiguracja kolumn wy[wietlanych przez DBGrid Po modyfikacji komponentu DBNavigator nale|y przeksztaBci kolumny komponentu DBGrid. W tym celu trzeba: 1. Klikn podwójnie na komponencie DBGrid, aby otworzy edytor kolumn. 2. Klikn przycisk Add All Fields, a nastpnie usun z listy pozycje WORDER_NUMBER i WORK_TYPE_CODE. Nie ma potrzeby wy[wietlania pola WORDER_NUMBER, gdy| numer jest ju| wy[wietlany na górze formularza, natomiast pole WORK_TYPE_CODE jest zbdne ze wzgldu na wprowadzenie do edycji i przegldania pola przegldowego. 3. Przenie[ do góry pole WORKTYPEDESCRIPTION, umieszczajc je bezpo[rednio po polu WODETAIL_LINE_NUMBER. Zamkn edytor kolumn. 4. Na zakoDczenie ustawi wBasno[ Read-Only kolumny WODETAIL_LINE_ NUMBER na True oraz zamkn edytor kolumn. Umieszczanie komponentów na formularzu W gBównej cz[ci formularza fmWORMEDE0 bdzie u|ywane sze[ pól z tabeli taWORDER. Na górnym panelu umieszczamy jeden komponent DBText, trzy DBEdit i dwa DBComboBox. Za chwil poBczymy ka|dy element z odpowiednim polem taWORDER. UWAGA Podczas wybierania specyficznych komponentów do obsBugi okre[lonych typów pól, nie ma ró|nicy midzy danymi numerycznymi, daty i BaDcuchowymi; do wszystkich trzech rodzajów pól u|ywamy tych samych kontrolek. W szczególno[ci dbEdit mo|e sBu|y do tworzenia pól zawierajcych daty, dane numeryczne lub BaDcuchowe. Nie stosujemy specyficznych narzdzi do okre[lonych typów pól; na poziomie komponentów nie s one rozró|nialne. Po umieszczeniu komponentów na formularzu nale|y ustawi ich wBa[ciwo[ DataSource na odpowiednie elementy dmRENTMAN.dsWORDER. Tablica 11.5. zawiera komponenty i odpowiadajce im pola: Tabela 11.5. NagBówki komponentów wykazu prac i ich atrybuty. Nazwa Etykieta Rodzaj komponentu Pole danych dteWORDER_Number No. DBText WORDER_NUMBER dlcbProperty_Address Address DBLookupComboBox PROPERTY_ADDRES S Formularze 361 Nazwa Etykieta Rodzaj komponentu Pole danych S dlcbEmployee_Name Employee DBLookupComboBox EMPLOYEE_NAME dedStartdate Startdate DBEdit STARTDATE dedEnddate Enddate DBEdit ENDDATE Commentsded Comments DBEdit COMMENTS Poniewa| |aden z wykorzystanych elementów nie posiada wbudowanych nagBówków, powinni[my je jeszcze opisa. W tym celu nad ka|dym sterownikiem nale|y na formularzu umie[ci komponent Tlabel. WSKAZÓWKA Je[li u|yjemy techniki przecigania pól z edytora pól do formularza, to automatycznie zostan na nim umieszczone wBa[ciwe kontrolki wraz z etykietami (Tlabel). Rysunek 11.8 ilustruje, jak bdzie wygldaB wkrótce projektowany formularz. Rysunek 11.8. Formularz kombinowany (master/detail) w fazie projektowania. Testowanie formularza Aby przeprowadzi próby z nowym formularzem, nale|y go poBczy z aplikacj RENTMAN. Najlepszym miejscem bdzie tym razem nie gBówne menu aplikacji, lecz budowany wcze[niej formularz tabelaryczny: fmRWORGRD0. PoBczenie formularza kombinowanego z formularzem tabelarycznym Nastpujcy algorytm opisuje poBczenie formularza tabelarycznego fmRWORGRD0 z formularzem kombinowanym fmRWORMDE0: 362 Cz[ II 1. Do projektanta formularzy wczyta wcze[niej skonstruowany formularz tabelaryczny fmRWORGRD0. 2. Z gBównego menu wybra opcj File\Use Unit i dwukrotnie klikn nazw moduBu z formularzem kombinowanym: RWORMDE0. W tym momencie wcze[niej napisany kod, modyfikujcy dziaBanie komponentu DBNavigator, zostanie skompilowany i powinien dziaBa poprawnie. Po poBczeniu formularzy nale|y jeszcze skonfigurowa komponent DBGrid, aby dwukrotne kliknicie na nim powodowaBo taki sam skutek, jak wci[nicie klawisza edycji, to znaczy zaBadowanie formularza kombinowanego. W tym celu nale|y: 1. Klikn komponent DBGrid, a nastpnie stron Events w inspektorze obiektów. 2. Na li[cie rozwijalnej klikn zdarzenie OnDbClick i wybra pozycj btEditClick. W ten sposób dwukrotne kliknicie komponentu DBGrid bdzie równowa|ne wci[niciu przycisku Edit. 3. Zachowa projekt i uruchomi aplikacj. Rysunek 11.9. ilustruje jak powinien wyglda formularz w czasie pracy programu. UWAGA Je[li nie zrobili[my tego wcze[niej, to dobrze byBoby doda kilka rekordów do tabeli WORKTYPE, aby móc utworzy kilka nowych linii przy pomocy formularza kombinowanego. Rysunek 11.9. Kombinowany formularz tabeli WORDER w czasie pracy programu. Wzbogacanie formularza Obejrzenie formularza w dziaBaniu odsBania jego braki. Na górze blankietu wy[wietlony jest adres nieruchomo[ci, ale przydaByby si jeszcze nazwisko i numer telefonu lokatora oraz kod, stan i dodatkowe informacje adresowe Formularze 363 o nieruchomo[ci. Dodanie ich do formularza pomo|e unikn ewentualnych pomyBek. Wykorzystanie zapytaD (Query) w celu uzupeBnienia formularza dodatkowymi informacjami Pewn wad relacyjnego modelu baz danych (jak twierdz krytycy RDBMS) jest to, |e peBna normalizacja wymaga zazwyczaj Bczenia wielu tabel do otrzymania odpowiedzi na najprostsze pytanie. Informacje s porozrzucane i jakakolwiek operacja wymaga masy kodu SQL. Wielu ekspertów jest jednak zgodnych, |e Batwo[ administracji, siBa powizanych danych i wiele innych czynników daje technologii RDBMS szans projektowania udanych aplikacji dla biznesu, pomimo tego |e model relacyjny powoduje konieczno[ programowania dBugich zapytaD nawet dla prostej struktury danych. Zbudujemy zapytanie do uaktualniania nowych pól na formularzu Work Order systemu RENTMAN. Aby wydoby odpowiednie rekordy tabeli TENANT przy u|yciu tabeli WORDER, musimy u|y kolumny PROPERTY_NUMBER tabeli WORDER do przegldania odpowiedniego rekordu tabeli PROPERTY. Majc ju| rekord zbioru PROPERTY, mo|emy go poBczy z tabel LEASE i okre[li aktualnego najemc nieruchomo[ci. W |argonie u|ywanym do opisu baz danych nazywa si to poBczeniem wielopoziomowym (multi-level join). Poniewa| baza jest znormalizowana, takie postpowanie jest nieuniknione. Istniej dwie drogi prowadzce do skonstruowania poBczeD wielopoziomowych. Pierwsza polega na wywoBaniu metod FindKey ka|dej tablicy i  rcznym przegldaniu poszukiwanych informacji. Druga korzysta z zapytaD SQL do wykonania poBczenia wielopoziomowego i zwrotu danych, których oczekujemy. Zapytanie o informacje o najemcy (quTenantInfo) Nastpujce czynno[ci sBu| skonstruowaniu quTenantInfo: 1. Do wizualnego projektanta wczyta moduB danych dmRENTMAN. 2. Na formularzu umie[ci komponent Query. Zmieni jego nazw na quTenantInfo, a wBa[ciwo[ DataBase na dmRENTMAN. Podwójnie klikn jego wBa[ciwo[ SQL i zaprogramowa nastpujce zapytanie: select t.NAME, t.HOMEPHONE, p.CITY, p.STATE, p.ZIP, p.ADDITION from PROPERTY p, LEASE l, TENANT t where p.PROPERTY_NUMBER=: PROPERTY_NUMBER and p.PROPERTY_NUMBER=: l.PROPERTY_NUMBER 364 Cz[ II and l.ENDDATE=(select MAX(ENDDATE) from LEASE where PROPERTY_NUMBER=p.PROPERTY_NUMBER) and ((l.MOVEDOUTDATE >  TODAY ) or (MOVEDOUTDATE IS NULL)) and l.TENANT_NUMBER = t.TENANT_NUMBER Zapytanie wykorzystuje warto[ PROPERTY_NUMBER do lokalizacji ostatniej transakcji najmu nieruchomo[ci, a w konsekwencji do okre[lenia aktualnego najemcy. Funkcja zwraca rezultat jedynie wtedy, gdy ostatni najemca jeszcze si nie wyprowadziB. W kodzie zapytania wykorzystana zostanie staBa TODAY. InterBase przetBumaczy j na bie|c dat, zatem zapytanie wyszukuje informacji o ostatnim najmie, gdy data wyprowadzki z nieruchomo[ci nastpi w przyszBo[ci (>  TODAY ) lub nie jest okre[lona (IS NULL). Po wprowadzeniu zapytania, zachowujemy je klikajc OK. Do zakoDczenia budowy quTenantInfo prowadz nastpujce kroki: 1. Dwukrotnie klikn na wBa[ciwo[ci zapytania Params i okre[li typ parametru PROPERTY_NUMBER jako Integer, po czym klikn OK. 2. Klikn dwukrotnie na zapytaniu quTenantInfo, by otworzy edytor pól. 3. Wcisn kombinacj klawiszy CTRL+A, celem dodania pól. 4. Przyciskiem OK zatwierdzi dodanie do zapytania sze[ciu pól, a nastpnie zamkn edytor Fields. 5. Komponent Querry jest zdefiniowany. Nastpny krok polega na dodaniu do formularza komponentu DataSource, aby móc skojarzy pytanie z odpowiednimi elementami dostpu do danych. Umie[ci komponent DataSource na formularzu dmRENTMAN i zmieni jego nazw ma dsTenantInfo. 6. Ustawi wBa[ciwo[ DataSet skBadnika DataSource, wskazujc nazw nowego komponentu Querry- quTenantInfo. PoBczenie zapytania z formularzem PrzyszBa pora na poBczenie zapytania z formularzem kombinowanym tabeli WORDER, aby umo|liwi mu pobieranie informacji o najemcach i ich adresach. Po tej czynno[ci umie[cimy na formularzu kilka komponentów, umo|liwiajcych obejrzenie odpowiedzi na zapytanie. Przygotowanie zapytania W projektancie Delphi otwieramy ponownie formularz kombinowany, fmRWORMDE0, a nastpnie zaznaczamy go (mo|e zaistnie konieczno[ wykorzystania listy wyboru inspektora obiektów, ze wzgldu na zasBanianie go Formularze 365 przez inne elementy). Wybieramy stron Events inspektora i dwukrotnie klikamy zdarzenie OnCreate. W edytorze kodu wprowadzamy polecenie: dmRENTMAN.quTenantInfo.Prepare; Przygotowanie zapytania odbierajcego zewntrzne parametry (w |argonie Delphi: zapytania sparametryzowanego, parameterized query), mo|e pomóc je szybciej zrealizowa. WywoBanie metody Prepare powoduje wysBanie zapytania do systemu bazy danych, gdzie zostanie poddane analizie skBadniowej i optymalizacji. Chocia| wywoBanie procedury przygotowania nie jest wymagane, w rzeczywisto[ci Delphi i tak j wywoBa przy ka|dym otwarciu sparametryzowanego zapytania, nawet je[li wcze[niej przygotowanie nie zostaBo uaktywnione. Z tego powodu sensowne jest wywoBanie metody Prepare w momencie inicjowania formularza korzystajcego z zapytania . Przebudowa formularza Aby umo|liwi korzystanie z zapytania, nale|y: 1. Przesun komponenty dedStartDate i dedEndData (wraz z etykietami) na praw stron formularza, by zrobi miejsce na informacje o najemcy. 2. Umie[ci sze[ komponentów DBText i sze[ etykiet na lewej cz[ci formularza. 3. Opisa nagBówki wszystkich sze[ciu etykiet odpowiednio do przeznaczenia pól, które opisuj. WBa[ciwo[ci Font elementów Tlabel doda atrybut Bold, co poprawi ich widoczno[ na ekranie. 4. Ustawi wBa[ciwo[ DataSource wszystkich sze[ciu komponentów DBText na dmRENTMAN.dsTenantInfo. 5. Ustawi wBa[ciwo[ DataField wszystkich sterowników na odpowiadajce im pola zbioru odpowiedzi quTenantInfo. Uruchamianie zapytania Po umieszczeniu na wBa[ciwych miejscach wszystkich komponentów, nale|y jeszcze rozstrzygn, jak bdziemy inicjowa realizacj zapytania. Godne rozwa|enia s dwie mo|liwo[ci. Pierwsza to wyzwolenie zapytania w chwili wy[wietlania si formularza. W chwili edycji przez u|ytkownika wykazu prac powinno zosta zainicjowane zapytanie, by umo|liwi dostp do wBa[ciwych informacji w momencie ukazania si formularza. Drug mo|liwo[ci realizacji zapytania powinien by wybór dowolnej pozycji z listy rozwijalnej okienka dlcbPROPERTY_ADDRESS, by uaktualni informacje z chwil zmiany interesujcej u|ytkownika nieruchomo[ci. Oczywi[cie zmiana wybranej nieruchomo[ci musi spowodowa podobn zmian pól z danymi o najemcy. 366 Cz[ II Aby powiza realizacj zapytania z wy[wietlaniem formularza, nale|y wybra go (by mo|e ze wzgldu na przysBanianie formularza przez inne elementy, zajdzie konieczno[ wykorzystania listy rozwijalnej inspektora obiektów), nastpnie klikn stron Event inspektora obiektów. Kolejno przewin list w dóB i dwukrotnie klikn zdarzenie OnShow. W edytorze kodów musimy wpisa: with dmRENTMAN.quTenantInfo do begin If Active then Close; ParamByName( PROPERTY_NUMBER ).AsInteger:= ¥' dmRENTMAN.TAWORDERPROPERTY_NUMBER.AsInteger; Open; end; Procedura zamyka komponent zapytania, je[li jest otwarty i ponownie go otwiera. Poniewa| nowy komponent jest poBczony ze zródBem danych (DataSource) dsTenantInfo, efektem bdzie uaktualnienie danych. Nastpnie, wykorzystajc zdarzenie OnClick komponentu dlcbPROPERTY_ADDRESS. wciskamy klawisz F12, aby powróci do projektanta formularzy i klikamy element listy wyszukiwania DBLLookupComboBox komponentu dlcbPROPERTY_ADDRESS. Wybieramy stron Event inspektora obiektów, a na li[cie wyboru zdarzenie OnClick. Wybieramy z listy pozycj FormShow. W ten sposób zapytanie bdzie wykonywane pierwszy raz w chwili wy[wietlenia formularza oraz przy ka|dym klikniciu komponentu dlcbPROPERTY_ADDRESS. Rysunek 11.10 ilustruje wygld skorygowanego formularza. Rysunek 11.10. Skorygowany formularz kombinowany WORDER. Testowanie formularza Zachowujemy wyniki pracy i uruchamiamy aplikacj. Rysunek 11.11. ilustruje wygld formularza w czasie pracy. Formularze 367 Rysunek 11.11. PrzeksztaBcony formularz fmRWORMDE0 w czasie pracy programu. Zmiana wielko[ci formularza i jego elementów Aby optymalnie wykorzysta komponenty Panel, mo|e zaistnie potrzeba powikszenia formularza do peBnego ekranu lub zmiana jego wielko[ci. W czasie przeksztaBceD elementy formularza powinny zachowywa pewne podstawowe proporcje (mo|na to sprawdzi powikszajc blankiet do peBnego ekranu). Kolejne udoskonalenia Mo|na zaprojektowa jeszcze jedno udoskonalenie, majce na celu zwikszenie przydatno[ci formularza. Poniewa| ka|da warto[ pola WORK_TYPE_CODE niesie informacj o czasie trwania pracy okre[lonej w odpowiednim rekordzie tabeli WORKTYPE, mo|e by korzystne wyliczanie przez aplikacj przewidywanego czasu wykonywania zadania i regulowanie czasem zakoDczenia prac objtych wykazem. Najpro[ciej osign to dziki zapytaniom SQL. Budowanie zapytaD przy pomocy konstruktora zapytaD (Query Builder) UWAGA Nie wszystkie wersje Delphi zawieraj wizualnego konstruktora zapytaD (Visual Query Builder). Je[li posiadana przez czytelnika wersja produktu nie jest wyposa|ona w to narzdzie, mo|na opu[ci fragment  Kolejne udoskonalenia Prac z wizualnym konstruktorem zapytaD rozpoczniemy od nastpujcych czynno[ci: 1. Zamkn aplikacj RENTMAN i powróci do Delphi. 2. W wizualnym projektancie formularzy uaktywni moduB danych dmRENTMAN i umie[ci w nim komponent Query. 368 Cz[ II 3. Zmieni nazw elementu Query na quWorkDuration i ustawi wBa[ciwo[ Database na dbRENTMAN. 4. Prawym klawiszem myszy klikn na komponencie Query i wybra z menu pozycj Query Builder. 5. Je[li wy[wietli si okienko dialogowe z zapytaniem o wybór u|ywanej bazy danych, to nale|y klikn dwukrotnie na zbiorze dbRENTMAN. 6. Kolejne okienko dialogowe sBu|y do wyboru interesujcych nas tabel. Dwukrotnie klikn na tabeli WODETAIL, po czym to samo zrobi z tabel WORKTYPE. Po zamkniciu okna Add Table uka|e si kolejne okno, zawierajce obie tabele obok siebie, tak jak na rysunku 11.12. Rysunek 11.12. GBówny ekran konstruktora zapytaD (Delphi s Query Builder). 7. Przecign kolumn WORK_TYPE_KODE tabeli WODETAIL nad pole o tej samej nazwie w zbiorze WORKTYPE, co powinno spowodowa poBczenie lini obu pól. Oznacza to ustanowienie poBczenia midzy tabelami, wykorzystujcego wspóln pozycj WORK_TYPE_KODE. Dziki temu zwizkowi bdziemy [ciga z tabel interesujce nas informacje. 8. Dwukrotnie klikn kolumn WORDER_NUMBER tabeli WODETAIL, aby doda j do zapytania. Jej nazwa powinna pojawi si w dolnej cz[ci okna dialogowego. 9. Przewin list w dóB i w polu kryteria wpisa = :WORDER_NUMBER, aby okre[li otrzymane informacje. 10. Prawym klawiszem myszy klikn okno Option pod rubryk WORDER_NUMBER i z podrcznego menu wybra pozycj Group. Dziki temu pola bd grupowane zgodnie z zawarto[ci kolumny WORDER_NUMBER. 11. Na pasku narzdzi klikn przycisk Expression Builder (ikona  a+b ). Przy pomocy otwartego w ten sposób okna dialogowego Expression, zdefiniowa wyra|enie sBu|ce do sumowania caBkowitego czasu trwania prac z wykazu: Formularze 369 12. Wpisa WorkDuration w linii Expression Name, nastpnie - z listy rozwijalnej - wybra nazw tabeli WORKTYPE. 13. Na li[cie Functions podwójnie klikn funkcj sum (), a nastpnie równie| podwójnie na pozycji TaskDuration listy Column. 14. Klikn kolejno przyciski Save i Close, aby powróci do gBównego okna dialogowego konstruktora zapytaD. (por. Rysunek 11.13). Rysunek 11.13. Pole okna dialogowego Expression z konstruktora zapytaD Delphi. Aby zobaczy rezultat pracy, nale|y klikn ikon SQL (ikona w ksztaBcie okularów na pasku narzdziowym). Wygenerowany przez konstruktora zapytaD kod SQL bdzie wygldaB mniej wicej tak: SELECT WODETAIL.WORDER_NUMBER , (sum( WORKTYPE.TASKDURATION)) as WorkDuration FROM WODETAIL WODETAIL, WORKTYPE WORKTYPE WHERE (WODETAIL.WORK_TYPE_CODE=WORKTYPE.WORK_TYPE_CODE) AND ( ( WODETAIL.WORDER_number= :WORDER_number ) ) GROUP BY WODETAIL.WORDER_NUMBER Po uproszczeniu zapytanie mo|e wyglda nastpujco: SELECT SUM ( WORKTYPE.TASKDURATION) WorkDuration FROM WODETAIL, WORKTYPE where WODETAIL.WORK_TYPE_CODE=WORKTYPE.WORK_TYPE_CODE and WORDER_NUMBER= :WORDER_NUMBER Zapytanie sumuje czas pracy, okre[lony w wykazie prac w rozbiciu na zadania elementarne. Podczas pracy programu pole WORDER_NUMBER jest wypeBnione warto[ciami, wic zapytanie bdzie dodawaBo jedynie warto[ci rekordów odpowiadajcych aktualnemu numerowi zestawienia prac. 370 Cz[ II Prac koDczymy zamykajc okna SQL Statement oraz konstruktora zapytaD. Nowe zapytanie zostanie zachowane automatycznie, jako wBa[ciwo[ SQL komponentu quWorkDuration. Wykorzystanie zapytania w formularzu Aby móc wykorzysta zapytanie w formularzu, nale|y: 1. Klikn podwójnie wBa[ciwo[ Params nowego komponentu quWorkDuration i okre[li typ danych parametru WORK_ORDER_NUMBER na Integer; wciskajc klawisz OK zachowa wprowadzone zmiany. 2. Podwójnie klikn na komponencie Query, aby otworzy edytor pól. 3. Prawym klawiszem myszy klikn na edytorze i wybra opcj Add fields. 4. Wybra z listy pozycj WorkDuration, klikn OK i zamkn edytor pól. Umo|liwi to Batwe odwoBywanie si do kolumny poprzez jej nazw. Zdarzenie AfterPost Po skompletowaniu zapytania jeste[my gotowi do poBczenia go z tabel WODETAIL. W tym celu klikamy komponent taWODETAIL, a nastpnie stron Event inspektora obiektów. Podwójnie klikamy na zdarzeniu AfterPost i dodajemy nastpujcy kod: with quWorkDuration do begin if Active then Close; ParamByName ( WORDER_NUMBER ).AsInteger:=taWODETAILWORDER_NUMBER. ¥' AsInteger; Open; taWORDEREndDate.AsFloat:=taWORDERStartDate.AsFloat+ quWorkDurationWorkDuration.AsFloat; end; Arytmetyka dat w Delphi Nastpny fragment programu uruchamia zapytanie, po czym dodaje jego rezultat do kolumny StartDate w tabeli WORDER, okre[lajc dat zakoDczenia prac. Takie podej[cie oparte jest na dwóch podstawowych przesBankach. Pierwsza wynika ze sposobu przechowywania daty i czasu (w postaci liczby zmiennoprzecinkowej). Jej cz[ caBkowita okre[la liczb dni od 31 grudnia 1899 r. , za[ cz[ uBamkowa czas obliczony jako uBamek doby. Umo|liwia to dodanie dni do daty przez zsumowanie caBkowitych cz[ci liczb. Drugie zaBo|enie to przyjcie, |e edycja bie|cego rekordu tabeli WORDER wskazuje go jako wBa[ciwy zbiór danych. Innymi sBowy, zaznaczenie zestawienia prac w formularzu tabelarycznym wybiera automatycznie wBa[ciwe elementy tabeli WORDER. Odpowiedni rekord pozostaje Formularze 371 bie|cym w tabeli, dopóki nie przeniesiemy kursora w inne miejsce. Oznacza to, |e nie trzeba przeszukiwa tabeli WORDER celem uaktualnienia wBa[ciwego rekordu. Zdarzenie AfterDelete Zdarzenie Post nie jest jedynym, które powinno powodowa ponowne przeliczenie czasu trwania prac. Program powinien zareagowa tak samo równie| na usunicie rekordu z tabeli WODETAIL. W tym celu, w inspektorze obiektów nale|y zaznaczy zdarzenie AfterDelete, klikn na li[cie rozwijalnej i wybra pozycj taWODETAILAfterPost. W ten sposób oba zdarzenia bd powodowaBy jednakowe skutki. Testowanie rozszerzeD Uruchamiamy aplikacj i wprowadzamy oraz usuwamy kilka pozycji zakresu robót. Podczas edycji data zakoDczenia powinna si odpowiednio zmienia. Formularz jest automatycznie aktualizowany podczas zmiany kolumny EndDate w formularzu moduBu danych fmRENTMAN. Jednocze[nie od[wie|anie terminu zakoDczenia pracy po ka|dej zmianie w szczegóBowym wykazie prac nie wyklucza wpisania przez u|ytkownika (w miejsce skalkulowanego terminu) wBasnej daty ukoDczenia zadania. Mo|e j wprowadzi tak samo jak przed skonstruowaniem zapytania. Ostatnia poprawka Omówimy teraz ostatnie ulepszenie, które mo|e poprawi u|yteczno[ formularza do zarzdzania wykazami prac. W sytuacji, gdy pracownicy s regularnie wyznaczani do ró|nych zadaD, skierowanie robotnika do nowej pracy, je[li nie skoDczyB poprzedniej, nie ma wikszego sensu. Dlatego mo|na si zastanowi nad takim filtrowaniem listy, aby u|ytkownik formularza mógB wybiera jedynie tych pracowników, którzy w danej chwili nie s zajci. Filtry Najlepszym rozwizaniem zadania jest lokalny filtr tabeli EMPLOYEE. (SBowo lokalny oznacza w tym kontek[cie rozwizanie narzucone na poziomie aplikacji, a nie DBMS.) Aplikacja bdzie pobieraBa z tabeli wszystkie rekordy, ale na formularzu bd widoczne tylko te, które dotycz aktualnie nie zajtych pracowników. Budowa zapytaD wykorzystywanych przez filtr Przy pomocy poni|szych czynno[ci zbudujemy niezbdny dla filtru komponent Query: 372 Cz[ II 1. Je[li aplikacja jeszcze pracuje, to nale|y wyBczy j i uruchomi Delphi. 2. Do projektanta formularzy wczyta moduB danych dmRENTMAN. 3. Umie[ci na formularzu komponent Query, zmieni jego nazw na quEMPLOYEEAVAILABLE i ustawi wBa[ciwo[ Database na dbRENTMAN. 4. Klikn dwukrotnie na wBa[ciwo[ci SQL komponentu Query i wpisa nastpujcy kod: select max(EndDate) EndDate from WORDER where EMPLOYEE_NUMBER= :EMPLOYEE_NUMBER and WORDER_NUMBER<> :WORDER_NUMBER and STARTDATE <=  TODAY Zapytanie wybiera dat zakoDczenia pracy przez danego pracownika zatrudnionego przy realizacji rozpocztego zestawu zadaD. Je[li prace pewnego wykazu maj by rozpoczte w przyszBo[ci, pracownik jest wykazywany jako zdolny do podjcia pracy. Aktualizacja polega na pobieraniu daty zakoDczenia robót przez pracownika z tabeli WORDER. DokoDczenie zapytania wymaga nastpujcych czynno[ci: 1. Po wprowadzeniu tekstu zapytania wcisn przycisk OK i opu[ci edytor SQL. 2. Klikn dwukrotnie na wBa[ciwo[ci Params komponentu Query. Ustawi typy danych obu parametrów na Integer i wcisn przycisk OK, aby zachowa zmiany. 3. Klikn dwukrotnie na komponencie Query, by otworzy edytor pól. 4. Prawym klawiszem myszy klikn na li[cie pól i wybra opcj Add fields; klawiszem OK zatwierdzi dodanie jednego pola i powróci do zapytania. 5. Zapytanie jest gotowe do spicia z tabel EMPLOYEE. Zamkn edytor pól, w inspektorze obiektów wybra komponent taEMPLOYEE, klikn dwukrotnie na zdarzeniu OnFilterRecord i wpisa nastpujcy kod: if Screen.ActiveForm.Name =  fmRWORMDE0 then begin with quEmployeeAvaliable do begin if Active then Close ParamByName ( EMPLOYEE_NUMBER )AsInteger:= ¥' taEMPLOYEEEMPLOYEE_NUMBER.AsInteger; ParamByName ( WORDER_NUMBER )AsInteger:= ¥' taWORDERWORDER_NUMBER.AsInteger; Open; Accept:=(Trunc(quEmployeeAvaliableEndDate.AsFloat)<=Date); end; end else Accept:=True; Formularze 373 Procedura korzysta z wBa[ciwo[ci ActiveForm.Name do sprawdzenia, czy formularz WORK ORDER jest aktywny. Je[li nie, to filtrowanie nie bdzie uruchomione. Jest to dodatkowe zabezpieczenie, gwarantujce, |e filtrowanie tabeli EMPLOYEE bdzie wykorzystywane zgodnie z przeznaczeniem. WBa[ciwo[ Filtered Po napisaniu kodu zdarzenia OnFilterRecord nale|y ponownie otworzy fmRWORMDE0 i dwukrotnie klikn zdarzenie OnShow w inspektorze obiektów. Poni|ej linii  inherited wpisa nastpujc lini kodu: dmRENTMAN .taEMPLOYEE.Filtered:=True; Nastpnie powróci do inspektora obiektów, dwukrotnie klikn zdarzenie OnClose i wprowadzi nastpujc lini: dmRENTMAN.taEMPLOYEE.Filtered:=False; Gwarantujemy w ten sposób, |e filtrowanie odbywa si wyBcznie wtedy, gdy formularz fmRWORMDE0 jest na ekranie. Kolejne testowanie Uruchamiamy program i sprawdzamy wyniki. Je[li na formularzu Work Order wybierzemy list z pracownikami, powinni[my zobaczy jedynie tych, którzy nie s zaplanowani do pracy przy trwajcych projektach. (Przyjte rozwizanie zakBada, |e pracownik koDczcy prac w okre[lonym dniu powinien by widoczny na li[cie). Po próbach wracamy do Delphi. WyBczanie filtrowania Wyznaczanie tego samego pracownika do dwóch prac jednocze[nie zazwyczaj nie jest najlepszym pomysBem. Allodium chce jednak dysponowa tak mo|liwo[ci. PrzykBadowo mo|e si bowiem zdarzy, |e kto[ wykona prac wcze[niej ni| przewidywano i bdzie gotowy do przyjcia kolejnego zlecenia. Bez mo|liwo[ci wyBczania filtra nie mo|na wykorzysta wolnego pracownika, dopóki nie minie formalny termin zakoDczenia poprzedniego zadania. Majc na uwadze powy|sz sytuacj poszukamy odpowiedniego rozwizania. Pierwszym pomysBem jest wykorzystanie prostego przycisku przeBcznika (check box) do wBczania i wyBczania mechanizmu selekcji. Mo|na wymy[li wiele bardziej finezyjnych sposobów, ale nie nale|y oczekiwa, by byBy bardziej funkcjonalne. Poni|sze czynno[ci sBu| do skonstruowania przycisku przeBcznika przeznaczonego do sterowania aktywno[ci filtra: 1. Przesun komponenty dlcbEMPLOYEE_NAME idlcbPROPERTY_ ADDRESS mo|liwie jak najbardziej w lewo. 374 Cz[ II 2. Umie[ci element CheckBox bezpo[rednio po prawej stronie skBadnika dlcbEMPLOYEE_NAME i usun jego nagBówek. 3. Nazwa nowy komponent ckFilteravailable. 4. Nada elementowi wielko[ umo|liwiajca wy[wietlenie jedynie przycisku przeBcznika; nagBówek zostanie utworzony oddzielnie. 5. Klikn dwukrotnie na wBa[ciwo[ci Checked celem wyboru okienka. 6. Umie[ci komponent etykiety ponad lub z prawej strony pola wyboru. Ustawi wBa[ciwo[ AutoSize na False, WordWrap na True i opisa nagBówek na przykBad Czy filtrowa pracowników?. 7. Klikn dwukrotnie na przycisku przeBcznika, dziki czemu powinien uaktywni si edytor kodów. Wpisa nastpujcy kod do procedury obsBugi zdarzenia OnClick: dmRENTMAN.taEMPLOYEE.Filtered:=ckFilterAvailable.Chec ked; Dziki temu kliknicie na przycisku przeBcznika bdzie przeBcza wBa[ciwo[ filtrowania tabeli pracowników. Kliknicie na etykiecie powinno skutkowa tak samo jak wybór przycisku. W tym celu musimy klikn wBa[ciwy element Label, przeBczy si do inspektora obiektów, klikn zdarzenie OnClick, a nastpnie wybra zdarzenie ckFilterAvailable.Checked. W normalnych okoliczno[ciach ostatnie czynno[ci nie s potrzebne. Wybór nagBówka przycisku przeBcznika jest równowa|ny klikniciu na samym polu. Poniewa| jednak nagBówek wbudowany w przycisk przeBcznika nie jest wyposa|ony w mo|liwo[ zawijania tekstu, zmuszeni byli[my u|y samodzielnego komponentu etykiety, a nastpnie powiza go z przeBcznikiem. Alternatywnym rozwizaniem jest caBkowita rezygnacja z nagBówka i zastosowanie dymka, który pojawiaBby si w chwili umieszczenia nad obiektem kursora myszy. Tworzenie takich elementów opisane jest w rozdziale 13. Zadanie, które zakoDczy konstruowanie formularza Work Order, polega na zmianie metody OnShow, aby uzale|ni filtrowanie od stanu pola wyboru. W tym celu nale|y wybra formularz fmWORMDE0 (by mo|e zaistnieje konieczno[ skorzystania z inspektora obiektów), a nastpnie dwukrotnie klikn zdarzenie OnShow. Liniê: dmRENTMAN.taEMPLOYEE.Filtered:=True; zastpi nastpujc procedur: with dmRENTMAN.taEMPLOYEE do begin Filtered:=ckFilterAvailable.Checked; Formularze 375 If Filtered then begin Close; Open; end; end; Napisany fragment programu gwarantuje, |e filtrowanie tabeli pracowników bdzie zale|aBo od ustawienia przycisku przeBcznika. Zamknicie i otwarcie formularza zapewnia prawidBowe dziaBanie filtra. Prace nad formularzem kombinowanym, obsBugujcym zestawienia robót, dobiegBy koDca, mo|na wic przej[ do tabeli CALL. Formularz Call Tabela CALL, podobnie jak WORDER, bdzie obsBugiwana przez dwa oddzielne formularze. Pierwszemu nadamy posta tabelaryczn, a drugi bdzie sBu|yB do edycji. Formularz tabelaryczny wykorzystamy jedynie do wybierania rekordów. Formularz tabelaryczny Z menu Delphi wybieramy opcj File\New. Nowy formularz bdzie dziedziczyB wBa[ciwo[ci fmGridForm. Zmieniamy jego nazw na fmRCALGRD0, a nagBówek przykBadowo na: Przegldanie zleceD. Zachowujemy formularz pod nazw RCALGRD0.PAS. Dostp do moduBu danych Podobnie jak poprzednie, tak i ten formularz wymaga poBczenia z moduBem danych, aby móc korzysta z tabeli CALL i obiektów DataSource. Z menu File wybieramy opcj Use Unit i dwukrotnie klikamy list na pozycji RENDATA. Wybieramy komponenty DBGrid iDBNavigator i ustawiamy im zródBo danych (wBa[ciwo[ DataSource) na dmRENTMAN.dsCall. W ten sposób przyporzdkowali[my obu elementom t sam baz danych: tabel CALL. Pola wyszukiwania Rozpoczniemy od zdefiniowania pola wyszykiwania, które przetBumaczy kolumn PROPERTY_NUMBERS na odpowiedni adres. Przy pomocy nastpujcych czynno[ci ustawiamy pole PROPERTY_ADDRESS w tabeli taCALL: 1. PrzeBczy si do moduBu danych dmRENTMAN i wywoBa edytor pól poprzez dwukrotne kliknicie na komponencie taCALL. 2. Utworzy nowe pole, klikajc prawym klawiszem myszy na li[cie i wybierajc pozycj New field. 376 Cz[ II 3. Nowe pole nazwa PROPERTY_ADDRESS, okre[li jego typ jako String, a rozmiar na 30. 4. Ustawi wBa[ciwo[ci: Field Type na Lookup, Key Fields na PROPERTY_NUMBER, DataSet na taPROPERTY, Lookup Keys na PROPERTY_NUMBER i Result Field na ADDRESS. 5. Zachowa definicj przy pomocy przycisku OK, nastpnie zamkn edytor pól. Dodanie pola wyszukiwania PROPERTY_ADDRESS do tabeli CALL umo|liwia wy[wietlanie zamiast numeru wiadomo[ci bardziej istotnej z punktu widzenia programu. Dziki oprogramowaniu pól wyszukiwania dostpnemu w Delphi, mamy dodatkowe korzy[ci pozwalajce ustawia warto[ci pól wyszukiwania, na przykBad przy pomocy komponentu DBLookupComboBox. Nadawanie polom warto[ci domy[lnych w czasie pracy programu Zdefiniujemy mechanizm, który pozwoli nadawa polom CALLDATE i CALLTIME domy[lne warto[ci bie|cej daty i czasu. W tym celu wybieramy komponent taCALL, a nastpnie dwukrotnie klikamy zdarzenie OnNewRecord w inspektorze obiektów. Nastpujcy kod zródBowy pozwala wyznaczy domy[lne warto[ci pól w momencie dodawania rekordu do tabeli taCALL: taCALLCallDate.Value:=Date; taCALLTimeValue:=TimeToSTR(Time); Konfigurowanie kolumn wy[wietlanych przez DBGrid Nastpujce czynno[ci konfiguruj kolumny komponentu DBGrid: 1. PrzeBczy si z powrotem do formularza fmRCALLGRD0 i wybra element DBGrid. 2. Dwukrotnie klikn na wBa[ciwo[ci Columns i wybra opcj Add All Fields. 3. Usun kolumn PROPERTY_NUMBER i przecign kolumn PROPERTY_ ADDRESS na gór listy przed pole DESCRIPTION. 4. Ustawi pole CALL_NUMBER jako Read-Only i zamkn edytor kolumn. Wykorzystanie komponentu DBGrid do wybierania rekordów Nowo stworzony formularz nie powinien umo|liwia edycji w jakiejkolwiek formie. Najlepszym rozwizaniem jest ustawienie wBa[ciwo[ci Read-Only komponentu DBGrid na True. Zapobiega to jakimkolwiek zmianom danych. Komponent wymaga dodatkowego oprogramowania, umo|liwiajcego w intuicyj- ny sposób wybieranie rekordów. Powszechnie przyjte w aplikacjach dla Windows Formularze 377 dwukrotne kliknicie wiersza powinno spowodowa jego zaznaczenie. Aby to osign, nale|y uto|sami zdarzenie OnDbClick ze zdarzeniem btEditClick przycisku btEdit. Nieco pózniej wpiszemy kod obsBugujcy komponent DBNavigator, tak aby podwójne kliknicie wiersza tabeli powodowaBo edycj zaznaczonego rekordu w innym formularzu. Powikszenie formularza do peBnego ekranu Ustawiamy wBa[ciwo[ WindowState formularza na wsMaximized i powikszamy go do peBnego ekranu. Zmieniamy nastpnie rozmiar panelu górnego, tak aby [rodkowy nie zajmowaB nadmiernej powierzchni, po czym przywracamy formularz do oryginalnego rozmiaru. Modyfikacja dziaBania komponentu DBNavigator Poniewa| pierwszy formularz ma by jedynie furtk otwierajc drog do nastpnego, jedyn prac, jak musimy wykona, jest okre[lenie sposobu jego wywoBania. W tym przypadku zmienimy domy[lne ustawienie komponentu DBNavigator i zaprogramujemy go tak, aby powodowaB otwarcie formularza do edycji danych. Klikamy zatem dwukrotnie na komponencie DBNavigator i dodajemy nastpujcy kod do obsBugi zdarzenia OnClick: With DBNavigator do case Button of nbInsert: begin DataSource.DataSet.Insert; // fmRCALEDT0.Show; end; nbEdit: begin DataSource.DataSet.Insert; // fmRCALEDT0.Show; end; end; Poniewa| btEdit wywoBuje zdarzenie BtnClick kontrolki DBNavigator, a wybranie DBGrid uruchamia procedur analogiczn do wci[nicia przycisku DBEdit, to wszystkie trzy metody dziaBaj jednakowo i sBu| wywoBaniu formularza do edycji tablicy CALL. WywoBanie metody Show drugiego formularza ujte jest jako komentarz, formularz do edycji jeszcze nie istnieje. Zbudujemy go za chwil. PoBczenie formularza z aplikacj Zanim przejdziemy do drugiego formularza, najpierw powinni[my sprawdzi, jak dziaBa pierwszy, ZaBadujmy gBówne okno programu fmRSYSMAB0 do projektanta 378 Cz[ II i kliknijmy dwukrotnie opcj Call menu Table. Przy pomocy edytora kodu wpisujemy: fmRCALGRD0.Show; Kolejnym krokiem, po zaprogramowaniu opcji File\Calls, jest udostpnienie jej metody OnClick - to jest Calls1Click przyciskowi narzdziowemu sbCalls, przeznaczonemu do wywoBywania formularza. DziaBanie obu narzdzi musi by identyczne. Je[li opcja menu i przycisk s gotowe, pozostaje jeszcze doda moduB RCALGRD0 do deklaracji Uses moduBu RSSYSMAN0 naszej aplikacji. Chcc zobaczy formularz, wciskamy klawisz F9, by uruchomi program, na koniec zamykamy aplikacj i wracamy do Delphi. Rysunek 11.14. Kompletny formularz siatkowy CALL. Formularz do edycji Zajmiemy si obecnie formularzem, którego zadaniem bdzie udostpnianie pojedynczych rekordów tabeli i umo|liwienie ich wprowadzania oraz edycji. Do obsBugi tabel wielokolumnowych lub do cigBego wprowadzania danych, najlepiej nadaj si formularze, udostpniajce pojedynczy rekord. Formularze tabelaryczne sprawdzaj si przy przeszukiwaniu zbiorów, ale do szybkiego wprowadzania danych lepszym rozwizaniem jest u|ywanie wyspecjalizowanego narzdzia. W naszym przypadku zapisujemy w tabeli telefony od obecnych i przyszBych najemców. ObsBuga komputera powinna absorbowa osob odpowiadajc na wezwania jedynie w stopniu niezbdnie koniecznym. Telefonistka lub telefonista powinien móc wpisa potrzebne dane bez przecigania rozmowy. Dlatego zaprojektowali[my jeden formularz do szybkiego przegldania caBej tabeli, a drugi do wprowadzania i aktualizacji jej rekordów. Formularze 379 Tworzymy nowy formularz, dziedziczcy wBa[ciwo[ci klasy fmEditForm, nazywamy go fmRCALEDT0 i wymy[lamy odpowiedni nagBówek, na przykBad: ObsBuga wezwaD telefonicznych. Zabezpieczenie formularza przed zmian rozmiaru Aby uniemo|liwi zmian wielko[ci okna dialogowego, nale|y wybra odpowiedni wBa[ciwo[ BorderStyle, tak jak bsDialog. WBa[nie w ten sposób konfigurujemy nasz formularz, zmieniamy styl obramowania na bsDialog i redukujemy jego wBa[ciwo[ BorderIcons na przypominajcy biSystemMenu (biMaximize i biMinimize ustawiamy na False). Musimy zapewni formularzowi dostp do moduBu danych. Wybieramy opcj File\Use Unit i dwukrotnie klikamy pozycj RENDATA na li[cie moduBów. Po ustanowieniu poBczenia zapisujemy nowy formularz na dysku pod nazw RCALEDT0.PAS. WypeBnianie formularza komponentami Na górnym panelu formularza umieszczamy: trzy kontrolki DBEdit, jedn DBLookupComboBox, siedem DBText oraz po jednej typu Label dla ka|dego elementu sterujcego. Ustawiamy warto[ dmRENTMAN.dsCAAL wBa[ciwo[ci DataSource kontrolki DBNavigator, najwy|szego komponentu DBText oraz wszystkich kontrolek do edycji. Te elementy bd wspóBpracowa z tabel CALL. PozostaBe sze[ komponentów DBText Bczymy zdmRENTMAN. dsTenantInfo ustawiajc odpowiednio ich wBa[ciwo[ DataSource - bd wy[wietlaBy nazwisko najemcy i informacje adresowe zwracane przez skonstruowany wcze[niej komponent quTenantInfoQuery. Jedn z najwa|niejszych zalet umieszczenia elementu quTenantInfo na formularzu dmRENTMAN jest mo|liwo[ korzystania z niego z dowolnego formularza, który u|ywa moduBu danych zawierajcego ten komponent. Po upewnieniu si, |e do ka|dego elementu sterowania danymi dodali[my etykiet, podobnie jak przy formularzu tabeli WORDER, dla lepszej widoczno[ci opisów, powinni[my nada im atrybut Bold. Rozmieszczamy skBadniki na panelu, wzorujc si na rysunku 11.15. Zwracamy uwag, aby elementy DBText, obsBugujce zbiór danych dsCALL, znalazBy si mniej wicej po lewej stronie i w górnej cz[ci okienka dialogowego. WBa[ciwo[ci DataField poszczególnych elementów konfigurujemy zgodnie z tablic 11.6. 380 Cz[ II Tablica 11.6. Komponenty umieszczone na górnym panelu i ich gBówne wBa[ciwo[ci. Nazwa Etykieta Komponent Pole danych dteCALL_NUMBER Call No. DBText CALL_NUMBER dedCallDate Date DBEdit CALLDATE dedCallTime Time DBEdit CALLDATE dlcbPROPERTY_ADDRE Property DBLookupComboB PROPERTY_ADDRE SS ox SS dedDescription Description DBEdit DESCRIPTION dteCity City DBText CITY dteState State DBText STATE dteZip ZIP DBText ZIP dteAddition Addition DBText ADDITION dteTenantName Tenant DBText NAME dteHomePhone HomePhone DBText HOMEPHONE Rysunek 11.15. Wstpna posta formularza do edycji tabeli CALL. WywoBanie procedury wykonania zapytania Po umieszczeniu na wBa[ciwych miejscach wszystkich komponentów nale|y jeszcze rozstrzygn, jak bdziemy inicjowa realizacj zapytania. Godne rozwa|enia s dwie mo|liwo[ci. Pierwsza to wykonanie zapytania w chwili wy[wietlania si formularza. W momencie edycji przez u|ytkownika wykazu prac, powinno zosta zainicjowane zapytanie, by umo|liwi dostp do wBa[ciwych informacji w momencie ukazania si formularza. Drugim zdarzeniem powodujcym realizacj zapytania; powinien by wybór dowolnej pozycji z listy Formularze 381 rozwijalnej okienka dlcbPROPERTY_ADDRESS, by uaktualni informacje z chwil zmiany interesujcej u|ytkownika nieruchomo[ci. Oczywi[cie zmiana wybranej nieruchomo[ci musi spowodowa podobn zmian pól z danymi o nazwisku i adresie najemcy. Aby powiza realizacj zapytania z wy[wietlaniem formularza, nale|y wybra jego komponent (by mo|e, ze wzgldu na przysBanianie formularza przez inne elementy, zajdzie konieczno[ wykorzystania listy rozwijalnej inspektora obiektów), nastpnie klikn stron Event inspektora obiektów. Przewin list w dóB i dwukrotnie klikn zdarzenie OnShow. W edytorze kodów musimy wpisa nastpujce polecenia: with dmRENTMAN.quTenantInfo do begin If Active then Close; ParamByName( PROPERTY_NUMBER ).AsInteger:= dmRENTMAN.taCALLPROPERTY_NUMBER.AsInteger; Open; end; Procedura zamyka komponent zapytania (je[li jest otwarty) i ponownie go otwiera. Poniewa| nowy komponent jest poBczony ze zródBem danych (DataSource) dsTenantInfo, efektem bdzie uaktualnienie danych. Drugi miejscem wywoBania zapytania bdzie zdarzenie OnClick komponentu dlcbPROPERTY_ADDRESS. Wciskamy klawisz F12, aby powróci do projektanta formularzy, klikamy nastpnie komponent dlcbPROPERTY_ADDRESS. Wybieramy stron Event inspektora obiektów, a na li[cie wyboru zdarzenie OnClick. Wybieramy z listy pozycj FormShow. W ten sposób zapytanie bdzie wykonywane pierwszy raz w chwili wy[wietlenia formularza oraz przy ka|dym klikniciu komponentu dlcbPROPERTY_ADDRESS. PoBczenie formularza z komponentami fmRCALGRD0 i fmRSYSMAN0 Po zakoDczeniu pracy nad budow formularza powinni[my doBczy go do listy deklaracji moduBów formularza tabelarycznego fmRCALGRD0, gdy| za jego pomoc bdziemy najcz[ciej uruchamia edycj. Robimy to w nastpujcy sposób: 1. Wczyta ponownie fmRCALGRD0 do projektanta formularzy. 2. Z gBównego menu wybra opcj File\Use Unit i dwukrotnie klikn list na pozycji RCALEDT0. Kolejne czynno[ci sBu| poBczeniu nowego formularza z opcj Log a Call gBównego okna aplikacji: 1. Do projektanta formularzy wczyta fmRSYSMAN0 382 Cz[ II 2. Wybra z oferty opcj File\Use Unit i dwukrotnie klikn list na pozycji RCALEDT0. 3. Wybra ponownie opcj File\Use Unit i doBczy do listy deklaracji Uses formularza fmRSYSMAN0 pozycj RENDATA. 4. Klikn dwukrotnie na opcji Log a Call i wpisa nastpujcy fragment kodu do zdarzenia OnClick: dmRENTMAN.ta CALL.Insert; fmRCALEDT0.Show; Procedura powoduje wstawienie nowego rekordu i przekazanie sterowania do formularza edycyjnego. PoBczenie formularza edycji CALL z formularzem kombinowanym tabeli WORDER Ostatnim zadaniem poprzedzajcym ukoDczenie formularza jest poBczenie go z formularzem kombinowanym tabeli WORDER. Powinni[my bowiem mie mo|liwo[ przeBczenia si do niego, bez konieczno[ci po[redniego przechodzenia przez gBówne okno aplikacji. Majc otwarte, w projektancie formularzy, okno dialogowe edycji CALL, wybieramy opcj File\Use Unit, a nastpnie dwukrotnie klikamy moduB RWORMDE0, aby umie[ci jego nazw na li[cie deklaracji Uses. Nastpnie klikamy na panelu [rodkowym i umieszczamy na nim komponent Button, bezpo[rednio obok przycisku Delete. Zmieniamy nazw obiektu na btGenerate WorkOrder, a jego nagBówek okre[lamy jako &Generate Work Order. Dopasowujemy rozmiar obiektu, tak aby mie[ciB wy[wietlany nagBówek. Teraz dwukrotnie klikamy nowy przycisk i wprowadzamy nastpujce linie programu: with dmRENTMAN do begin If (taCallWORDER_NUMBER.AsInteger=0) then begin taWORDER.Insert; taWORDER.Refresh; // Potrzebne ze wzgldu na generatory serwera taCall.Edit; taCALLWORDER_NUMBER.Value:=taWORDERWORDER_NUMBER.Value; taWORDERPROPERTY_NUMBER.Value:=taCALLWORDER_NUMBER.Value; end else begin If not taWORDER.FindKey ((taCALLWORDER_NUMBER.Value)) then raise Exception.Create ( Work Order has been deleted ); end; end; fmRWORMDE0.Show; Formularze 383 FindKey Powy|szy fragment programu jest odpowiedzialny za kilka wa|nych spraw. Po pierwsze rozró|nia generowanie nowego zakresu prac i przeprowadza edycj ju| istniejcego poprzez sprawdzenie kolumny WORDER_NUMBER tabeli CALL. Po drugie, je[li dziaBanie polega na edycji, to procedura wykorzystuje metod FindKey komponentu taWORDER do przewinicia zbioru danych nad wBa[ciwy rekord zakresu prac. Wreszcie program sprawdza wynik wykonania metody FindKey, aby mie pewno[, |e skoDczyBa si powodzeniem. Je[li nie, zgBasza wyjtek. Chocia| ze wzgldu na odno[ne wizy integralno[ci midzy tabelami CALL i WORDER takie zdarzenie nie powinno mie miejsca, to je[li si zdarzy, na ekranie pojawi si wBa[ciwy komunikat i wywoBanie okna dialogowego zakresu prac zostanie pominite. Sterowanie powróci do formularza CALL. Mo|emy odnotowa istnienie bloku try ... except, obejmujcego kod wyznaczania warto[ci kolumny WORDER_NUMBER tabeli taCALL. Powodem tego jest brak wiadomo[ci, w jakim stanie znajduje si tabela taCALL w momencie wci[nicia przycisku uruchamiajcego formularz Work Order. Kolejne stany zbioru danych mog nie by kompatybilne z okre[lonymi warto[ciami. Normalnym sposobem administrowania w takich sytuacjach jest porównanie warto[ci wBa[ciwo[ci State ze zbiorem flag, dsInactive...dsCurVal. Niestety, nie dodali[my jeszcze tych flag do moduBu przy pomocy wBa[ciwego zapisu w deklaracji Uses. Niebawem uzupeBnimy deklaracj. Dynamiczne ustawianie nagBówka przycisku Dodatkiem do przycisku uruchamiajcego formularz Work Order mo|e by nagBówek, który zmienia si dynamicznie w zale|no[ci od tego, czy wci[nicie spowoduje dodanie nowego zakresu prac, czy edycj ju| istniejcego. WBa[ciwym miejscem na zaimplementowanie tego uBatwienia jest zdarzenie OnShow formularza edycji tabeli CALL. Wybieramy formularz, dwukrotnie klikamy zdarzenie OnShow w inspektorze obiektów i przy pomocy edytora kodu wpisujemy na pocztku procedury nastpujce polecenia: If (dmRENTMAN.taCALLWORDER_NUMBER.AsInteger=0) then btGenerateWorkOrder.Caption:= &Generate Work Order else btGenerateWorkOrder.Caption:= Edit &Work Order ; 384 Cz[ II UWAGA Jakikolwiek kod dodany do obsBugi zdarzenia OnShow bdzie równie| wykonywany po klikniciu komponentu dlcbPROPERTY. Dzieje si tak ze wzgldu na poBczenie zdarzenia OnClick z metod FormShow. W naszym przypadku nie mamy nic przeciwko temu, ale trzeba mie [wiadomo[ konsekwencji wykorzystywania wspólnego kodu do obsBugi kilku klas, zwBaszcza istotnie ró|nych. Testowanie formularza Zachowujemy projekt i uruchamiamy program. Rysunek 11.16. ilustruje dziaBanie nowego formularza. Rysunek 11.16. Skompletowany formularz do edycji tabeli CALL w czasie pracy.

Wyszukiwarka