Sunteți pe pagina 1din 51

CAPITOLUL 1 Introducere n Programarea Orientat-Obiect

Programarea orientat obiect (POO) revoluioneaz aproape orice aspect al dezvoltrii aplicaiilor cu Visual FoxPro, de la faza de analiz i proiectare pn la faza de scriere a codului de program i testarea aplicaiilor i a componentelor aplicaiilor. De asemenea, Visual FoxPro, ca i Visual C++ de altfel, este un limbaj hibrid, adic dezvoltatorii de programe pot alege ntre metodele POO i programarea modular. POO sre o altfel de abordare dect programarea modular, n faptul c POO lucreaz cu entiti de genul obiectelor. Dac se dorete adaptarea unei aplicaii ntr-o nou form, avnd n vedere c exist o form modificat a unei aplicaii mai vechi, se realizeaz modificrile pe baza unui procedeu numit subclasare, i anume preluarea vechilor obiecte ale aplicaiei i modificarea acestora dup noile proprieti. Comportamentul i atributele obiectelor originale sunt automat aduse i la noile obiecte modificate, acest lucru numindu-se motenire. n schimb dac se modific cumva obiectele originale, schimbrile fcute sunt aduse imediat i asupra obiectelor noi, realizate cu ajutorul subclasrii, prin modificarea obiectelor originale. POO utilizeaz nite termeni, pentru a explica expres conceptele POO, i anume: motenire, ncapsulare i polimorfism. Primul i cel mai important concept cheie al POO este obiectul. Un obiect este un pachet de informaii i aciuni. Un obiect se conine pe sine. Toate cunotiinele i comportamentele unui obiect
1

sunt coninute n acesta. Acest concept este cunoscut sub numnele de ncapsulare. Orice obiect este caracterizat de propireti i evenimente. Proprieti Datele dintr+un obiect sunt denumite proprieti. O proprietate (n termenii Visual FoxPro) este foarte simplu o variabil de memorie care este ataat la obiect i care are un anumit scop. Utilizarea valorii proprietii i modificarea ei se face utiliznd numele obiectului urmat de punct (.) i apoi de numele proprietii. Propreitile pot conine orice tipuri de date care sunt valide pentru variabilele de memorie Visual FoxPro. De exemplu, dac avem o proprietate numit lEsteNou care este ataat la un obiect numit oTest, se poate interoga valoarea proprietii n felul urmtor: oTest.lEsteNou Metode Pe lng faptul c obiectele au date ataate, ele pot executa anumite aciuni. Aceste aciuni sunt reprezentate de fapt de codul de program care este scris n procedurile care sunt ataate la obiect. Aceste proceduri sunt denumite de fapt metode. Apelarea unei metode se face n mod asemntor cu a unei proprieti, i anume numele obiectului, urmat de punct (.) i de numele metodei, dup cum urmeaz: oTest.Print() Tehnic, parantezele care apar la sfritul numelui metodei sunt necesare numai dac se ateapt returnarea unei valori sau dac cumva se transmit parametrii metodei. Sugestia noastr este de a se utiliza
2

ntotdeauna paranteze pentru siguran, n acest caz fiind i siguri c se apeleaz o metod. n cazul apelrii unei metode dup care se ateapt returnarea unei valori, se poate salva valoarea returnat n modul urmtor: lValoareReturnat = oTest.Print() Evenimente Evenimentele sunt aciuni care se ntmpl. De exemplu, fcnd click pe butonul stnga al mouse-ului se declaneaz un eveniment. Evenimentele pot fi cauzate de aciunea utilizatorului (ca n cazul de mai sus) sau de ctre sistem nsui (ca n cazul n care apare o eroare). Dac creezi o clas de tipul unui buton de comand n Visual FoxPro, poi ataa cod (ca o metod) la evenimente. Dac se declaneaz evenimentul (de exemplu, utilizatorul face click stnga cu mouse-ul deasupra butonului de comand), metoda asociat (care este metoda click) este apelat automat. n Visual FoxPro, se pot ataa metode la tot felul de evenimente: dac se d click pe mouse, dac se ia mna de pe mouse, se poate apela o metod n momentul n care un obiect este creat (evenimentul Init) sau invers n momentul n care obiectul este ters (evenimentul Destroy). Apelarea evenimentelor se face n acelai mod ca i apelarea metodelor. Clase Pn la acest punct, toate discuiile din acest capitol au fost centrate n jurul obiectelor. n programarea orientat-obiect, obiectele nu sunt niciodat programate, ci mai degrab obiectele de baz (numite clase) pot fi programate. Toate obiectele sunt instaniate (adic, create) pornind de la clase. De aceea, toate programele se fac
3

la nivelul clasei. Odat un obiect instaniat pe baza unie clase, tot ceea ce trebuie s faci este s interacionezi cu el. Nu se adaug sau se modific metode existente ntr-un obiect, ci mai degrab se adaug i se modific metode n clase pe baza crora se instaniaz obiectele. Un exemplu de clas: DEFINE CLASS Clas AS Custom cNume = "" cTip = "" lEsteNou = .F. PROCEDURE AratValoare ? this.cNume ? this.cTip IF this.lEsteNou ? "Sunt Nou" ELSE ? "Sunt Vechi" ENDIF ENDPROC ENDDEFINE Define Class Clas as Custom Aceast linie de program spune Visual FoxPro c utilizatorul definete o nou clas numit Clas bazat pe o clas de baz Custom. cNume = "" cTip = ""
4

lEsteNou = .F. Liniile anterioare sunt cunoscute ca declaraii de cod. n aceat parte a definiiei clasei, se enumer variabilele (proprietile) obiectului i valorile lor iniiale. PROCEDURE AratValoare ? this.cNume ? this.cTip IF this.lEsteNou ? "Sunt Nou" ELSE ? "Sunt Vechi" ENDIF ENDPROC Aceasta este o definiie a unei metode. Apelarea unei metode va executa toate liniile de cod dintre linia PROCEDURE pn la linia ENDPROC. Instanierea Obiectelor Un obiect este instaniat cu ajutorul funciei CREATEOBJECT(). Sintaxa pentru crearea unei instane a clasei Clas: oClas = CREATEOBJECT("Clas") oClas este o variabil de memorie simpl de tipul Object.

Pentru a accesa membrii clasei Clas, se pot utiliza urmtoarele comenzi: ? oClas.cNume && Iniial gol oClas.cNume = "Popescu Ion" ? oClas.cNume && Acum arat "Popescu Ion" oClas.AratValoare() && Execut metoda AratValoare Cuvntul cheie THIS nseamn c se acceseaz metodele i variabilele membre ale obiectului nsui. Subclasarea-Bazarea unei Clase pe alt Clas S presupunem c vom defini o clas numit Formular i care definete de fapt un formular cu anumite proprieti ale sale. DEFINE CLASS Formular AS form Width=100 Height=150 PROCEDURE Init Caption = Formular1 ENDPROC ENDDEFINE Putem crea o subclas a clasei create anterior i pe care o vom denumi Formular1, subclas care va moteni toate proprietile clasei printe, adic clasa Formular, dar n plus va avea proprieti n plus fa de clasa printe. DEFINE CLASS Formular1 AS Formular
6

Name=Formular PROCEDURE Click Caption = Formular cu click ENDPROC ENDDEFINE O nsuire foarte interesant a motenirii poate accepta ceea ce i convine de la clasa printe i poate rescrie restul dup cum doreti. Acest lucru se poate realiza prin rescrie proprietii sau a metodei respective n subclasa respectiv. De exemplu n clasa Formular, clasa printe a subclasei Formular1, avem un eveniment Init, n care dm titlul formularului ca fiind Formular1, putem rescrie acest lucru n subclas prin rescrierea procedurii respective. DEFINE CLASS Formular1 AS Formular Name=Formular PROCEDURE Init Caption = Formular2 ENDPROC ENDDEFINE n acest caz am redenumit evenimentul din clasa printe rescriind aceiai procedur n subclasa Formular1. De asemenea, s presupunem c este posibil s dorii s lansai n execuie metoda din clasa printe nti i apoi s adugai ceva cod de program n plus n metoda din subclas, ca n exemplul urmtor: DEFINE CLASS Formular2 AS Formular Name=Formular PROCEDURE Init
7

Formular1::Init() Caption = Formular2 WAIT WINDOW Exemplu de apelare a unei metode din clasa printe ENDPROC ENDDEFINE Operatorul (::) este utilizat pentru a apela metodele din clasele superioare n ierarhia claselor. Metode i Proprieti Protejate La crearea unui obiect trebuie s decidei dac dorii s fie public, adic s poat s fie utilizat i de alte clase sau numai n cadrul clasei respective. Soluia n acest caz este s creai metode i proprieti protejate, care nu pot fi accesibile din afara clasei n care sau definit respectivele metode i proprieti. Acest lucru se realizeaz scriind: PROTECTED numeproprietate n seciunea n care declarai definiiile de cod, sau PROTECTED n faa liniei PROCEDURE. DEFINE CLASS Clas AS Custom PROTECTED cNume cNume = "" cTip = "" lEsteNou = .F. PROTECTED PROCEDURE AratValori ? this.cNume ? this.cTip
8

IF this.lEsteNou ? "ESTE NOU" ELSE ? "ESTE VECHI" ENDIF ENDPROC ENDDEFINE n acest exemplu ambele proprieti cNume i cTip sunt protejate, ca i metoda AratValori care este i ea protejat. ncercrile de a le accesa din afara clasei vor produce erori ca i cum aceste proprieti i metode nu ar exista. Polimorfism Polimorfismul este un alt concept care trebuie dezbtut dac se vorbete despre programarea orientat-obiect. Polimorfismul este capacitatea de a da metodelor i proprietilor din diferite clase acelai nume, chiar dac acele metode i proprieti fac lucruri cu totul diferite de la o clas la alta. De exemplu urmtoarele linii de comand: oObiect1 = CREATEOBJECT("Formular1") oObiect2 = CREATEOBJECT("Telefon") oObiect1.Execut() &&Lanseaz n execuie metoda Execut a Obiect1 oObiect2.Execut() &&Lanseaz n execuie metoda Execut a Obiect2

Crearea Obiectelor oFact = CREATEOBJECT("Factura") aceast linie de cod de program transmite un mesaj clasei Factura spunndu-i s creeze un obiect numit oFact bazat pe aceast clas. Atribuirea unei valori unei proprieti lnValoare = oFact.nValoare Aceast linie de cod de program transmite un mesaj obiectului oFact i i spune s ia valoarea proprietii nValoare i s o returneze la lnValoare. Apelarea unei metode oFact.Afiare && Afieaz obiectul oFact Se transmite un mesaj obiectului oFact spunndu-i s execute metoda Afiare. Analiz i Proiectare cu POO Programarea orientat-obiect nu ncepe cu scrierea codului de program, cu toate c pn acum am discutat numai despre implementarea fazei de scriere a obiectelor, iar acest pas este totui ultimul n crearea programelor orientate-obiect. Primul pas ce trebuie fcut este de a analiza domeniul problemei i de a proiecta ierarhia claselor. Este destul de simplu de realizat dac se respect o anumit disciplin. Analitii au apreciat c n realizarea unei aplicaii 70% din timp se pierde cu analiza orientat10

obiect (AOO) i proiectarea orientat-obiect (POO). Exist mai multe tipuri de metodologii create de nume populare n domeniul bazelor de date Grady Booch, Ivar Jacobsen i Rebecca Wirfs-Brock. Crearea i utilizarea claselor cu Visual FoxPro Definirea claselor se face utiliznd constructorul DEFINE CLASS / ENDDEFINE, dup cum urmeaz: DEFINE CLASS <numeclas> AS <clasdebaz> *-- Aici se face declararea codului PROTECTED <list variabile membru> PROCEDURE <metodproc> (param1, param2 ....) LOCAL <list de variabile locale> *-- Aici se scrie codul procedurii ENDPROC FUNCTION <metodfunc> (param1, param2 ....) LOCAL <list de variabile locale> *-- Aici se scrie codul funciei RETURN <valoarereturnat> ENDFUNC ENDDEFINE DEFINE CLASS <numeclas> AS <superclas> Aceast linie de cod comunic Visual FoxPro c se creaz o nou clas. Toate liniile de cod de program dintre DEFINE i ENDDEFINE in de definiia clasei respective. <numeclas> este

11

numele clasei nou create i <superclas> este numele clasei pe baza creia se creaz clasa cea nou. Termenul superclas mai poate fi ntlnit n terminologia de specialitate i ca o clas printe. Prin definiie orice clas creat n Visual FoxPro este o subclas a altei clase. La cel mai nalt nivel clasele create n Visual FoxPro sunt subclase a ccea ce Microsoft numete clase de baz, clase care apar n tabelul urmtor. Visual FoxPro 6.0 Clase de Baz Nume Clas ActiveDoc Descriere Obiectul document active care poate fi gzduit ntr-un browser de tipul Internet Explorer. CheckBox O caset de validare standard, control similar cu o caset de validare din FoxPro 2.x. Column O coloan ntr-un control grid. ComboBox O caset combinat (combo box) similar cu un control pop-up n FoxPro 2.x. CommandButton Echivalent cu un pushbutton n FoxPro 2.x. CommandGroup Un grup de butoane de comand care opereaz mpreun. Sunt echivalente cu un grup de pushbutton din FoxPro 2.x controlate de o variabil Container Un obiect generic proiectat pentru a putea conine alte obiecte n el. Este utilizat n cazul crerii unei clase care conine mai multe obiecte n ea. Control Acelai lucru ca i clasa container , ns de data aceasta referirea nu se mai face la clasa container ci la clasa control.
12

Nume Clas Cursor

Descriere Definiia unui cursor ntr-un mediu de date. Custom n mod primar se folosete pentru obiecte care nu sunt vizuale, dar care pot conine obiecte vizuale ca membrii. Data O colecie de medii de date cursori i relaii pentru a putea fi deschise i nchise ca o unitate. EditBox O regiune de editare echivalent cu FoxPro 2.6. Form Un singur "screen", format pentru introducerea de date. Este obiect container care poate conine i alte obiecte n el. FormSet Un obiect tip container care are ca membrii mai multe formulare (forms). Grid Un obiect de tip container care permite afiarea i editarea informaiilor n formatul tabel. Header Antetul unei coloane a unui tabel. Hyperlink Object Furnizeaz butoane, imagini sau etichete care la un click pot lansa pagini WEB. Image O imagine. Label O etichet a unui obiect. Line O linie desenat. ListBox O list derulant. OleControl Un control bazat pe un obiect OLE. OptionButton Un singur obiect radio-tip obiect. OptionGroup Mai multe butoane radio care opereaz ca un singur control. Este echivalentul unui obiect radio button din FoxPro 2.x. Page O singur pagin din cadrul unui
13

Nume Clas PageFrame

ProjectHook

Relation Separator Shape Spinner TextBox Timer

ToolBar

Descriere formular pagin. Un control de tip pagin. Fiecare pagin din cadrul unui control de tip pagin este o pagin separat. Formularul pagin este un control tip container deoarece el poate conine mai multe obiecte. Creeaz instane ale proiectului deschis care permit acces la nivel program ctre evenimentele proiectului. O definiie a unei relaii ntre dou cursoare ntr-un mediu de date. Obiect care pune spaii albe ntre controale pe un toolbar. O form (un cerc sau un dreptunghi). Echivalentul unui spinner control din FoxPro 2.x. Echivalentul unui GET control din FoxPro 2.x. Un obiect vizual care nu apare pe form. Acest control este proiectat pentru a permite aciuni la intervale de timp fixe. O bar de instrumente, care este un grup de obiecte care pot fi lipite n partea de sus, jos, sau lateral ecranului. Cnd nu este lipit, o bar de instrumente arat asemntor unei forme.

Clase Clasele pot fi caracterizate n dou tipuri i anume clase vizuale i clase nonvizuale. Clase Vizuale
14

O clas vizual este o clas proiectat pentru scopul de a putea fi afiat. De exemplu, un formular este o clas vizual. Principalul scop al claselor vizuale este ns crearea interfeei (deseori numit i GUI - Graphical User Interface sau interfaa grafic a utilizatorului). n aceast categorie de clase se pot proiecta clase n urmtoarele subcategorii: controale singure combinaii de controale containere formulare toolbar-uri. Butonul de comand OK este un bun exemplu de control singular, care la execuia unui click prsete formularul. Pentru a realiza acest lucru se creaz o clas de tipul CommandButton n care se definesc cteva proprieti ale butonului OK i bineneles evnimentul Click cu ajutorul cruia prsete formularul. *-- Class: butonok *-- ParentClass: CommandButton *-- BaseClass: CommandButton * DEFINE CLASS butonok AS CommandButton AutoSize = .F. Height = 29 Width = 41 Caption = "OK" Default = .T. Name = "butonok" PROCEDURE Click
15

RELEASE thisform ENDPROC ENDDEFINE Acest buton poate fi plasat n orice formular. Metoda utilizat de acest buton este RELEASE THISFORM n evenimentul Click al butonului. n figura nr.1 putei vedea un buton OK creat cu ajutorul codului de program anterior.

Fig.1 Un formular cu un buton care prsete formularul Subclasa unei clase a unui control singular Tehnic, toate clasele din Visual FoxPro sunt subclase ale unor clase de baz. S presupunem c dorim o versiune a butonului creat mai sus, dar cu un text ajuttor (tooltip text care apare dac lsai mouse-ul puin timp deasupra controlului respectiv). *-- Class: butonokcuajutor *-- ParentClass: butonok *-- BaseClass: CommandButton *-- Subclas a butonOK adaug un ajutor (ToolTip) . DEFINE CLASS butonokcuajutor AS okbutton
16

Height = 29 Width = 41 ToolTipText = "Prsete formularul" Name = "butonokcuajutor" ENDDEFINE Observai c evenimentul Click de data aceasta nu este prezent, deoarece este motenit din clasa printe. Se adaug n plus la aceast subclas proprietatea ToolTipText. De ce subclas? Se apeleaz la subclase i nu se face direct modificarea n clasa printe, deoarece ar nsemna n caz contrar c orice modificare n clasa printe va fi motenit de toate subclasele sau instanele obiectului respectiv. O clas container - Navigator Un container de CommandButtons utilizat pentru navigarea ntr-o tabel dintr-un formular. Pentru a realiza un astfel de container de butoane de navigarese definete n prim fay clasa container n care se adaug instanele claselor butoanelor de navigare definite ulterior. Adugarea la clasa container se face cu ajutorul instruciunii ADD OBJECT. Prog. 1 Un Container - Bazat pe un set de butoane de navigare *-- Class: navigator *-- ParentClass: container *-- BaseClass: container DEFINE CLASS navigator AS container
17

Width = 350 Height = 32 BackStyle = 0 BorderWidth = 0 Name = "navigator" ADD OBJECT cmdUrmatoarea AS cmdUrmatoarea WITH ; Top = 0, ; Left = 0, ; Height = 31, ; Width = 60, ; Caption = "Urmatoarea", ; Name = "cmdUrmatoarea" ADD OBJECT cmdAnterioara AS cmdAnterioara WITH ; Top = 0, ; Left = 72, ; Height = 31, ; Width = 60, ; Caption = "Anterioara", ; Name = "cmdAnterioara" ADD OBJECT cmdPrima AS cmdPrima WITH ; Top = 0, ; Left = 144, ; Height = 31, ; Width = 60, ; Caption = "Prima", ; Name = "cmdPrima"
18

ADD OBJECT cmdUltima AS cmdUltima WITH ; Top = 0, ; Left = 216, ; Height = 31, ; Width = 60, ; Caption = "Ultima", ; Name = "cmdUltima" ADD OBJECT cmdok AS butonokcuajutor WITH ; Top = 0, ; Left = 288, ; Height = 31, ; Width = 60, ; Name = "cmdOK" ENDDEFINE DEFINE cmdUrmatoarea AS CommandButton PROCEDURE Click SKIP 1 IF EOF() =Messagebox("Sfrit de fiier!", 16) GO BOTTOM ENDIF thisform.refresh() ENDPROC ENDDEFINE DEFINE CLASS cmdAnterioara AS CommandButton
19

PROCEDURE Click SKIP -1 IF BOF() =Messagebox("nceput de fiier!", 16) GO TOP ENDIF thisform.refresh() ENDPROC ENDDEFINE DEFINE CLASS cmdPrima AS CommandButton PROCEDURE Click GO TOP thisform.refresh() ENDPROC ENDDEFINE DEFINE CLASS cmdUltima AS CommandButton PROCEDURE Click GO BOTTOM thisform.refresh() ENDPROC ENDDEFINE DEFINE CLASS butonokcuajutor AS okbutton Height = 29 Width = 41 ToolTipText = "Prsete formularul" Name = "butonokcuajutor"
20

ENDDEFINE

Fig. 2 Formular cu butoane de navigare Pornind de la programul anterior n care am definit o clas container de butoane de navigare, vom realiza un alt program, care va avea n plus fa de cel anterior un buton Nou (acesta va crea o nou nregistrare n tabelul test.dbf). Se creaz clasa container care va conine pe lng butoanele de navigare i 2 casete text legate cu ajutorul proprietii ControlSource la tabelul test care se consider c este deja adugat la mediul de date al formularului. Aceste 2 casete text vor fi legate la 2 cmpuri ale tabelului test i anume cnume i ctip. *-- Form: form1 *-- ParentClass: form *-- BaseClass: form DEFINE CLASS form1 AS form Top = 0 Left = 0 Height = 182 Width = 463
21

DoCreate = .T. BackColor = RGB(192,192,192) BorderStyle = 2 Caption = "Form1" Name = "Form1" ADD OBJECT text1 AS textbox WITH ; BackColor = RGB(192,192,192), ; ControlSource = "test.cnume", ; Height = 24, ; Left = 48, ; Top = 24, ; Width = 113, ; Name = "Text1" ADD OBJECT text2 AS textbox WITH ; BackColor = RGB(192,192,192), ; ControlSource = "test.ctip", ; Height = 24, ; Left = 48, ; Top = 60, ; Width = 113, ; Name = "Text2" ADD OBJECT navigator1 AS navigator WITH ; Top = 120, ; Left = 12, ; Width = 421, ; Height = 32, ; Name = "Navigator1", ;
22

cmdUrmatoarea.Name = "cmdUrmatoarea", ; cmdAnterioara.Name = "cmdAnterioara", ; cmdPrima.Name = "cmdPrima", ; cmdUltima.Name = "cmdUltima", ; cmdOK.Top = 0, ; cmdOK.Left = 360, ; cmdOK.Height = 31, ; cmdOK.Width = 61, ; cmdOK.Name = "cmdOK" ADD OBJECT form1.navigator1.cmdNou AS commandbutton WITH ; Top = 0, ; Left = 288, ; Height = 31, ; Width = 61, ; Caption = "Nou", ; Name = "cmdNou" PROCEDURE cmdNou.Click APPEND BLANK thisform.refresh() ENDPROC ENDDEFINE Adugarea butonului Nou la container se face cu ajutorul comenzii ADD OBJECT sau al metodei AddObject()

23

Fig.3 Formular cu casete de text Formularul n programarea structurat pentru a lansa un formular se folosete comanda DO FORM nume, n schimb n programarea orientat obiect se creaz o instan a obiectului printe cu ajutorul metodei CreateObject(), iar apoi se apeleaz metoda Show() a obiectului respectiv, metod care l va afia.. TIP n Visual FoxPro 6, putei utiliza funcia NewObject() pentru a crea obiecte din clase. oForm = CreateObject("Form") oForm.Show(1) sau oForm = NewObject("Form") oForm.Show(1) Citirea evenimentelor sistemului SET CLASS TO junkme
24

oForm = CreateObject("Form") oForm.Show() n programul anterior se creeaz un formular pe baza unei instanieri a clasei de baz Form, apoi se apeleaz metoda Show(). Problema se pune n felul urmtor: la apelarea metodei Show() formularul va aprea i apoi va disprea de pe ecran. De aceea este necesar s se transmit cumva sistemului s citeasc din nou evenimentele. Acest lucru se poate realiza cu ajutorul comenzii READ EVENTS. Prog.2 Un buton de comand care lanseaz un formular *-- Class: lansarea n execuie a unui formular *-- ParentClass: CommandButton *-- BaseClass: CommandButton DEFINE CLASS lansareformular AS CommandButton Height = 29 Width = 94 Caption = "LansareFormular" oform = .NULL. Name = " LansareFormular " PROCEDURE Click this.oForm = CreateObject("Form") this.oForm.Show() ENDPROC ENDDEFINE Mediul de date sau Data Environment Una dintre cele mai mari diferene dintre crearea formularului .SCX i crearea unei clase de tip formular se afl n zona mediului de date. Folosirea mediului de
25

date se face pentru a specifica ce tabele, vederi sau relaii sunt utilizate n formular. La crearea unui formular nu se poate salva mediul de date mpreun cu el, dac se salveaz un formular ca o clas care are un mediu de date ataat, mediul de date este pierdut. De aceea se creeaz acest mediu de date cu ajutorul codului de program. De obicei plasarea codului de program referitor la deschiderea mediului de date se face n evenimentul Load, sau ntr-o procedur numit Load. Astfel se creaz clasa container (formularul) care va conine casetele de text, legate la tabela Client cu ajutorul proprietii ControlSource, i bineneles etichetele corespunztoare fiecrei casete de text. n evenimentul Load al formularului deschidem baza de date test specificnd calea unde se afl memorat n calculator, iar apoi deschidem tabela Client. Prog.3 Un formular care deschide o tabel de date pentru editare *-- Class: formularcudateclient *-- ParentClass: form *-- BaseClass: form DEFINE CLASS formularcudateclient AS form DataSession = 2 Height = 238 Width = 356 DoCreate = .T. AutoCenter = .T. BackColor = RGB(192,192,192) Caption = "Exemplu de Date Client" Name = "formularcudate" ADD OBJECT txtcodcl AS TextBox WITH ;
26

ControlSource = "client.codcl", ; Enabled = .F., ; Height = 24, ; Left = 120, ; Top = 24, ; Width = 205, ; Name = "txtCodcl" ADD OBJECT txtcompanie AS TextBox WITH ; ControlSource = "client.companie", ; Height = 24, ; Left = 120, ; Top = 72, ; Width = 205, ; Name = "txtCompanie" ADD OBJECT txtcontact AS TextBox WITH ; ControlSource = "client.contact", ; Height = 24, ; Left = 120, ; Top = 120, ; Width = 205, ; Name = "txtContact" ADD OBJECT txttitlu AS TextBox WITH ; ControlSource = "client.titlu", ; Height = 24, ; Left = 120, ; Top = 168, ; Width = 205, ;
27

Name = "txtTitlu" ADD OBJECT label1 AS label WITH ; AutoSize = .T., ; BackStyle = 0, ; Caption = "Cod Client:", ; Height = 18, ; Left = 12, ; Top = 24, ; Width = 80, ; Name = "Label1" ADD OBJECT label2 AS label WITH ; AutoSize = .T., ; BackStyle = 0, ; Caption = "Companie:", ; Height = 18, ; Left = 12, ; Top = 72, ; Width = 64, ; Name = "Label2" ADD OBJECT label3 AS label WITH ; AutoSize = .T., ; BackStyle = 0, ; Caption = "Contact:", ; Height = 18, ; Left = 12, ; Top = 120, ; Width = 52, ;
28

Name = "Label3" ADD OBJECT label4 AS label WITH ; AutoSize = .T., ; BackStyle = 0, ; Caption = "Titlu:", ; Height = 18, ; Left = 12, ; Top = 168, ; Width = 32, ; Name = "Label4" PROCEDURE Load OPEN DATA _SAMPLES+" \test.dbc" USE client ENDPROC ENDDEFINE TIP Visual FoxPro 6 are o nou variabil de sistem numit _SAMPLES. Aceasta reine calea unde sunt memorate exemplele de coduri de program din directorul printe Visual Studio 6, aceste exemple toate fiind memorate n acelai director.

29

Fig. 4 Formular cu casete de text legat la un tabel Prog. 4 Formularul de date precedent cu butoanele de navigare adugate *-- Class: formularcudateclientcunavigator *-- ParentClass: formularcudateclient *-- BaseClass: form DEFINE CLASS formularcudateclientcunavigator formularcudateclient AS

Height = 283 Width = 370 DoCreate = .T. Name = " formularcudateclientcunavigator " txtCodcl.Name = "txtCodcl" txtCompanie.Name = "txtCompanie" txtContact.Name = "txtContact" txtTitlu.Name = "txtTitlu" Label1.Name = "Label1" Label2.Name = "Label2" Label3.Name = "Label3"
30

Label4.Name = "Label4" ADD OBJECT navigator1 AS navigator WITH ; Top = 240, ; Left = 12, ; Width = 350, ; Height = 32, ; Name = "Navigator1", ; cmdUrmatoarea.Name = "cmdUrmatoarea", ; cmdAnterioara.Name = "cmdAnterioara", ; cmdPrima.Name = "cmdPrima", ; cmdUltima.Name = "cmdUltima", ; cmdOK.Name = "cmdOK" ENDDEFINE Construirea formularelor cu ajutorul claselor sau utilizarea Proiectantului de Formulare? Utilizarea proiectantului de formulare versus formularele create sub forma claselor este o ntrebare la care se rspunde greu. Ambele metode merg bine n aplicaii. Mixarea i schimbarea diferitelor feluri de abordare nu face dect s ngreuneze meninerea aplicaiilor respective peste timp. Proiectantul de Formulare poate fi folosit pentru crearea de seturi de formulare, care conin mai mult de un formular. Astfel se poate controla care dintre formulare este vizibil la un moment dat. Clasele mediului de date (data environment) La crearea unui formular cu Proiectantul de formulare din Visual FoxPro, trebuiesc specificate tabelele cu care lucreaz
31

formularul respectiv prin crearea unui mediu de date pentru formular. Dup cum apare i n figura urmtoare un mediu de date este alctuit din cursori i relaii. V putei gndi la un mediu de date ca la un pachet (de fapt un container), care conine informaiile necesare pentru configurarea mediului de date.

Fig. 5 Mediul de date al unui formular Exist o limitare a mediului de date, cursorii i clasele nu pot fi create vizual, ci pot fi create numai prin cod de program. Clasa Cursor Clasa Cursor definete coninutul zonei de lucru, se vor detalia proprietile, evenimentele i metodele acestei clase.
32

Proprietile Clasei Cursor Proprieti Alias Descriere Configureaz aliasul zonei de lucru cnd se deschide BufferModeOverride Specific modul de buffering pentru cursor: 0 Nimic (fr buffering) 1 Este configurat la nivel de formular 2 Pessimistic row buffering 3 Optimistic row buffering 4 Pessimistic table buffering 5 Optimistic table buffering dac clasa mediului de date nu este utilizat ntrun formular se folosete orice valoare n afar de 1. CursorSource Specific sursa pentru datele cursorului. Poate fi o tabel, o baz de date, o vedere sau o tabel liber. Database Specific baza de date care conine sursa cursorului, trebuie menionat calea complet. Exclusive Specific dac sursa cursorului este deschis n mod exclusiv i accept valori logice. Filter Specific irul de caractere dup care se face filtrarea NoDataOnLoad Dac aceast proprietate este setat pe .T., deschide cursorul i creaz structura, dar nici o dat nu va fi descrcat n cursor. Acest lucru se va realiza cu ajutorul lui Requery(). Order Specific ordinea de afiare a datelor. Trebuie
33

ReadOnly

specificat un tag de index. Dac aceast proprietate este setat pe .T., atunci datele nu vor putea fi modificate. Cursor suport numai

Evenimente i Metode: Clasa evenimentele Init, Destroy i Error. Clasa Relaii

Clasa Relaii specific informaiile necesare pentru a configura o relaiile ntre doi cursori dintr-un mediu de date. Proprieti SELECT Factura SET ORDER TO cCodCl SELECT Client SET RELATION TO cCodCl INTO Factura Proprietile Clasei Relaii Proprieti ChildAlias ChildOrder OneToMany ParentAlias RelationalExpr Descrierea Aliasul tabelei copil. Ex. Factura. Specific ordinea din tabelul copil. Ex. cCodCl. Specific dac este relaie una-la-mai-multe. Aliasul tabelei printe. Ex. Client Expresia dup care se face relaia. Ex. cCodCl. relaie suport numai

Evenimente i Metode Clasa evenimentele Init, Destroy i Error.

Clasa Mediu de date (DataEnvironment)


34

Clasa DataEnvironment este un container pentru cursori i relaii, care luate mpreun formeaz un mediu de date. Proprietile Clasei DataEnvironment Proprieti AutoCloseTables Descrierea Specific dac tabelele ar trebui nchise automat n cazul n care obiectul este prsit. AutoOpenTables Specific dac tabelele ar trebui deschise automat n cazul n care obiectul este instaniat. InitialSelectedAlias Specific care alias ar trebui selectat iniial. Metode Adiionale ale Clasei DataEnvironment Metod Descrierea CloseTables() Aceast metod nchide toate tabelele i cursorii din clasa mediului de date. OpenTables() Aceast metod deschide toate tabelele i cursorii din clasa mediului de date. Evenimentele Clasei DataEnvironment Eveniment Descrierea BeforeOpenTables() Acest eveniment se execut nainte ca tabelele s fie deschise AfterCloseTables() Acest eveniment se execut dup ce tabelele sunt nchise. Prog. 5 Un exemplu de clas Data Environment DEFINE CLASS client AS cursor alias = "CLIENT" cursorsource = "CLIENT" database = HOME()+"TEST.DBC"
35

ENDDEFINE DEFINE CLASS comenzi AS cursor alias = "COMENZI" cursorsource = "COMENZI" database = HOME()+"TESTDATA.DBC" ENDDEFINE DEFINE CLASS articolcomand AS cursor alias = "ARTICOLCOMAND" cursorsource = "ARTICOLCOMAND" database = HOME()+"tESTDATA.DBC" ENDDEFINE DEFINE CLASS Client_La_Comenzi AS relation childalias = "Comenzi" parentalias = "Client" childorder = "cCodCl" RelationalExpr = "cCodCl" ENDDEFINE DEFINE CLASS Comenzi_La_ArticolComand AS relation childalias = "ArticolComand" parentalias = "Comenzi" childorder = "cCodComanda" RelationalExpr = "cCodComanda" ENDDEFINE DEFINE CLASS DE AS DataEnvironment
36

ADD OBJECT oClient AS Client ADD OBJECT oComenzi AS Comenzi ADD OBJECT oArticolComand AS ArticolComand ADD OBJECT o Client_La_Comenzi AS Client_La_Comenzi ADD OBJECT o Comenzi_La_ArticolComand AS Comenzi_La_ArticolComand PROCEDURE Init this.OpenTables() ENDPROC PROCEDURE Destroy this.CloseTables() ENDPROC ENDDEFINE Evenimentul Init apeleaz metoda OpenTables n aa fel nct toate tabelele sunt automat deschise cnd obiectul este instaniat i metoda CloseTables() este apelat cnd obiectul este prsit. Recuperarea definiiilor din DBC ar putea fi o problem, mai ales dac n timpul dezvoltrii aplicaiei mai facei i ceva schimbri n DBC. n acest caz trebuie imediat actualizat i mediul de date. Acest aspect se poate realiza relativ simplu cu ajutorul funciilor de tipul ADBObjects, astfel nct s v generai programul automat din DBC. Clasa: DUMPDBC DumpDbc este o subclas a clasei Custom.
37

Proprietile subclasei DumpDbc Proprieti PROTECTED aRelations PROTECTED aTables PROTECTED aViews CDBCName CPRGName PROTECTED cPath PROTECTED nRelations PROTECTED nTables PROTECTED nViews Descrierea Este o list de obiecte relaie din fiierul DBC. Este o list de obiecte tabel din fiierul DBC. Este o list de obiecte vedere din fiierul DBC. Este numele fiierului DBC care se export. Este numele programului PRG care se creeaz. Este calea complet unde se afl baza de date. Este numrul de obiecte relaie din fiierul DBC. Este numrul de obiecte tabel din fiierul DBC. Este numrul de obiecte vedere din fiierul DBC.

Evenimente i Metode Metoda Executa Aceast metod iniiaz scrierea programului, fiind singura metod public. De fapt ea verific dac s-au completat proprietile cDBCName i cPRGName, n caz contrar apare o caset de dialog de tipul Getfile() sau Putfile(). Metoda clasecursor Aceast metod PROTECTED merge prin toate tabele i vederile bazei de date i genereaz clasele cursor pentru ele, apelnd metoda WriteCursorClass. Metoda citestedbc Aceast metod PROTECTED citete definiiile relaiilor, tabelelor i vederilor DBC utiliznd ADBObjects i le plaseaz n aRelations, aTables i aViews ca membrii ai unui tabel.

38

Metoda claserelatie Aceast metod PROTECTED genereaz toate clasele relaie pentru fiierul DBC i le scrie n fiierul program de ieire. Metoda scrieclase() Aceast metod PROTECTED lanseaz procesul de scriere al tuturor claselor. Este apelat de metoda Executa dup ce metoda CitesteDbc i termin treaba. Metoda Scrieclase apeleaz metodele ClaseCursor i ClaseRelatie pentru a scrie clasele individuale n fiierul de ieire. Un ultim lucru pe care l face aceast metod este s apeleze metoda ScrieClaseImplicite, care scrie o clas mediu de date implicit care are toi cursorii i relaiile n ea. Metoda scrieclasecursor (tcClassName) Metoda PROTECTED scrie o singur clas cursor n program, avnd acelai nume cu cel al vederii sau cursorului. Metoda scrieclaseimplicite PROTECTED scrie o clas mediu de date implicit numit Default_de, care are toate clasele cursor i relaii din fiierul DBC. Prog. 6 Cod pentru crearea clasei DumpDBC i creaz i un program de ieire *-- Class: dumpdbc *-- ParentClass: custom *-- BaseClass: custom *-- Creaz clase CURSOR i clase RELATION pentru un .DBC. DEFINE CLASS dumpdbc AS custom *-- Numrul de obiecte relaie din .DBC
39

PROTECTED nrelations nrelations = 0 *-- Numrul de obiecte tabel din .DBC PROTECTED ntables ntables = 0 *-- Numrul de obiecte vedere din .DBC PROTECTED nviews nviews = 0 *-- Numele .DBC cdbcname = "" *-- Numele fiierului program care va fi creat cprgname = "" Name = "dumpdbc" *-- Calea unde se afl baza de date PROTECTED cpath *-- Lista obiectelor relaie din .DBC PROTECTED arelations[1] *-- Lista obiectelor vedere din .DBC PROTECTED aviews[1] *-- Lista obiectelor tabel din .DBC PROTECTED atables[1] PROTECTED init *-- Citete .DBC-ul ntr-un array (tablou) . PROTECTED PROCEDURE citestedbc IF !dbused(this.cDbcName) OPEN DATABASE (this.cDbcName) ENDIF *-- Citete .DBC
40

this.nTables "Table") this.nViews "View") this.nRelations "Relation") ENDPROC

= aDBObjects(this.aTables, = aDBObjects(this.aViews, = aDBObjects(this.aRelations,

*-- Scrie toate clasele. PROTECTED PROCEDURE scrieclase SET TEXTMERGE TO (this.cPRGNAME) NOSHOW IF this.nTables > 0 OR this.nViews > 0 this.ClaseCursor() ENDIF IF this.nRelations > 0 this.ClaseRelatie() ENDIF this.ScrieClaseImplicite() SET TEXTMERGE OFF SET TEXTMERGE TO ENDPROC *-- Proceseaz toate clasele cursor n .DBC. PROTECTED PROCEDURE ClaseCursor LOCAL lnCounter SET TEXTMERGE ON FOR lnCounter = 1 TO this.nTables this.ScrieClaseCursor(this.aTables[lnCounter]) ENDFOR FOR lnCounter = 1 TO this.nViews
41

this.ScrieClaseCursor(this.aViews[lnCounter]) ENDFOR SET TEXTMERGE OFF ENDPROC *-- Scrie o clas cursor n fiierul program de ieire. PROTECTED PROCEDURE scrieclasecursor LPARAMETERS tcClassName \DEFINE CLASS <<STRTRAN(tcClassName, chr(32), "_")>> AS cursor \ alias = "<<tcClassName>>" \ cursorsource = "<<tcClassName>>" \ database = DATABASEPATH + "<<this.cDbcName>>" \ENDDEFINE \ ENDPROC *-- Proceseaz i scrie toate clasele relaie. PROTECTED PROCEDURE claserelatie LOCAL lnCounter, ; lcClassName, ; lcChildAlias, ; lcParentAlias, ; lcChildOrder, ; lcRelationalExpr SET TEXTMERGE ON FOR lnCounter = 1 TO this.nRelations
42

lcClassName = "RELATION"Alltrim(Str(lnCounter)) lcChildAlias = this.aRelations[lnCounter,1] lcParentAlias = this.aRelations[lnCounter,2] lcChildOrder = this.aRelations[lnCounter,3] lcRelationalExpr = this.aRelations[lnCounter,4] \DEFINE CLASS <<lcClassName>> AS relation \ childalias = "<<lcChildAlias>>" \ parentalias = "<<lcParentAlias>>" \ childorder = "<<lcChildOrder>>" \ RelationalExpr = "<<lcRelationalExpr>>" \ENDDEFINE \ ENDFOR SET TEXTMERGE OFF ENDPROC *-- Scrie clasa mediului de date implicit (Data Environment) n program PROTECTED PROCEDURE scrieclaseimplicite LOCAL laClasses[this.nTables + this.nViews + this.nRelations] FOR lnCounter = 1 TO this.nTables laClasses[lnCounter] = this.aTables[lnCounter] ENDFOR
43

FOR lnCounter = 1 TO this.nViews laClasses[lnCounter+this.nTables] = this.aViews[lnCounter] ENDFOR FOR lnCounter = 1 TO this.nRelations laClasses[lnCounter+this.nTables+this.nViews] =; "Relation" + ALLTRIM(STR(lnCounter)) ENDFOR SET TEXTMERGE ON \DEFINE CLASS de_implicit AS DataEnvironment FOR lnCounter = 1 TO ALEN(laClasses,1) lcObjectName = 'o'+laClasses[lnCounter] lcClassName = laClasses[lnCounter] \ ADD OBJECT <<lcObjectName>> AS <<lcClassName>> ENDFOR \ENDDEFINE \ SET TEXTMERGE OFF ENDPROC PROCEDURE executa *-- Dac nici un nume dbc nu este specificat, ntreab de unul. IF EMPTY(this.cDBCName)
44

this.cDBCName = GETFILE("DBC", "Selectati va rugam DBC pentru clasa dump:") IF !FILE(this.cDBCName) =MESSAGEBOX("Nu este selectat nici un DBC! Anulam!",16) RETURN .F. ENDIF ENDIF *-- Acelai lucru i cu .PRG IF EMPTY(this.cPRGName) this.cPRGName = PUTFILE("PRG pentru a fi creat:","","PRG") IF EMPTY(this.cPRGName) =Messagebox("Operatie anulata!", 16) RETURN ENDIF ENDIF IF SET("safety") = "ON" AND ; FILE(this.cPRGName) AND ; MessageBox("Rescriere existenta " + ; ALLTRIM(this.cPRGName) + "?", 36) #6 =Messagebox("Operatie anulata!", 16) RETURN ENDIF *-- salveaz configurrile SAFETY
45

LOCAL lcOldSafety lcOldSafety = SET("safety") SET SAFETY OFF this.citestedbc() this.scrieclases() SET SAFETY &lcOldSafety ENDPROC ENDDEFINE Prog. 7 Program care ilustreaz utilizarea clasei Dumpdbc Set ClassLib to Chap17 Set ClassLib to FoxTool ADDITIVE oDbcGen = CREATEOBJECT("dumpdbc") oDbcGen.cDBCName = "testdata" oDbcGen.cPRGName = "deleteme.prg" oDbcGen.xecuta() Prog. 8 Programul de ieire DELETEME.PRG * Program...........: deleteme.prg * DBC...............: TESTDATA.DBC * Generated.........: August 28, 1998 - 10:16:23 #DEFINE databasepath HOME()+"\TEST\" DEFINE CLASS CLIENT AS cursor alias = "CLIENT" cursorsource = "CLIENT"
46

database "TESTDATA.DBC" ENDDEFINE

DATABASEPATH

DEFINE CLASS PRODUSE AS cursor alias = "PRODUSE" cursorsource = "PRODUSE" database = DATABASEPATH "TESTDATA.DBC" ENDDEFINE DEFINE CLASS ARTICOLCOMAND AS cursor alias = "ARTICOLCOMAND" cursorsource = "ARTICOLCOMAND" database = DATABASEPATH "TESTDATA.DBC" ENDDEFINE DEFINE CLASS COMENZI AS cursor alias = "COMENZI" cursorsource = "COMENZI" database = DATABASEPATH "TESTDATA.DBC" ENDDEFINE DEFINE CLASS ANGAJATI AS cursor alias = "ANGAJATI" cursorsource = "ANGAJATI" database = DATABASEPATH "TESTDATA.DBC"
47

ENDDEFINE DEFINE CLASS RELATIE1 AS relation childalias = "COMENZI" parentalias = "CLIENTI" childorder = "CODCL" RelationalExpr = "CODCL" ENDDEFINE DEFINE CLASS RELATIE2 AS relation childalias = "COMENZI" parentalias = "ANGAJATI" childorder = "CODANG" RelationalExpr = "CODANG" ENDDEFINE DEFINE CLASS RELATIE3 AS relation childalias = "ARTICOLCOMAND" parentalias = "COMENZI" childorder = "CODCOMANDA" RelationalExpr = "CODCOMANDA" ENDDEFINE DEFINE CLASS RELATIE4 AS relation childalias = "ARTICOLCOMAND" parentalias = "PRODUSE" childorder = "CODPRODUS" RelationalExpr = "CODPRODUS" ENDDEFINE
48

DEFINE CLASS de_implicit AS DataEnvironment ADD OBJECT oClient AS Client ADD OBJECT oProduse AS Produse ADD OBJECT oArticolcomand AS Articolcomand ADD OBJECT oComenzi AS Comenzi ADD OBJECT oAngajati AS Angajati ADD OBJECT oRelatie1 AS Relatie1 ADD OBJECT oRelatie2 AS Relatie2 ADD OBJECT oRelatie3 AS Relatie3 ADD OBJECT oRelatie4 AS Relatie4 ENDDEFINE Mai este necesar s apelai metoda OpenTables() pentru a avea tabelele deschise i deasemenea s apelai metoda CloseTables() pentru a nchide tabelele. DEFINE CLASS DE2 AS DataEnvironment PROCEDURE Init this.OpenTables() ENDPROC PROCEDURE Destroy this.CloseTables() ENDPROC ENDDEFINE Creterea puterii mediului de date cu ajutorul sesiunilor de date (DataSessions) Putei s realizai aplicaii mult mai flexibile, lucrnd cu mai multe sesiuni de date. Acest lucru se ntmpl pentru a nu mai deschide toate fiierelor la nceput, ci numai funcie de sesiunea de
49

date corespunztoare. De asemena, numai formularele pot crea sesiuni de date independente. Clasa care este creat ulterior nu se va putea aduga la un formular cu ajutorul lui ADD OBJECT sau AddObject(), ci va trebui s fie instaniat un obiect de acest tip cu ajutorul lui CreateObject(). Prog. 9 Codul pentru clasa Sesiunededatenoua *-- Class: Sesiunededatenoua *-- ParentClass: form *-- BaseClass: form DEFINE CLASS sesiunededatenoua AS form DataSession = 2 Top = 0 Left = 0 Height = 35 Width = 162 DoCreate = .T. Caption = "Form" Visible = .F. Name = "sesiunededatenoua" PROTECTED show PROTECTED visible ENDDEFINE Clasa de mai sus a creat un formular care nu va pute a fi afiat, deoarece proprietatea Visible a fost configurat pe .F. i metoda SHOW a fost protejat de asemenea. Clasele nonvizuale sunt clasele care nu sunt proiectate n primul rnd pentru a fi afiate n vreun fel. De exemplu
50

CommandButton este o clas creat pentru a fi afiat ntr-un formular. Clasele nonvizuale n Visual FoxPro sunt tipic descendente ale claselor Custom i deseori nu conin componente care s poat fi afiate. Cu toate acestea o clas nonvizual poate avea componente vizuale ataate la ea. De asemenea, clasele vizuale pot fi baza pentru clasele nonvizuale.

51