Documente Academic
Documente Profesional
Documente Cultură
Metode evoluate de
programare
(Elemente de programare
vizuala utilizând Delphi)
Cuvânt înainte
2
programare C-Builder este, abstracţie făcând de limbajul din spate, identic cu mediul
vizual de programare Delphi. De aceea, va fi uşor pentru fanii împătimiţi ai C++ să
cocheteze cu C-Builder, după ce au descoperit strategia de lucru sub Delphi.
Dată fiind întinderea universului problematic al unui mediu vizual de programare
(Delphi sau C-Builder), o parte dintre aceste probleme vor fi, din fericire, abordate la
cursul opţional de Programare Windows.
*
Programarea în Pascal, din perspectivă DOS, reprezintă un prilej de afirmare a
unor principii foarte clare ale “modelului clasic de rezolvare a unei probleme” cu
ajutorul calculatorului:
3
impresionantă de funcţii, constante şi structuri de date care îi permit să creeze
aplicaţii conform standardelor Windows. Toate aceste facilităţi sunt grupate în
interfaţa de programare a aplicaţiilor (Win32API - Applicaţion Programming
Interface).
Cum am mai spus, mai multe detalii pe teme de programare Windows se pot afla
la cursul opţional de Programare Windows sau din nenumăratele surse de informare
care există în librării şi, din păcate, mai puţin în bibliotecile şcolilor noastre.
Firma Borland a oferit programatorilor şansa de a programa în spirit Windows
prin intermediul pachetului Borland Pascal for Windows al kitt-ului Borland Pascal
7.0. Evoluţia galopantă a paradigmelor în materie de comunicaţie electronică şi în
materie de gestiune a colecţiilor de date a scos la rampă mediile vizuale de
programare a sistemelor soft utilizator. Deşi pionier în această direcţie, Visual Basic
are o serie de neajunsuri pe care specialiştii de la Borland le-au sesizat şi le-au
rezolvat prin propunerea mediului Delphi de dezvoltare a aplicaţiilor utilizator şi nu
numai (a se vedea C-Builder sau J-Builder!).
Delphi este un mediu vizual de dezvoltare de aplicaţii cu adevărat orientate pe
obiecte şi modularizate, pornind de la platforma Windows. Prin aceasta Delphi devine
un instrument ideal pentru aplicarea în practică a paradigmei RAD (Rapid
Applications Development). Deşi nu este un mediu CASE (Computer Aided
Software Engineering), Delphi este o platformă care permite rezolvarea multor
probleme a căror soluţie se bazează pe prototipizare (=construirea unor versiuni sau
componente simplificate ale sistemului soft propus, care pot fi analizate înainte de a
se continua dezvoltarea).
4
Ce noutăţi oferă DELPHI ?
Orientarea pe obiecte
Limbaje precum Visual Basic sunt pseudo-obiect orientate, folosind obiecte şi
metode fără a oferi suport pentru încapsulare, moştenire şi polimorfism. Limbajul
Pascal Object, care stă la baza aplicaţiilor Delphi, este un limbaj cu adevărat obiect
orientat, care permite combinarea datelor şi a codului asociat pentru a defini clasele
(încapsulare), crearea de descendenţi ai acestor clase (moştenire) şi tratarea unei clase
descendente în relaţia cu o clasă părinte din perspectivă polimorfică.
Biblioteca de componente
Toate elemenetele cu ajutorul cărora sunt realizate, în mod uzual, interfeţele
aplicaţiilor Windows sunt standardizate şi puse la dispoziţia programatorilor ca şi
componente, păstrate în biblioteca de componente a sistemului. Dacă există
programatori care vor să modifice funcţionalitatea componentelor oferite de Delphi, o
pot face elegant, printr-o derivare adecvată, dar cu un efort de programare
considerabil mai mare decât în cazul simplei utilizări a componentelor.
5
Şabloane
Delphi recunoaşte patru tipuri de şabloane: forma, aplicaţia, componenta şi codul.
Şabloanele de tip formă, aplicaţie şi componentă permit reutilizarea colecţiilor de
obiecte în programe diferite sau ca bază pentru realizarea unui program nou.
Şabloanele de tip cod simplifică procesul de scriere a codului aferent unor enunţuri
Delphi standard.
Compilare adevărată
Multe medii de dezvoltare Windows generează executabile semi-compilate (p-
cod). Deoarece p-codul nu este executabil pe o maşină fizică, el trebuie translatat în
momentul execuţiei, ceea ce înseamnă o semnificativă penalizare a performanţei unui
program. Delphi produce cod executabil autentic care, în plus, nu pretinde
performanţe deosebite din partea mediului de execuţie gazdă. Totodată, filozofia
Delphi permite lucrul cu componente DLL, fapt ce are implicaţii asupra
performanţelor programului şi mediului de execuţie. Orientarea pe componente DLL
a aplicaţiilor realizate în spirit Windows creeaza, este drept, niste probleme de
portabilitate de la sisteme puternic configurate la sisteme mai modeste, atât din punct
de vedere hard cat si din punct de vedere al forţei sistemului de operare.
Aplicaţii robuste
Sunt cunoscute de la alte limbaje dificultăţile legate de tratarea de către
programator a excepţiilor care pot să apară în timpul execuţiei unui program. Delphi
rezolvă aceste probleme propunând enunţuri de limbaj adecvate pentru soluţionarea
lor. Aceste enunţuri nu fac altceva decât să transpună în sintaxă Object Pascal,
semantica cunoscută de la abordarea C++ pentru tratarea excepţiilor.
Aş mai adăuga incă un motiv important în alegerea mediului Delphi pentru a
face programare vizuală: uşurinţă a învăţării protocoalelor de dezvoltare asistată a
aplicaţiilor Delphi, comparativ cu alte medii (Visual Basic sau Visual C++).
6
2. Fundamentele limbajului Object Pascal
Deşi capabilităţile mediului Delphi permit realizarea unor aplicaţii utilizând,
esenţial, doar click-ul de mouse, adevăratele aplicaţii utilizator presupun, încă,
efort de programare pentru rezolvarea unor probleme specifice acestora. Limbajul
prin intermediul căruia se face inserţia de comportament specific în aplicaţiile
Delphi este limbajul Object Pascal. Schema de principiu după care un programator
combină capabilităţile Delphi de generare a codului cu activitatea de adăugare a
codului specific poate fi dedusă făcând o scurtă trecere în revistă a disciplinei Delhpi
de realizarea a unei aplicaţii.
object Form1:Tform1
Left =200
Top =110
Width =544
Height =375
Caption =’Form1’
Font.Charset =DEFAULT_CHARSET
Font.Color =clWindowText
Font.Height =-11
Font.Name =’MS Sans Serif’
Font.Style =[]
PixelsPerInch=96
7
TextHeight =13
end
Dacă doreşte, programatorul poate modifica unele dintre proprietăţile care apar în
vizualizarea de mai sus.
Revenirea de la reprezentarea de tip text la reprezentarea vizuală a unei forme se
poate face cu ajutorul comenzii View as Form (Alt+F12), accesibilă în meniul local
al reprezentării de tip text.
8
mai multe unit-uri. Legarea formelor, astfel încât acestea să formeze o aplicaţie este
realizată cu ajutorul conceptului de proiect.
Nu este interzis ca o formă să îşi implementeze funcţionalitatea cu ajutorul mai
multor unit-uri, dacă este necesar din punct de vedere al modularizării.
program Proiect1;
uses Forms,
Unit1 in “Unit1.pas’ {Form1}
{$R *.RES}
begin
Application.Initialize;
Application.CreateForm(Tform1,Form1);
Application.Run;
end.
9
Observaţie
În mod uzual, identificatorii de tip în Object Pascal pot fi utilizaţi doar în
contextul definirii unui nou tip sau în contextul unei declaraţii de variabile.
Există, totuşi, câteva rutine care folosesc identidicatorii de tip ca parte a unei
instrucţiuni executabile. De exemplu, SizeOf( T ) returnează numărul de octeţi
necesari pentru o instanţă de tip T.
Tipuri ordinale
Dintre tipurile de date simple, cele mai simple sunt tipurile ordinale. Tipurile
ordinale reprezintă informaţia prin elemente discrete. Relaţia între elementele discrete
şi modul în care acestea sunt reprezentate în memorie instituie o relaţie de ordine
naturală între elemente. De aici denumirea de ordinal.
Object Pascal are trei grupe predefinite de tipuri ordinale: întregi, caractere şi
valori booleene. Grupele de tipuri ordinale definite de utilizator sunt: enumerările şi
subdomeniile.
Valorile oricărui tip ordinal formează o secvenţă ordonată astfel încât valoarea
ordinală a oricărei valori de tip ordinal este determinată de poziţia valorii înăuntrul
secvenţei ordonate. Exceptând valorile de tip întreg, care pot fi atât pozitive cât şi
negative, primul element al unui tip ordinal are indexul de poziţie 0, al doilea are
indexul de poziţie 1 ş.a.m.d.. Indexul de poziţie al unei valori de tip întreg este chiar
valoarea.
În acest context, toate tipurile ordinale partajează anumite operaţii comune care
permit manipularea valorilor lor conform Tabelului 2.1.
Observaţie
Pentru toate tipurile ordinale, Object Pascal asigură un mecanism typecasting
pentru convertirea valorilor întregi în valoarea ordinală corespunzătoare, asftel:
“Dacă T este numele unui tip ordinal şi X este o expresie întreagă, atunci
T(X) returnează o valoare de tip T a cărui valoare ordinală este X.
10
expresiei ordinale X, relativ la tipul ordinal
gazdă.
Pred(X) Funcţie; returnează predecesorul valorii
expresiei X. Pentru expresii întregi returnează
X-1.
Succ(X) Funcţie; returnează succesorul valorii
expresiei X. Pentru expresii întregi returnează
X+1.
Dec(V) Procedură; decrementează variabila V; Efectul
ei este echivalent cu V:=Pred(V).
Inc(V) Procedură; incrementează variabila V; Efectul
ei este echivalent cu V:=Succ(V).
Tabelul 2.1 Proceduri şi funcţii relativ la tipurile ordinale
Tipuri întregi
Tipurile întregi reprezintă informaţia ca numere întregi. În Object Pascal tipurile
întregi predefinite se împart în tipuri fizice (fundamentale) şi tipuri logice
(generice). În mod uzual în aplicaţii sunt preferate tipurile logice deoarece acestea
sunt implementate astfel încât să asigure cele mai bune performanţe pe o maşină şi un
sistem de operare date. Tipurile întregi fizice sunt utile atunci când se doreşte un
control strâns asupra numărului de octeţi afectaţi întregilor cu care lucrează
programul. Distribuţia exactă pe cele două tipuri a varietăţilor de întregi o prezentăm
în Tabelul 2.2 şi Tabelul 2.3.
11
Operaţia Rezultatul
Abs(X) Returnează valoarea absolută a întregului din X
X Div Y Returnează câtul împărţirii întregului X la întregul Y
X Mod Y Returnează restul împărţirii întregului X la întregul Y
Odd(X) Returnează TRUE dacă X este impar şi FALSE dacă X este par
Sqr(X) Returnează pătratul lui X
Tabelul 2.4 Alte operaţii cu numere întregi
Tipuri caracter
Implementările pe calculatoarele compatibile IBM-PC ale limbajului Pascal au
folosit de la început pentru reprezentarea noţiunii de caracter codul ASCII (American
Standard Code for Information Interchange). Schema de codificare ASCII utilizează
efectiv şapte biţi ai unei locaţii de memorie pentru reprezentarea unui caracter. În
mod evident, bitul suplimentar dublează numărul de caractere care pot fi reprezentate
pe opt biţi. Actuala definiţie a sistemului Delphi utilizează o variantă extinsă a
codului ASCII numită Schema de codificare extinsă ANSI (American National
Standard Institute). Codul extins ANSI permite, pe diferite platforme de operare,
includerea de caractere suplimentare, utile în comunicarea cât mai completă cu
utilizatorii calculatoarelor. Pentru acoperirea tuturor cerinţelor de comunicare a
calculatoarelor cu utilizatorii, în contextul internaţionalizării comunicaţiei prin
Internet, a fost specificat codul pe 16 biţi UNICODE, în care primele 256 de intrări
corespund direct celor 256 caractere definite în codul ANSI. Pentru a facilita
utilizarea acestor tipuri de reprezentare a caracterelor, Object Pascal defineşte două
tipuri fizice de date de tip caracter şi un tip generic sau logic de dată de tip caracter.
Tipurile fizice sunt prezentate în Tabelul 2.5.
Tipul Caracteristici
AnsiChar Caractere orientate byte, ordonate conform setului de caractere extins
ANSI
WideChar Caractere orientate word, ordonate conform setului de caractere
UNICODE. Primele 256 caractere UNICODE corespund setului
extins de caractere ANSI.
Tabelul 2.5 Tipuri fizice de caractere utilizabile în Delhpi
Tipuri logice
12
Programatorii se lovesc de timpuriu de necesitatea de a lucra cu variabile cu două
stări. În Pascalul clasic tipul predefinit care răspunde unei astfel de cerinţe este tipul
boolean care poate lua una din valorile true sau false. În limbajul C valoarea
numerică o este asimilată cu false iar o valoare numerică nenulă este asimilată cu
true.
În Delphi există patru tipuri logice predefinite, prezentate în Tabelul 2.6.
Variabilele de tip Boolean pot lua numai valorile False sau True. Variabilele de
tip ByteBool, WordBool şi LongBool pot lua alte valori ordinale interpretate prin
convenţie ca False pentru 0 sau True pentru orice valoare nenulă.
Tipuri enumerate
În mod uzual, un tip enumerat este capabil să reprezinte valori discrete care au
nume. Tipul Boolean din Object Pascal este un exemplu de tip enumerat predefinit
astfel:
type Boolean=(False, True);
Cele mai multe tipuri enumerate sunt pur şi simplu liste de identificatori unici pe
care programatorul îi va utiliza în situaţii dedicate.
Sintaxa de declarae este:
Tipul enumerat este ordinal. Prin urmare, identificatorii din lista enumerată au
asociat un număr numit valoare ordinală asociată. Primul identificator are valoarea
ordinală 0, al doilea are valoarea ordinală 1 ş.a.m.d..
Tipuri subdomeniu
Un tip subdomeniu reprezintă informaţii care pot lua valori de un anumit ordin al
unui tip ordinal corespunzător, altul decât subdomeniu.
Sintaxa de declarare a tipului subdomeniu rămâne aceeaşi din Pascal:
type <Subdomeniu>=<Valoare_De_Început>..<Valoare_De_Sfârşit>;
Tipuri reale
Tipurile reale reprezintă informaţii numerice care pot avea atât parte întreagă cât
şi parte fracţionară. Object Pascal are şase specii de tipuri reale. Aceste tipuri se
13
deosebesc prin ordinul de mărime asociat şi precizia reprezentării corespunzătoare,
fapt ilustrat mai precis în Tabelul 2.7.
Numerele reale, în înţeles Object Pascal, nu sunt acelaşi lucru cu numerele reale
ca înţeles matematic. Un tip real Object Pascal este o submulţime strictă a lui R,ale
cărei elemente pot fi reprezentate în virgulă mobilă utilizând un registru cu număr
specific de biţi, conform standardului IEEE (Institute of Electrical and Electronic
Engineers). Într-o măsură mult mai mare decât numerele întregi, numerele reale
ridică probleme dintre cele mai neaşteptate celor care au aplicaţii în care precizia
reprezentării şi ordinul de mărime sunt esenţiale.
Unit-ul Delphi System pune la dispoziţia programatorilor o serie de rutine pentru
manipularea numerelor reale. Cele mai uzuale dintre ele sunt prezentate în Tabelul
2.8. Alte rutine de interes în acest scop sunt disponibile în unit-urile SysUtils şi Math.
Funcţia Ce returnează
Abs(x) Valoare absolută a lui x
ArcTan(x) Arctangenta lui x
Cos(x) Cosinusul argumentului x, considerat în radiani
Exp(x) Puterea x a numărului e
Frac(x) Partea fracţionară a lui x
Int(x) Partea întreagă a lui x. Atenţie! Int returnează o valoare de tip
real.
Ln(x) Logaritmul natural al numărului x
Pi Numărul π (3.1416…)
Round(x) Numărul întreg cel mai apropiat de x. Rezultatul returnat de
Round este de tip înreg. Formula “cel mai apropiat de x” devine
ambiguă când partea fracţionară este 0.5. Delphi lasă pe seama
sistemului să decidă cum efectuiază rotunjirea în această situaţie.
În mod uzual, cu procesor INTEL, recomandarea IEEE este de a
se rotunji la cel mai apropiat număr înreg par.
Sin(x) Sinusul trigonometric al argumentului x, considerat în radiani.
Sqr(x) Pătratul lui x. Adică x*x.
Sqrt(x) Rădăcina pătrată a lui x.
Trunc(x) Partea întreagă a lui x. Spre deosebire de Int, Trunc returnează o
valoare de tip întreg.
14
Tabelul 2.8 Funcţii pentru lucrul cu numere reale
Tipuri şir
În expresii, Delphi suportă trei specii de şiruri de caractere format fizic :
-scurt (ShortString);
-lung (AnsiString);
-mărit (WideString).
AnsiString, ShortString şi WideString pot fi utilizate combinat în atribuiri şi
expresii, Delphi executând automat conversiile necesare.
Atât tipul AnsiString cât şi tipul WideString păstrează caracterele în vectori
alocaţi dinamic, a căror lungime este plafonată doar de lungimea fizică a memoriei.
Diferenţa între aceste două tipuri constă în faptul că AnsiString păstrează caracterele
într-un arrray de caractere de tip char iar WideString păstrează caracterele într-un
array de caractere de tip WideChar. În mod uzual este utilizat tipul AnsiString, tipul
WideString fiind indispensabil dacă se realizează aplicaţii care utilizează setul de
caractere UNICODE.
Fizic, tipul ShortString este păstrat ca un array [0..255] of char. Prima poziţie în
şir păstrează lungime dinamică a şirului, care poate varia între 0 şi 255 caractere.
Caracterele efective ocupă poziţiile de la 1 până la 255. Tipul ShortString a fost
introdus din motive de compatibilitate cu Borland Pascal şi versiunile timpurii ale
mediului Delphi.
Tipul şir de caractere generic este cunoscut în Delphi ca string. Cu ajutorul
directivei de compilare {$H} putem stabili dacă string se referă la ShortString sau
AnsiString. Pentru {$H+}, care este starea implicită a directivei, string se referă la
un AnsiString.
Din motive de compatibilitate cu alte limbaje, Delphi suportă o clasă de şiruri de
caractere numite şiruri de caractere null-terminate. Nu există cuvinte rezervate sau
identificatori speciali pentru a indica folosirea şirurilor de caractere null-terminate.
Şirurile de caractere null-terminate se compun din caractere nenule urmate de
caracterul null (#0). Spre deosebire de tipurile Object Pascal AnsiString, ShortString
şi WideString, şirurile de caractere null-terminate nu au indicator de lungime separat.
Tabelul 2.9 prezintă câteva rutine utile în lucrul cu şiruri de caractere.
Funcţia Descrierea
Concat (S1, S2, S3) Returnează rezultatul concatenării şirurilor
S1, S2, S3.
Copy (S, Pos, Len) Returnează un subşir de lungime cel mult
Len caractere, care începe din poziţia Pos a
şirului de caractere S.
Delete (S, Pos, Len) Şterge cel mult Len caractere din şirul S,
începând cu poziţia Pos
Insert ( Sursa, Dest, Pos) Inserează şirul de caractere Sursa în variabila
şir Dest începând din poziţia Pos.
Length (S) Returnează lungimea dinamică a şirului S.
Similară funcţiei LEN din Basic sau funcţiei
15
strlen( ) din C/C++.
Pos (Subs,S) Returnează poziţia primei apariţii a
subşirului Subs în şirul S. Similară funcţiei
SUBSTR din Basic sau funcţiei strstr( ) din
C/C++.
SetLength(S, NewLen) Setează lungimea dinamică a variabilei şir S.
SetString Setează conţinutul unui şir de caractere.
Str (X, S) Converteşte expresia numerică X în şirul de
caractere S.
StringOfCharS Returnează un un şir de un număr dat de
caractere.
Val (S, V, Code) Converteşte şirul S la reprezentarea
numerică corespunzătoare.
Tabelul 2.9 Rutine sistem utile în lucrul cu şiruri de caractere
Tipul înregistrare
Cuvântul rezervat record permite gruparea diferitelor tipuri de date într-un singur
tip. Sintaxa generală a declaraţiei unui tip înregistrare este:
type
:
<Identificator_Tip_Record>=record
<Câmp_1>:<Tip_Câmp_1>;
<Câmp_2>:<Tip_Câmp_2>;
16
:
<Câmp_n>:<Tip_Câmp_n>;
[case <Selector_parte_variabilă> : <Tip_Selector> of
<Val_1_Selector>:<Parte_variabilă_1>;
<Val_2_Selector>:<Parte_variabilă_2>;
:
<Val_k_Selector>:<Parte_variabilă_k>;]
end;
sau:
type
:
<Identificator_Tip_Record>=record
<Câmp_1>:<Tip_Câmp_1>;
<Câmp_2>:<Tip_Câmp_2>;
:
<Câmp_n>:<Tip_Câmp_n>;
[case <Tip_Selector> of
<Val_1_Selector>:<Parte_variabilă_1>;
<Val_2_Selector>:<Parte_variabilă_2>;
:
<Val_k_Selector>:<Parte_variabilă_k>;]
end;
:
var
Inreg:<TInregistrare>;
:
…Inreg . <Nume_Câmp> …
:
var
Inreg:<TInregistrare>;
:
with Inreg do
17
:
…<Nume_Câmp>…
:
end;
Putem remarca faptul că tipul struct din C este echivalent cu tipul record fără
parte variabilă din Delphi. De asemenea, tipul union din C este echivalent cu tipul
record cu lungime variabilă din Delphi.
Tipul array
Structurile de tip array pot exista în variante unidimensionale sau
multidimensionale. Sintaxa generală pentru declararea unui tip array este
următoarea:
:
type
:
<TArray>=array [<Tip_ordinal_1>,<Tip_ordinal_2>,…,<Tip_ordinal_n>]
of <Tip_element>;
:
Deşi este utilizat în varianta trivială, în care tipurile ordinale după care se face
indexarea sunt subdomenii ale unor varietăţi de întregi, tipul array are şi posibilităţi
de indexare după alte tipuri ordinale, în funcţie de particularităţile problemei de
rezolvat.
Tipul mulţime
Cu ajutorul cuvântului rezervat set, se pot defini colecţii ordonate de cel mult 256
valori ordinale distincte. Sintaxe de declarare a tipului mulţime este:
:
type
:
<TSet>=set of <Tip_ordinal>;
:
:
var
:
<VSety: <TSet>;
:
18
Tipul fişier
Un tip file permite controlarea accesului la o secvenţă liniară de elemente care pot
fi de orice tip cu excepţia tipului file şi a tipului class. În Delphi, putem declara tipuri
de fişiere astfel:
:
type
:
<TFile>=file of <Tip_Record>;
sau
<TFile>=file ;
sau
<TFile>=textfile ;
:
Tipuri speciale
Tipul pointer
Un tip pointer este un tip de dată ale cărui valori sunt adrese către variabile ale
tipului de bază. Altfel spus, o variabilă de tip pointer poate conţine adresa din
memorie a unei variabile. Sintaxa de declarare a varietăţilor de pointeri din Delphi
este:
:
type
:
<Tip_Pointer_Structurat>= ^ <Tip_Definit_De_Utilizator>;
sau
<Tip_Pointer_Nedefinit>=pointer ;
:
Rutină Descriere
New Alocă memorie (din zona Heap a aplicaţiei) unei
variabile dinamice, prin intermediul unei variabile
pointer.
GetMem Alocă un block de memorie nedefinită (din zona
Heap a aplicaţiei) unei variabile dinamice, prin
19
intermediul unei variabile pointer.
@ Returnează adresa din memorie a unei variabile,
sau adresa punctului de intrare într-o procedură
sau funcţie.
Addr La fel ca la operatorul @
Assigned Verifică dacă o variabilă de tip procedural are
valoarea specială Nil.
Ptr Converteşte o adresă specificată prin <Segment>
şi <Ofsset) la o variabilă pointer.
Rolul special al constantei Nil, precum şi cerinţele care privesc utilizarea corectă
a tipului pointer sunt cunoscute de la programarea în Pascal.
Tipuri procedurale
Object Pascal permite tratarea procedurilor şi a funcţiilor ca entităţi care pot fi
atribuite variabilelor şi transmise ca parametri (fapt deosebit de benefic, cel puţin în
programarea generică). Astfel de acţiuni sunt posibile datorită tipurilor procedurale.
Sintaxa de definire a tipurilor procedurale este:
:
type
:
<Tip_Procedural>= procedure [(Lista_parametri_formali)]
[of object] [<Conventie_de_apel>];
sau
20
Exceptând convenţia cdecl, în toate celelalte eliminarea parametrilor din stivă este
realizată de procedurile sau funcţiile apelate. În cazul convenţiei cdecl, parametrii
sunt eliminaţi din stivă de apelant.
Convenţia de apel implicită este register.
Revenind, se poate observa că declararea tipurilor procedurale este asemănătoare
declarării antetelor procedurilor sau funcţiilor, cu deosebirea că lipseşte
identificatorul care urmează după cuvintele cheie procedure sau function la
definirea unui antet.
Analiza sintaxei de apel ne arată că există două categorii de tipuri procedurale:
Indicatori de procedură globală
Indicatori de metodă.
:
type
TProcedura = procedure;
TSirProc = procedure (const S:string);
TMathFunc = function (X:double):double;
:
Indicatori de metodă
Corespund unei declaraţii de tip în care este prezentă clauza of object. Un
indicator de metodă poate referi o metodă de tip procedură sau funcţie care aparţine
unui obiect. Indicatorul de metodă este specificat cu ajutorul a doi pointeri: in primul
se păstrează adresa metodei; în al doilea se păstrează referinţa la obiect.
Exemple:
:
type
TGenMetoda = procedure of object;
TNotifyEvent=procedure (Sender:TObject) of object;
:
21
În contextul valorilor procedurale, un identificator de procedură sau funcţie
globală desemnează o valoare a unui pointer la o procedură globală iar un designator
de metodă indică o valoare a unui indicator de metodă.
Exemple:
:
type
TMainForm=class(TForm)
procedure ButtonClick(Sender:TObject);
…
end;
var
MainForm:TMainForm;
MathFunc:TMathFunc;
Onclick :TNotifyEvent;
function Tan(Unghi:double):double;
begin
Result:=Sin(Unghi)/Cos(Unghi);
end;
:
:
MathFunc:=Tan;
OnClick:=MainForm.ButtonClick;
:
:
X:=MathFunc(X); {Echivalent cu X:=Tan(X)}
OnClick(Self);{Echivalent cu MainForm.ButtonClick(Self);
:
De semnalat faptul că, utilizarea unei variabile procedurale care are valoarea Nil
într-un apel determină o eroare de execuţie destul de neplăcută. Valoarea Nil este
utilizată pentru a indica faptul că o valoare procedurală este neatribuită, asfel că,
dacă există posibilitatea ca o variabilă procedurală să ia valoarea Nil, apelurile care
implică variabila trebuie să fie protejate de un test specific ca în exemplul:
22
Pentru a fi considerate compatibile, tipurile procedurale trebuie să aibă:
-aceeaşi convenţie de apel;
-acelaşi număr de parametri;
-parametri de acelaşi tip în poziţiile omoloage;
-În cazul funcţiilor, tipul returnat trebuie să fie identic.
Numele parametrilor nu are influenţă asupra compatibilităţii tipurilor procedurale.
Constanta Nil este compatibilă cu orice tip procedural.
Indicatorii de procedură globală şi indicatorii de metodă sunt întotdeauna mutual
incompatibili din punct de vedere al tipului.
Funcţiile şi procedurile standard, precum şi funcţiile şi procedurile imbricate nu
pot fi utilizate ca valori procedurale.
:
type
IntFunc=function:integer;
var
F:IntFunc;
N:integer;
function ReadInt:integer;far;
var
I:integer;
begin
read(I);
ReadInt:=I;
end;
begin
F:=ReadInt; {Atribuire de valoare procedurală}
N:=ReadInt; {Atribuire de rezultat apel funcţie }
end.
:
Compilatorul discerne tipul de atribuire după tipul variabilei din partea stângă a
instrucţiunii de atribuire. Din păcate există şi situaţii în care compilatorul nu poate
decide acţiunea pe care trebuie să o întreprindă din analiza contextului. Astfel, în
exemplul:
:
if F=ReadInt
then
Edit1.Text:=’Egalitate’;
:
23
compilatorul nu ştie dacă trebuie să compare valorea procedurală a lui F cu valoarea
procedurală a lui ReadInt pentru a determina dacă F referă ReadInt sau trebuie să
apeleze F şi ReadInt pentru a compara valorile returnate.
Sintaxa Object Pascal specifică faptul că prezenţa unui identificator de funcţie
într-o expresie înseamnă apelul acelei funcţii, astfel că efectul comparaţiei din
exemplul de mai sus este previzibil. Pentru a cere compararea valorilor procedurale
ale identificatorilor F şi ReadInt sintaxa obligatorie este:
:
if @F=@ReadInt
then
Edit1.Text:=’Egalitate’;
:
Aplicat unei valori procedurale sau unui identificator de funcţie sau procedură,
operatorul @ previne compilatorul să nu apeleze procedura şi, totodată converteşte
argumentul căruia i se aplică în pointer. Aşadar, @F converteşte F într-o variabilă
pointer fără tip care conţine o adresă iar @ReadInt returnează adresa funcţiei ReadInt.
Cele două valori pointer pot fi comparate pentru a determina dacă F referă ReadInt.
O altă situaţie în care putem folosi operatorul @ este prezentată în exemplul de
mai jos:
:
type
TSirComp=function(Sir1,Sir2:PChar):integer;
var
SirComp:TSirComp;
…
begin
@SirComp:=GetProcAdress(KernelHandle,’istrcmpi’);
…
end.
:
Tipurile variabile
24
Limbajul Object Pascal introduce, prin intermediul cuvântului cheie variant,
posibilitatea de a reprezenta valori al căror tip se modifică dinamic. În timp ce o
variabilă de orice alt tip este strict dependentă de acel tip, o variabilă de tip variant
poate primi valori de tipuri diferite, în timpul execuţiei programului.
Tipul variant are următoarele caracteristici:
O variabilă de tip variant poate conţine: valori întregi, valori reale, şiruri de
caractere, valori booleene, valori de tip data-şi-ora, precum şi obiecte OLE. Mai mult,
o variabilă de tip variant poate conţine tablouri de dimensiuni variabile, populate cu
elemente de oricare din tipurile mai sus precizate.
Valoarea specială de tip variant Unassigned este utilizată pentru a indica faptul
că unei variabile de tip variant nu i s-a atribuit, încă, o valoare.
Valoarea specială de tip variant Null este utilizată pentru a indica o dată lipsă
sau necunoscută.
Valorile de tip variant pot fi combinate între ele sau cu variabile statice de tip
integer, real, string şi boolean în expresii, compilatorul efectuând automat conversiile
necesare.
Dacă o variabilă de tip variant conţine un obiect OLE, atunci aceasta poate fi
folosită pentru a consulta şi seta proprietăţile obiectului sau pentru a invoca metodele
obiectului.
Variabilele de tip variant sunt întotdeauna iniţializate ca Unassigned când sunt
create pentru prima dată. Acest fapt este valabil indiferent dacă o variabilă de tip
variant este globală, locală sau parte a unei structuri de tip tablou, record sau obiect.
var
V1,V2,V3,V4,V5: variant;
I:integer;
D:double;
S:string;
begin
V1:=1; {Valoare întreagă }
V2:=1234.5678; {Valoare reală }
V3:=’ Sir de caractere’; {Valoare şir de caractere }
V4:=’1000’; {Valoare şir de caractere }
V5:=V1+V2+V4; {Valoarea reală 2235.5678 }
I:=V1; {I=1 }
D:=V2; {D=1234.5678 }
S:=V3; {S=’Sir de caractere’ }
I:=V4’; {I=1000 }
S:=V5; {S=’2235.5678’ }
end;
25
O variabilă de tip variant ocupă 16 octeţi iar reprezentarea ei internă constă dintr-
un cod de tip şi o valoare (sau referinţă la o valoare) de un anumit tip dat, conform
codului de tip. Funcţia standard VarType returnează codul de tip al unei variabile de
tip variant. În Tabelul 2.11 prezentăm o listă parţială a constantelor utilizate pentru
identificarea tipului datelor păstrate într- variabilă de tip variant, împreună cu
valorile asociate şi semnificaţia lor.
26
Delphi păstrează valorile referitoare la dată şi oră în variabile de tip TDateTime
astfel:
Partea întreagă a valorii păstrate în variabila de tip TDateTime reprezintă
numărul de zile trecute începând din 30 decembrie 1889.
Partea fracţionară a valorii păstrate în variabila de tip TDateTime reprezintă
ora.
O parte din procedurile furnizate de unit-ul SysUtils pentru manipularea
variabilelor de tip TDateTime sunt:
27
procedure TForm1.Button1Click(Sender: TObject);
begin
Label1.Caption := DateToStr(Date);
end;
Alte funcţii a căror descriere poate fi găsită cu ajutorul Help-ului Delphi sunt:
Operatori Categoria
. ^ Dereferenţiere câmp sau pointer (Precedenţa cea
mai înaltă)
@ not Operatori unari
* / div mod as and shl Operatori multiplicativi şi de typecasting
shr
+ - or xor Operatori conjunctivi(aditivi)
= <> > < <= >= in is Operatori de comparare şi apartenenţă (Precedenţa
cea mai joasă.
Tabelul 2.12 Operatorii Object Pascal grupaţi pe categorii de precedenţă.
28
De remarcat faptul că o parte din operatorii prezentaţi în Tabelul 2.12 au două
întrebuinţări : operatori la nivel de bit sau operatori logici în funcţie de
contextul în care sunt utilizaţi. În Tabelul 2.13 prezentăm, împreună cu
operatorii dedicaţi lucrului la nivel de bit şi operatorii cu dublă
întrebuinţare.
Operator Semnificaţie
not negaţia logică asupra variabilelor booleene / inversarea poziţiilor
binare ale unei variabile convenabile aplicării operatorului.
and şi logic asupra variabilelor booleene / şi logic asupra altor tipuri de
operatori convenabili.
or sau logic asupra variabilelor booleene / sau logic asupra altor tipuri
de operatori convenabili.
xor sau logic exclusiv asupra variabilelor booleene / sau logic exclusiv
asupra altor tipuri de operatori convenabili.
shl Shiftare logică la stânga
shr Shiftare logică la dreapta
Tabelul 2.13 Operatori la nivel de bit în Object Pascal
Instrucţiuni simple
Instrucţiunile simple modifică conţinutul memoriei prin asignarea unei valori,
apelează o procedură sau o funcţie sau (ceea ce nu este tocmai în spirit profesional)
determină transferarea necondiţionată a controlului execuţiei unui program la o
instrucţiune oarecare a programului. Instrucţiunile simple în Object Pascal sunt:
-Instrucţiunea de atribuire;
-Apelul de subrutină;
-Instrucţiunea goto;
Instrucţiunea de atribuire
Sintaxa Object Pascal pentru o instrucţiune de atribuire este:
29
<Identificator_Variabilă>:=<Expresie>;
Apelul de subrutină
Un apel de subrutină determină transferul controlului execuţiei programului către
o procedură, funcţie sau metodă de prelucrare,execuţia blocului de instrucţiuni
aferent, urmată de revenirea şi continuarea execuţiei cu instrucţiunea carea urmează
apelului de subrutină. Sintaxa unui apel de subrutină se circumscrie regulilor
cunoscute deja de la studiul limbajului Pascal.
Instrucţiunea goto
Deşi controverstă, mai ales din perspectiva principiilor programării structurate,
instrucţiunea goto are drept de cetate şi în Object Pascal. Se cunoaşte faptul că, de
exemplu, şi limbajul C, specifică posibilitatea utilizării instrucţiunii goto.
Recomandarea valabilă în orice limbaj de programare este să nu se abuzeze de
utilizarea acestei instrucţiuni, deoarece, în caz contrar, calitatea programului are de
suferit.
Instrucţiuni structurate
Cu ajutorul instrucţiunilor structurate, putem grupa prelucrările simple sau
compuse în conformitate cu cerinţele de moment, putem ramifica prelucrările în
funcţie de valoarea anumitor condiţii logice, putem executa în mod repetat anumite
prelucrări. Adică, pot fi reprezentate structurile fundamentale de prelucrare.
Oferta Object Pascal pentru reprezentarea structurilor fundamentale de prelucrare
este următoarea:
-Instrucţiunea compusă;
-Instrucţiunile condiţionale (if, case);
-Instrucţiunile repetitive (for, while, repeat);
-Instrucţiunea with.
Instrucţiunea compusă
Instrucţiunile compuse specifică o ordine în care instrucţiunile, pe care le conţin,
trebuie executate. Dacă secvenţa de instrucţiuni este delimitată de begin şi end,
atunci întreaga secvenţă poate fi tratată ca o instrucţiune şi utilizată ca atare în
construcţiile sintactice Object Pascal care o permit.
Instrucţiuni condiţionale
Instrucţiunea if
Sintaxa instrucţiunii if este:
30
if <Expresie>
then
<Instrucţiune_1>
[else
<Instrucţiune_2>];
<Expresie> trebuie să returneze un rezultat de tip boolean. Dacă <Expresie>
returnează TRUE, atunci va fi executată <Instrucţiune_1>, care urmează clauze then.
Dacă <Expresie> returnează FALSE şi clauza else este prezentă, atunci se execută
<Instrucţiune_2> care urmează clauzei else. Dacă <Expresie> returnează FALSE şi
clauza else lipseşte, atunci se execută instrucţiunea care urmează după instrucţiunea
if, privită ca întreg. <Instrucţiune_1> şi <Instrucţiune_2> pot fi simple sau compuse.
Instrucţiunea case
Sintaxa instrucţiunii case este:
case <Selector> of
<Val_Sel_1>: <Instrucţiune_1>;
<Val_Sel_2>: <Instrucţiune_2>;
:
<Val_Sel_n>: <Instrucţiune_n>
end;
sau
case <Selector> of
<Val_Sel_1>: <Instrucţiune_1>;
<Val_Sel_2>: <Instrucţiune_2>;
:
<Val_Sel_n>: <Instrucţiune_n>
else
<Instrucţiune>
end;
:
case Operator of
Plus: X := X + Y;
31
Minus: X := X - Y;
Times: X := X * Y;
end;
:
sau
:
case I of
0, 2, 4, 6, 8: Edit1.Text := 'Cifra para';
1, 3, 5, 7, 9: Edit1.Text := 'Cifra impara';
10..100: Edit1.Text := 'Intre 10 si 100';
else
Edit1.Text := 'Negativ sau mai mare decat 100';
end;
:
sau
:
case MySelector of
5: Edit1.Text := 'Caz special';
1..10: Edit1.Text := 'Caz general';
end;
:
Instrucţiuni repetitive
Repetitiva cu număr cunoscut de paşi
Pentru reprezentarea secvenţelor repetitive cu număr cunoscut de paşi în Object
Pascal, la fel ca în Pascal, avem la dispoziţie instrucţiunea cu sintaxa generală:
sau
32
Pentru reprezentarea repetitivelor cu număr necunoscut de paşi la care se preferă
condiţionarea anterioară avem sintaxa:
while <Expresie> do
<Instrucţiune>;
repeat
<Instrucţiune>
until <Expresie>;
Instrucţiunea with
Instrucţiunea with este utilizată pentru simplificarea dereferenţierii câmpurilor
unor variabile record şi a membrilor unui obiect. Astfel, în Object Pascal este foarte
frecvent întâlnită o situaţie de genul:
33
procedure TForm1.Button1Click(Sender: TObject);
begin
with ListBox1 do
begin
Clear;
MultiSelect := True;
Items.Add('One');
Items.Add('Two');
Items.Add('Three');
Sorted := True;
Font.Style := [fsBold];
Font.Color := clPurple;
Font.Name := 'Times New Roman';
ScaleBy(125, 100);
end;
end;
Antet procedură
procedur
e Identificator
Identificator metodă
calificată
cdecl
forward
stdcall 34
safecall
Declararea unei funcţii
Antet funcţie
function Identificator
Identificator metodă
calificată
; Tip rezultat
Bloc subrutină
bloc
register ;
directivă externă
cdecl
forward
stdcall
safecall 35
Din analiza sumară a diagramelor de sintaxă, rezultă o serie de particularităţi
Object Pascal în utilizarea procedurilor şi a funcţiilor. Aceste particularităţi se referă
la posibilitatea de a alege, în funcţie de context, convenţia de apel, precum şi la
protocolul de utilizare a directivelor externe în cazul în care procedurile sau funcţiile
fac parte din potenţialul de calcul al bibliotecilor de legături dinamice (DLL).
Deocamdată, să mai menţionăm un amănunt care nu transpare din analiza diagramei
de sintaxă a funcţiei.
Pentru a returna prin nume o valoare de un anumit tip, în secţiunea executabilă a
unei funcţii trebuie să apară o atribuire de tipul:
<Nume_Funcţie>:=Result;
Variabila Result este creată automat în corpul unei funcţii Object Pascal, având
tipul acesteia.
Precizările care se referă la vizibilitatea variabilelor în blocurile procedurale,
precum şi la transmiterea parametrilor între <apelat> şi <apelant> sunt similare celor
cunoscute de la programarea în Pascal.
36
Secţiunea de interfaţă a unităţii este destinată declarării acelor resurse care
urmează să fie exportate către alte programe sau unit-uri (constante, tipuri, variabile,
proceduri,funcţii);
Secţiunea de implementare este porţiunea din unit în care apare codul
complet al unităţilor de prelucrare exportate, precum şi codul unor unităţi de
prelucrare de interes local, dacă este cazul.
Secţiunea de iniţializare a unit-ului este secţiunea în care apare, opţional,
codul care realizează iniţializarea mediului în care urmează să lucreze capabilităţile
unit-ului. Acest cod este executat la începerea execuţiei programului, deci înainte de
a se preda controlul instrucţiunilor programului principal. Dacă sunt mai multe unit-
uri care au secvenţe de iniţializare, acestea se vor executa în ordinea în care sunt
declarate unit-urile în lista asociată clauzei uses.
Secţiunea de finalizare, o noutate Object Pascal, în materie de modularizare a
aplicaţiilor în context Delphi, este utilizată pentru a permite o serie de prelucrări
specifice terminării apelului la resursele unui unit. Această secţiune este opţională,
dar poate apare numai în condiţiile în care există şi o secvenţă de iniţializare.
Instrucţiunile care urmează cuvântului cheie finalization sunt executate la terminarea
programului. Ne putem imagina următorul scenariu plauzibil pentru utilizarea celor
două secţiuni: toate resursele alocate sau deschise în secvenţa de iniţializare
(memorie, fişiere,etc.) sunt eliberate sau închise în secţiunea de finalizare. De
asemenea, secvenţa de finalizare poate elibera orice resursă necesară pentru execuţia
normală a unit-ului însuşi. Dacă sunt mai multe unit-uri care au secvenţe de
finalizare, acestea se vor executa în ordinea inversă în care apar în unit-urile în lista
care face obiectul clauzei uses.
Aşadar, programarea orientată pe unit-uri presupune abilitatea programatorului
de a specifica resurse statice generice (constante, tipuri, variabile) şi, mai ales,
abilitatea de a specifica unităţi de prelucrare cu interfaţă eficientă şi stabilă. Dacă
există astfel de abilităţi, atunci codul obţinut este fiabil, rezistent la modificări şi
versatil. La nevoie, datorită localizării indusă de abstractizare, modificările se fac cu
minim de efort.
Unit-urile oferă pentru programator următoarele avantaje:
Sunt păstrate în format binar, ceea ce înseamnă scurtarea timpului de generare
a fişierelor executabile;
Pot fi utilizate ca suport pentru promovarea încapsulării acelor resurse care
sunt critice pentru existenţa aplicaţiei (Se operează o distincţie clară între ceea ce
trebuie văzut din afara unit-ului şi ceea ce este de interes local acestuia);
Constituie o bază a promovării abstractizării, în sensul că pot exista două
unităţi cu aceeaşi interfaţă dar cu implementări diferite, înlocuirea unei unităţi cu alta
nefiind problematică din punct de vedere sintactic.
Referitor la utilizarea unit-urilor, adăugăm următoarele precizări:
<Nume unitate> este identificatorul unit-ului şi trebuie să coincidă cu
numele fişierului în care este definit acesta. De remarcat faptul că unit-urile
folosite la un moment dat trebuie să aibă nume diferite.
<Lista alte unităţi> reprezintă lista altor unităţi folosite de către unitatea
curentă. Nu se permit referinţe circulare.
37
<Declaraţii globale> indică declaraţiile de constante, tipuri,variabile,etc.
vizibile atât în cadrul unit-ului curent cât şi în toate unităţile şi programele care îl
utilizează.
<Lista de funcţii şi proceduri globale> specifică antetele funcţiilor şi/sau
procedurilor declarate ca vizibile în unit şi în toate unităţile şi programele care îl
utilizează.
<Lista unităţi utilizate> reprezintă lista altor unităţi utilizate de către unitatea
curentă, dar necesare doar părţii de implementare. Sunt permise referinţe circulare
între unităţi.
<Declaraţii locale> permite specificarea unor constante, variabile, etc.
necesare doar părţii de implementare, deci invizibile pentru alte unităţi sau programe.
<Implementare proceduri şi funcţii> ocazionează implementarea procedurilor
şi funcţiior ale căror antete au fost anunţate în interface ,precum şi a altor proceduri
şi funcţii necesare părţii de implementare.
38
3. Concepte avansate în programarea Object
Pascal
În această secţiune ne propunem să luăm în discuţie o serie de aspecte care
subliniază pregnant noutatea ofertei Delphi, în principal, în materie de programare
obiect orientată. Se va putea observa la finalul secţiunii, efortul făcut de cei care au
specificat Object Pascal, pentru a apropia acest limbaj de standardele de facto în
programarea obiect orientată şi, totodată, de a păstra proprietăţile limbajului Pascal
specificate de primul lui părinte Niklaus Wirth.
<TClasa_Utilizator>=class [(<TClasa_Definitoare>)]
public
<Nume_Camp>:<Tip_Camp>;
…
<Antet_Metoda>
…
property
<Nume_Proprietate>:<Tip_Proprietate>
read <Nume_Camp/Nume metoda>
write < Nume_Camp/Nume metoda>
…
private
:
protected
:
published
39
:
end;
Domenii de vizibilitate
Componentele unei clase pot avea domenii de vizibilitate diferite, în funcţie de
directiva de specificare a vizibilităţii sub a cărei incidenţă se află. După cum se vede
şi mai sus, aceste directive de specificare a vizibilităţii sunt: private, protected,
public şi published. Aceste directive restricţionează vizibilitatea componentelor în
situaţia în care alte unit-uri forţează accesul la ele. În interiorul unit-ului în care este
definită clasa, toate componentele sunt vizibile.
Observaţie
Spre deosebire de mulţi alţi identificatori utilizaţi în declararea tipurilor,
directivele de specificare a vizibilităţii nu sunt cuvinte rezervate în afara contextului
care ocazionează declararea clasei. În practică se recomandă, totuşi, să le tratăm ca şi
când ar fi cuvinte rezervate, în adevăratul sens al cuvântului.
40
Informaţiile de tip run-time permit unei aplicaţii externe să afle date despre
câmpurile, metodele sau proprietăţile unui obiect, despre clasa definitoare a
obiectului, etc.
Pe timpul execuţiei unui program, din punct de vedere al vizibilităţii, o
componentă published se comportă ca şi când ar fi o componentă de tip public.
Toate componentele published sunt vizibile în orice unit unde clasa care le
încapsulează este vizibilă. Diferenţa constă în faptul că, o aplicaţie externă poate
obţine informaţii de tip run-time despre componentele published.
Ca un exemplu, inspectorul de obiecte al sistemului Delphi foloseşte interfeţele
published ale obiectelor din Paleta de Componente a sistemului Delphi pentru a
determina ce proprietăţi şi evenimente trebuie vizualizate în timpul proiectării unei
aplicaţii.
Există anumite restricţii în ceea ce priveşte modul de utilizarea al directivei
published.
O clasă poate avea componente published dacă este compilată sub incidenţa
directivei {$M} având starea {$M+} sau dacă este derivată dintr-o clasă care deja a
fost compilată astfel încât să aibă componente published. Directiva {$M}
controlează generarea RTTI.
Un câmp definit într-o secţiune published trebuie să fie de tip clasă. Câmpurile
de orice alt tip trebuie plasate în secţiunile public, protected sau private.
Proprietăţile published sunt restricţionate din punct de vedere al tipului. Sunt
acceptate proprietăţi de tip:
-ordinal;
-real(Single, Double, Extended, Comp, nu şi real);
-şir de caractere;
-mulţime (small set);
-clasă;
-identificator de metodă (dar nu tip procedural global)
Small set desemnează un tip mulţime al cărui tip de bază este ordinal şi ale cărui
valori ordinale sunt cuprinse între 0 şi 50.
Metode
În procesul de definire a unei clase, metodele leagă codul cu tipurile de date pe
care codul este abilitat să le manipuleze. În acest scop, metodele au dreptul să
acceseze câmpurile unui obiect fără ca acestea să-i fie trimise explicit ca parametri.
Declararea unei metode are două părţi: declararea signaturii metodei în procesul
de definire a clasei şi implementarea corpului metodei în afara definiţiei clasei, dar
în acelaşi unit în care s-a definit şi clasa. De la programarea Pascal OO se ştie că
declararea signaturii este asemănătoare unei declaraţii forward de procedură sau
funcţie. De subliniat ceea ce, de asemenea, se ştie de la Pascal OO şi anume faptul că
implementarea corpului metodei presupune ca antetul ei să specifice numele clasei
din a cărei definiţie face parte metoda. Referitor la implementarea unei metode mai
facem următoarele precizări:
În interiorul corpului unei metode, o instrucţiune care apelează o funcţie sau o
procedură permite utilizarea designatorilor de metodă calificată pentru a activa o
anumită metodă a unei clase. Un designator de metodă poate fi o variabilă referinţă la
41
un obiect sau o referinţă la o clasă. Cuvântul rezervat inherited desemnează
strămoşul tipului obiect care include metoda. Prezentăm în continuare un exemplu de
definire a unei clase împreună cu implementarea metodei aferente în care se
utilizează şi cuvântul rezervat inherited.
type
TFramedLabel = class(TLabel)
protected
procedure Paint; override;
end;
:
procedure TFramedLabel.Paint;
begin
inherited Paint;
with Canvas do
begin
Brush.Color := clWindowText;
Brush.Style := bsSolid;
FrameRect(ClientRect);
end;
end;
with Self do
begin
...
end;
Variabila Self este o variabilă de acelaşi tip cu clasa în care apare metoda.
Implicit metodele sunt statice. Object Pascal propune însă şi alte tipuri de metode, din
perspectiva modului de rezolvare a apelului acestora. Le prezentăm în Tabelul 3.1.
Directivă Efect
Virtual Metoda apelată este determinată cu ajutorul tabelei VMT
Dynamic Metoda apelată este determinată cu ajutorul tabelei de metode
dinamice
Message Metoda apelată este determinată cu ajutorul mecanismului de
transmitere a mesajelor
Abstract Metoda nu are implementare dar trebuie redefinită în aval
Override Metoda redefineşte o metodă virtuală sai dinamică
Class Apel de metodă fără a utiliza variabila implicită Self
Tabelul 3.1 Tipuri de metode în Object Pascal
42
Evident, în Object Pascal pot fi metode :procedurile, funcţiile, constructorii şi
destructorii. În linii mari, constructorii şi destructorii se utilizează cu semnificaţia
care se cunoaşte de la limbajul Pascal.
Metode statice
Metodele declarate într-o clasă sunt implicit statice. Nu este necesar un
identificator special pentru a desemna o metodă de tip static. Când este apelată o
metodă statică, tipul variabile este cel care determină ce metodă urmează să fie
executată. Compilatorul determină exact adresa metodei în timpul compilării.
Avantajul fundamental al metodelor statice constă în faptul că executarea lor este
foarte rapidă. Prin contrast, metodele virtuale şi dinamice rezolvă în timpul execuţiei
problema legării codului care trebuie executat, ceea ce lungeşte timpul de execuţie al
programelor dacă se abuzează de apelul la metode virtuale sau dinamice.
O metodă statică nu poate fi schimbată când este moştenită de un descendent al
clasei în care aceasta este definită. Altfel spus, dacă declaraţi o clasă care include în
definiţie o metodă statică, atunci derivând o nouă clasă din aceasta, clasa derivată
partajează exact aceeaşi metodă, situată la aceeaşi adresă. Aceasta înseamnă că nu
putem redefini static metodele.
În exemplul de mai jos, prima clasă declară două metode statice. Cea de-a doua
clasă declară două metode statice cu acelaşi nume, care înlocuiesc metodele
moştenite de la prima clasă.
:
type
TFirstComponent = class(TComponent)
procedure Move;
procedure Flash;
end;
TSecondComponent = class(TFirstComponent)
procedure Move; { diferită de metoda moştenită,
acelaşi antet}
function Flash(HowOften: Integer): Integer; {Evident,
diferită de metoda moştenită }
end;
:
Metode virtuale
Spre deosebire de apelul metodele statice, apelurile metodelor virtuale nu sunt
rezolvate în faza de compilare. Metoda care urmează să fie executată, în cazul virtual
este determinată în timpul execuţiei printr-un procedeu numit legare întârziată.
Orice metodă poate fi făcută virtuală prin menţionarea unei directive virtual la
sfârşitul definiţiei metodei în lista de componente a clasei. Noutatea metodelor
virtuale constă în următorul mecanism: dacă într-un lanţ de derivare, o anumită
metodă, declarată virtuală în clasa rădăcină, apare în descendenţi redefinită (marcată
de directiva override), atunci un apel la metoda respectivă, făcut din contextul unei
variabile compatibilă cu lanţul de derivare, va fi rezolvat în funcţie de tipul curent al
43
variabilei. Tipul variabilei este stabilit în momentul creării instanţei, de către
constructorul corespunzător clasei context.
Alegerea metodei corespunzătoare contextului se face cu ajutorul tabelelor VMT,
unice, asociate claselor care au metode virtuale şi create la apelarea constructorilor.
Metode dinamice
Un mecanism oarecum similar metodelor virtuale este utilizat şi în cazul
metodelor dinamice. Din punctul de vedere al utilizatorului nu se poate face diferenţa
între cele două tipuri de metode. Codul generat, însă, diferă semnificativ, astfel:
apelurile metodelor virtuale sunt mai rapide dar generează creşterea codului; apelurile
metodelor dinamice sunt mai lente, dar generează cod mai mare.
În mod uzual, metodele virtuale sunt preferate dacă se doreşte exploatarea
capabilităţilor polimorfice ale unui lanţ de derivare. Dacă, însă, se doreşte crearea
unei clase de bază din care se derivează un număr mare de descendenţi, şi în fiecare
descendent se redefineşte un număr mic de metode virtuale moştenite.
const
CM_CHANGECOLOR = WM_USER + 400;
type
TMyComponent = class(TControl)
...
protected
procedure CMChangeColor(var Message: TMessage): message
CM_CHANGECOLOR;
…
end;
procedure TMyComponent.CMChangeColor(var Message: TMessage);
begin
Color := Message.lParam;
inherited;
end;
44
Metode abstracte
De regulă când se specifică o metodă în lista de componente asociată definiţiei
unei clase, compilatorul se aşteaptă să găsească implementarea metodei în secţiunea
corespunzătoare a unit-ului gazdă. Pe de altă parte, atunci când se specifică o metodă
în clasa de bază, se stabileşte un comportament implicit al tuturor descendenţilor,
relativ la metoda respectivă. Pentru a schimba comportamentul în descendenţi,
trebuie redefinită metoda în descendenţi. Dacă nu are sens asocierea în clasa de bază
a unui comportament implicit, se poate utiliza directiva abstract, pentru a semnala
compilatorului că nu va fi implementată o metodă implicită. De precizat faptul că
orice metodă declarată abstractă trebuie să fi, totodată virtuală sau dinamică, ca în
exemplul de mai jos.
type
Base = class
procedure DaliVision; virtual; abstract;
procedure TellyVision; dynamic; abstract;
end;
type
TFirstComponent = class(TCustomControl)
procedure Move; { metodă statică }
procedure Flash; virtual; { metodă virtuală }
procedure Beep; dynamic; { metodă dinamică }
end;
TSecondComponent = class(TFirstComponent)
procedure Move; { declarare metodă nouă }
procedure Flash; override; { redefinire metodă moştenită
}
procedure Beep; override; { redefinire metodă moştenită
}
end;
45
type
Tclass1 = class
Nume:string;
class procedure ModificNume (NumeNou:string);
end;
class procedure ModificNume (NumeNou:string);
begin
Nume:=NumeNou;
end;
Unit-ul System defineşte două tipuri, TObject şi TClass, care sunt tipuri rădăcină
pentru toate tipurile clasă şi referinţă la clasă, despre care vom discuta în continuare.
Rădăcina TObject conţine o bogată colecţie de metode de tip clasă pe care le putem
apela fără a fi nevoie să instanţiem clasa.
type
TObject = class;
TClass = class of TObject;
TObject = class
constructor Create;
destructor Destroy; virtual;
class function ClassInfo: Pointer;
class function ClassName: ShortString;
class function ClassNameIs(const Name: string): Boolean;
class function ClassParent: TClass;
function ClassType: TClass;
procedure CleanupInstance;
procedure DefaultHandler(var Message); virtual;
procedure Dispatch(var Message);
function FieldAddress(const Name: ShortString): Pointer;
procedure Free;
procedure FreeInstance; virtual;
class function InheritsFrom(AClass: TClass): Boolean;
class function InitInstance(Instance: Pointer): TObject;
46
Conceptul de proprietate
Conceptul de proprietate nu este absolut nou. În Turbo Pascal, proprietăţile se
confundau cu înregistrările sau câmpurile unui obiect. În Delphi, noţiunea de
proprietate, ca şi concept nou, pare să fie strâns legată de necesităţile programării
vizuale. Este adevărat doar în parte deoarece noţiunea de proprietate are o valoare de
întrebuinţare care depăşeşte cerinţele programării vizuale. O definiţie de proprietate
într-o clasă permite declararea unui anumit atribut al obiectelor unei clase şi a
acţiunilor asociate cu citirea şi scrierea atributelor. Exemple de astfel de proprietăţi
sunt : proprietatea “Caption” a unei forme, mărimea fontului intr-un derivat TMemo,
etc.
Putem spune că proprietăţile sunt o extensie naturală a câmpurilor unui
obiect. Atât câmpurile cât şi proprietăţile pot fi utilizate pentru a exprima atributele
unui obiect, dar, în timp ce câmpurile sunt doar locaţii de memorie care pot fi
examinate şi modificate după dorinţă, proprietăţile asigură un control mai mare
asupra valorilor atributelor, datorită mecanismelor de citire /scriere cu care se
asociază o anumită proprietate.
Prezentăm mai jos, cu ajutorul limbajului diagramelor de sintaxă, regulile
sintactice care stau la baza specificării proprietăţilor unei clase.
Definiţie proprietate
property Identificator
Interfaţă
proprietate
Specificatori
;
proprietate
: Tip identificator
Listă parametri
proprietate
[ Declarare parametru ]
Specificator
Specificator Specificator Specificator
de
READ WRITE implicit
stocare
Constanta
booleană
48
default Constantă
nodefault
Identificator câmp
Identificator metodă
unit Exemplu;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TArrayProp = array [1..5] of string[7];
TEverything = class(TCustomControl)
private
{ Private declarations }
FArrayProp : TArrayProp;
function GetArrayPropInt(pIndex: integer): string;
function GetArrayPropStr(pIndex: string): integer;
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
property ArrayPropInt[Index: integer]: string read GetArrayPropInt;
property ArrayPropStr[Index: string]: integer read GetArrayPropStr;
published
{ Published declarations }
end;
procedure Register;
implementation
49
// Iniţializare FArrayProp
FArrayProp[1] := 'one';
FArrayProp[2] := 'two';
FArrayProp[3] := 'three';
FArrayProp[4] := 'four';
FArrayProp[5] := 'five';
end;
procedure Register;
begin
RegisterComponents('UD3', [TEverything]);
end;
end.
Blocuri de protecţie
50
În Delphi, tratarea excepţiilor se face prin aşa numitele blocuri de protecţie, care
pot executa, fie un cod de terminare pentru a nu fi compromisă sesiunea Windows,
fie o secvenţă de cod care tratează efectiv excepţia, caz în care execuţia programului
continuă normal.
Aceste blocuri de protecţie sunt la rândul lor compuse din alte două tipuri de
blocuri, un bloc de gardă, care, aşa după cum îi spune numele este răspunzător de
interceptarea excepţiei şi un bloc de răspuns ce conţine codul de tratare al excepţiei,
sau codul corespunzător terminării aplicaţiei.
Structura de principiu a unui bloc de protecţie în Delphi este:
try
//Blocul de gardă în care excepţia este susceptibilă
// să apară
finally
//Blocul de răspuns ce conţine codul de terminare,
//fără a înlătura evoluţia excepţiei
end;
sau
try
//Blocul de gardă în care excepţia este susceptibilă
//să apară
except
//Blocul de răspuns ce conţine codul de tratare,
//a excepţiei
on <Tip_Exceptie_1> do <Instrucţiune_1>
on <Tip_Exceptie_2> do <Instrucţiune_2>
:
on <Tip_Exceptie_n> do <Instrucţiune_n>
end;
Dacă vreuna dintre instrucţiunile cuprinse între try şi finally provoacă o excepţie,
atunci sistemul predă controlul blocului de răspuns, cuprins între finally şi end.
Dacă nu a apărut nici o excepţie, după epuizarea instrucţiunilor cuprinse între try şi
finally, se continuă cu execuţia instrucţiunilor cuprinse între finally şi end.
Altfel spus, în varianta cu finally avem la dispoziţie un mecanism cu ajutorul
căruia avem garanţia că se execută un cod de terminare corectă a unui tip de
prelucrare, indiferent de excepţiile care pot apare. Prin acest mecanism se urmăreşte
limitarea efectelor posibilelor excepţii la execuţia unui program Delphi.
Să mai adăugăm faptul că, în varianta cu finally, după execuţia codului de
terminare, dacă a apărut o excepţie, aceasta îşi continuă evoluţia (nu este ridicată),
putând fi interceptată şi tratată într-o buclă try externă, iar dacă această buclă nu este
găsită, putând provoca în cele din urmă terminarea anormală a programului.
51
În varianta cu except execuţia decurge astfel:
Lista instrucţiunilor din blocul try se execută în ordine. Dacă nu apare nici o
eroare, blocul except este ignorat, continuându-se execuţia cu prima instrucţiune
aflată după end. Dacă a apărut o excepţie, controlul este dat celui mai interior handler
de excepţie existent. Dacă un astfel de handler de excepţie nu există, atunci se va
căuta un handler de excepţii în exterior, în alt bloc try-except, neterminat încă. Dacă
un astfel de handler nu este găsit, se continuă astfel până la epuizarea blocurilor try-
except, sau până la găsirea handler-ului de excepţie adecvat. Dacă nu este găsit nici
un handler, se generează un mesaj standard de eroare şi execuţia este terminată
anormal.
În sfârşit, să mai adăugăm precizarea că, similar modului în care utilizam în C++
enunţul throw, în Object Pascal putem folosi enunţul raise pentru a genera o excepţie.
Delphi pune la dispoziţia programatorului clase de excepţii, extrem de utile pentru
a monitoriza sistematic apariţia excepţiilor uzuale ale unei aplicaţii Delphi (împărţie
la zero, acces nepermis la memorie, eroare la crearea unui fişier, etc.).
unit UExcept1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
Label1: TLabel;
Edit2: TEdit;
Label2: TLabel;
Button1: TButton;
Label3: TLabel;
Edit3: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
52
Op1,Op2,Rezultat:real;
implementation
{$R *.DFM}
end.
unit UExcept2;
//Aplicatie la tratarea exceptiilor in Delphi
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Buttons;
//----------------------------------------------------------
// Codul care urmeaza este o interfata intre
//exceptiile aplicatiilor utilizator si sistem
// asigurata de clasa Exception din unit-ul SYSUTILS, prezentată mai jos sub formă
de //comentariu.
//----------------------------------------------------------
(*Exception = class(TObject)
private
FMessage: string;
53
FHelpContext: Integer;
public
constructor Create(const Msg: string);
constructor CreateFmt(const Msg: string; const Args: array of const);
constructor CreateRes(Ident: integer);
constructor CreateResFmt(Ident: integer; const Args: array of const);
constructor CreateHelp(const Msg: string; AHelpContext: integer);
constructor CreateFmtHelp(const Msg: string; const Args: array of const;
AHelpContext: integer);
constructor CreateResHelp(Ident: integer; AHelpContext: integer);
constructor CreateResFmtHelp(Ident: integer; const Args: array of const;
AHelpContext: integer);
property HelpContext: integer read FHelpContext write FHelpContext;
property Message: string read FMessage write FMessage;
end;
*)
type
EMyComponentError = class(Exception)
private
FErrorCode: integer;
public
property ErrorCode: integer read FErrorCode write FErrorCode;
constructor Create(const Msg: string; ErrCode: integer);
end;
EMyCompoRangeError =class(EMyComponentError);
EMyCompoInvalidValue =class(EMyComponentError);
TForm1 =class(TForm)
Button1: TButton;
Button3: TButton;
Button2: TButton;
Button4: TButton;
Button5: TButton;
ListBox1: TListBox;
Button6: TButton;
Button7: TButton;
Button8: TButton;
BitBtn1: TBitBtn;
procedure Button1Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button6Click(Sender: TObject);
54
procedure Button7Click(Sender: TObject);
procedure Button8Click(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1 :TForm1;
Stream :TMemoryStream;
implementation
{$R *.DFM}
//----------------------------------------------------------
// Rutinele care urmeaza sunt scrise utilizand
// maniera Delphi de tratare a exceptiilor
//----------------------------------------------------------
procedure UseFunctions;
var cVal: char;
sStrVal: string;
begin
try
sStrVal := 'Delphi Rock ';
cVal := CharFromString(sStrVal,13);
if cVal <> 's' then
InsertChar('s',sStrVal,12);
ShowMessage(sStrVal);
except
55
exit;
end;
end;
//----------------------------------------------------------
// Aceste rutine rezolva aceleasi probleme ca
// mai sus intr-un stil de programare defensiv
// clasic.
//----------------------------------------------------------
procedure UseFunctions;
var cVal: char;
sStrVal: string;
begin
sStrVal := 'Delphi Rock ';
cVal := CharFromString(sStrVal,12);
if cVal <> #0 then
begin
if cVal <> 's' then
if InsertChar('s',sStrVal,12) then
ShowMessage(sStrVal)
else
exit;
end
else
56
exit;
end;
//----------------------------------------------------------
// Aceste rutine exemplifica utilizarea optionala
// a sintaxei [on..do] a unei constructii [try..except]
//----------------------------------------------------------
procedure LowMemTerminate;
begin
{Eventuale instructiuni de de-initializare}
Application.Terminate;
end;
57
mtError,[mbYes,mbNo],0) = mrYes then
Application.Terminate;
end
else
Raise;
end;
end;
end;
//----------------------------------------------------------
// Imbricare constructii [try..except] si [try..finally]
//----------------------------------------------------------
procedure TForm1.Button4Click(Sender: TObject);
var sVar: string;
pVar: PChar;
begin
try
GetMem(pVar,10);
try
StrCopy(pVar,'ListBox');
with ListBox1.Items do
begin
Add('Line1 - index 0');
Add('Line2 - index 1');
end;
sVar := ListBox1.Items[2];
finally
FreeMem(pVar,10);
end;
except
on EStringListError do
MessageDlg('List index out of bounds', mtError, [mbOk], 0);
on EAccessViolation do
MessageDlg('Memory Overwrite', mtError, [mbOk], 0);
else
Raise;
end;
end;
58
try
sVar := ListBox1.Items[0];
except
on EStringListError do
begin
ListBox1.Items.Add('Item1');
sVar := ListBox1.Items[0];
end
else Raise;
end;
{Instructiuni de manipulare variabila sVar}
finally
FreeMem(pVar,10);
end;
end;
//----------------------------------------------------------
// Aceste rutine arata utilizarea unei instantede tip EAbort
// [Silent Exception]
//----------------------------------------------------------
//----------------------------------------------------------
// These routines demonstrate the use of raising an
// exception of type EAbort - the silent exception
//----------------------------------------------------------
constructor EMyComponentError.Create(const Msg: string; ErrCode: integer);
begin
Inherited Create(Msg);
FErrorCode := ErrCode;
end;
const
59
cInvalidValue = 0;
cRangeError = 1;
//----------------------------------------------------------
// These routines relate to the creation of custom exception
// types. Move statments into your global handler and
// replace "Sender" with EInstance to test
//----------------------------------------------------------
procedure TForm1.Button7Click(Sender: TObject);
begin
if Sender is EMyComponentError then
case (Sender as TCOmponent).Tag of
cInvalidValue: {statements for appropriate action here};
cRangeError : {statements for appropriate action here};
else
begin
ShowMessage('Fatal Error - Terminating program');
Application.Terminate;
end;
end;
end;
end.
60
4.Bibliotecile RUNTIME ale sistemului DELPHI
Biblioteca RUNTIME (RTL) a sistemului DELPHI constă din trei unit-uri compilate
separat: System, SysUtils, Math. Capabilităţile acestor unit-uri pot fi utilizate în
programele utilizator implicit sau dacă în unit-urile asociate acestora sunt referite
cu ajutorul clauzei uses.
Unit-ul System defineşte o serie de tipuri de date care pot fi utilizate în diferite
contexte ale aplicaţiilor utilizator. Astfel avem, de exemplu, tipul TdateTime ,
declarat ca un o varietate specială de virgulă mobilă, astfel:
:
type
TdateTime =double;
:
Acest gen de redeclarare a tipului double oferă programatorilor posibilitatea de a
distinge variabilele virgulă mobilă utilizate pentru a păstra valori timp/dată de
variabilele virgulă mobilă folosite în alte scopuri.
Există o serie de alte tipuri de date, mult mai complexe, strict necesare pentru accesul
la tipuri de date uzuale. De exemplu, tipul TvarData declară structura internă a tipului
predefinit “Variant”. De asemenea, tipul TvarRec declară structura internă a
variabilelor care sunt transmise rutinelor ca parametri formali de tip “array of const”.
:
CmdLine: pchar=nil; //Pointer linie de comandă
CmdShow: integer=0; //Parametru ShowWindow
FileMode: byte=2; //Mod implicit deschidere fişier
Hinstance: longint=0; //Handler-ul instanţei curente în mediul Windows
InOutRes: integer=0; //Bufer reszultat operaţii I/O
Input: text; //Fişierul standard de intrare
IsConsole: boolean; //Returnează dacă sau nu un modul este o
//aplicaţie consolă
61
Null: variant=nil; //Constantă de tip variant care indică că o variabilă
//variant nu are valoare.
Output: text; //Fişierul output standard
RandSeed: longint; //Sămânţă generator de numere aleatoare
:
Dintre rutinele cele mai mult folosite ale unit-ului System, care pot fi apelate
direct amintim:
ChDir(S);
Schimbare director curent în directorul S.
GetDir(N,S);
Procedura returnează în S directorul curent al unui drive specificat prin
parametrul N. Valorile pentru N sunt:
0 Drive-ul implicit;
1 Drive-ul A
2 Drive-ul B
2 Drive-ul C.
Exemplu:
:
var
s : string;
begin
GetDir(0,s); { 0 = Drive-ul curent }
MessageDlg('Current drive and directory: ' + s, mtInformation, [mbOk] , 0);
end;
:
MkDir(S);
Procedura permite crearea unui director de cale S..
ParamCount
62
Funcţia returnează numărul de parametri transmişi programului prin linia de
comandă.
ParamStr(N);
Funcţia returnează al N-le parametru transmis prin linia de comandă.
Random;
Funcţia returnează un număr pseudoaleator. Fără parametru, funcţia returnează un
număr pseudoaleator cuprins între 0 şi 1. Când este apelată sub forma:
Random(N)
funcţia returnează un număr pseudoaleator cuprins între 0 şi N-1.
Randomize;
Procedura iniţializează generatorul de numere aleatoare cu o valoare aleatoare
dependentă de ceasul sistem.
RmDir(S);
Procedura şterge direcorul specificat prin calea S.
Append(VF);
Procedura deschide un fişier text existent pentru operaţii de adăugare.
AssignFile(VF,FileName);
Procedura permite asignarea unui nume extern de fişier la o variabilă fişier
compatibilă ca tip.
CloseFile(VF);
Procedura închide fişierul deschis referit de variabila VF.
Eof(VF)
Funcţia returnează True dacă pointerul de fişier reperează marcajul de sfârşit de
fişier.
Eoln(VF)
Funcţia returnează True dacă pointerul de prelucrare a unui fişier text detectează
marcajul de sfârşit de linie.
Erase(VF)
Procedura şterge fişierul extren asociat cu variabila VF.
FilePos(VF)
Funcţia returnează poziţia curentă într-un fişier cu tip sau fără fip.
FileSize (VF)
Funcţia returnează numărul de înregistrări într-un fişier Pascal cu tip sau fără tip.
Flush (VF)
Procedura goleşte buffer-ul unui fişier text.
63
IOResult
Funcţia returnează un întreg care codifică rezultatul ultimei operaţii I/O.
Readln (VF,V1,V2,…,Vn)
Procedura permite citirea din fişierul text asociat cu variabila VF a valorilo
variabilelor V1,V2,…,Vn, urmată de retur de car şi salt la linie nouă.
Rutinele:
Rename
Reset
Rewrite
Seek
SeekEof
SeekEoln
SetTextBuf
Truncate
Write
Writeln
au valoarea de întrebuinţare cunoscută de la limbajul Pascal.
AdjustLineBreaks(S)
Funcţie. Returnează sirul S concatenat cu <CR>/<LF> dacă a avut în coadă <CR>
sau <LF> sau secvenţa <LF>/<CR>.
AnsiLowerCase(S)
Funcţie. Returnează şirul ANSI S convertit la litere mici.
64
AnsiUpperCase(S)
Funcţie. Returnează şirul ANSI S convertit la litere mari.
LowerCase(S)
Funcţie. Returnează şirul ASCII S convertit la litere mici.
UpperCase(S)
Funcţie. Returnează şirul ASCII S convertit la litere mari.
Trim(S)
Funcţie. Curăţă şirul S de spaţiile sau caracterele de control care îl preced sau
postced.
TrimLeft(S)
Funcţie. Curăţă şirul S de spaţiile sau caracterele de control care îl preced.
TrimRight(S)
Funcţie. Curăţă şirul S de spaţiile sau caracterele de control care îl postced.
AnsiCompareStr(S1,S2)
Compară ANSI şirurile S1 şi S2 făcând diferenţă între litere mari şi litere mici.
AnsiCompareText(S1,S2)
Compară ANSI şirurile S1 şi S2 fără a face diferenţă între litere mari şi litere
mici.
CreateDir(NumeDirector)
Funcţie. Returnează TRUE dacă s-a creat un director cu numele NumeDirector şi
FALSE în caz contrar.
RemoveDir(NumeDirector)
Funcţie. Returnează TRUE dacă s-a şters directorul cu numele NumeDirector şi
FALSE în caz contrar.
Date
Funcţie. Returnează data curentă.
Now
Funcţie. Returnează data şi ora curentă. Se poate utiliza funcţia DateToStr pentru
a converti valoarea returnată de funcţia Now din format TdateTime în format string.
65
Time
Funcţie. Returnează ora curentă. Se poate utiliza funcţia TimeToStr pentru a
converti valoarea returnată din format TdateTime în format string.
DateTimeToStr(DT)
Funcţie. Converteşte valoarea variabilei DT, de tip TdateTime, la format şir de
caractere.
DateToStr(DT)
Funcţie. Converteşte valoarea variabilei DT de tip TdateTime la şir de caractere.
FormatDateTime(Format,DT)
Funcţie. Returnează ca şir de caractere valoarea variabilei de tip DT, utilizând
formatul specificat.
TimeToStr(DT)
Funcţie. Converteşte valoarea variabilei DT, de tip TdateTime, la şir de caractere.
DeleteFile(FileName)
Funcţie. Returnează True dacă ştergerea fişierului FileName a decurs cu succes.
FileName este nume extern de fişier. Fals în caz contrar.
FileAge(FileName)
Funcţie. Returnează un număr întreg care păstrează informaţii cu privire la vârsta
fişierului. Valoarea returnată poate fi convertită la format TdateTime cu rutina
FileDateToTime. Dacă fişierul nu există, rutina returnează –1.
FileCreate(FileName)
Funcţie. Crează un fişier de nume specificat returnând un întreg, care este handle-
rul fişierului. Rutina este utilizată pentru rezolvarea unor probleme de comunicare cu
Windows API. Nu este recomandată pentru fişiere native Pascal.
FileGetAttr(FileName)
Funcţie. Returnează un întreg care încapsulează atributele fişierului specificat.
FileSetAttr(FileName, NewAttr)
Funcţie. Setează atributele fişierului. Returnează zero în caz de succes.
RenameFile(OldName,NewName)
66
Funcţie. Redenumeşte fişierul de nume OldName. Returnează 0 în caz de succes.
FileExists(FileName)
Funcţie. Returnează True dacă fişierul de nume specificat există.
FileSearch(FileName, DirList)
Funcţie. caută fişierul FileName în lista de directoare DirList. Returnează calea
completă către fişier dacă găseşte fişierul sai stringul vid în caz contrar. FileSearch
function. Lista de directoare este specificată ca în exemplul de mai jos.
FindClose(SearchRec)
Procedură. Termină o secvenţă FindFirst/FindNext.
FindFirst(FileSpec,Attr,Searchrec);
FindNext(Searchrec);
Proceduri. Au aceeaşi valoare de întrebuinţare pe care o aveau înPascal.
ExtractFileName(FileName)
Funcţie. Extrage numele fişierului din specificatorul FileName.
ExtractFilePath(FileName)
Funcţie. Extrage calea către fişierul indicat de specificatorul FileName.
ExtractFileExt(FileName)
Funcţie. Extrage extensia unui fişier indicat de specificatorul FileName.
67
5. Dezvoltarea rapidă a aplicaţiilor în Delphi
5.1 Introducere
Unii specialişti consideră Delphi ca fiind versiunea RAD (Rapid Application
Development) a mediului de programare Borland Pascal. Unul dintre primele lucruri
care trebuie înţelese când se lucrează într-un mediu RAD se referă la faptul că un
mediu RAD este o tehnologie de elaborare a soluţiilor unor probleme de informatică,
bazată be o serie de concepte, componente şi protocoale de utilizarea a acestora. Un
mediu RAD devine cu adevărat puternic în mâinile unui programator dacă acesta ştie:
Să modeleze obiect orientat soluţia unei probleme date;
Să utilizeze suportul Delphi pentru progranmare obiect orientată;
Să utilizeze componentele Delphi în procesul de dezvoltare rapidă de aplicaţii;
Să reutilizeze propriul effort de dezvoltarea rapidă a aplicaţiilor Delphi.
Deprinderea de a modela obiect orientat soluţia unei probleme se formează prin
însuşirea unei metodologii de modelare adecvate şi prin mult exerciţiu în contextul
respectivei metodologii.
Elementele referitoare la suportul Delphi pentru programarea obiect orientată le-
am prezentat în Capitolele 2 şi 3.
În acest capitol voi încerca o incursiune selectivă în ceea ce înseamnă oferta
Delphi de componente şi facilităţi pentru operaţionalizarea paradigmei RAD.
Înainte de a face acest lucru voi încerca să explic cititorului ce se înţelege mai
precis prin sintagma RAD, strâns legată în ingineria softului de ideea de prototipizare.
RELAŢIA RAD-PROTOTIPIZARE
În ingineria softului se numeşte prototip un sistem sau un sistem parţial finisat care
este construit rapid pentru a explora anumite aspecte ale cerinţelor faţă de sistem şi
care nu este considerat sistem gata de livrarea finală la utilizator.
68
Dezvoltarea prototipului este posibilă efectiv doar utilizând instrumente pentru
dezvoltarea rapidă a sistemelor soft (medii vizuale de proiectare, medii vizuale de
programare, etc.).
Când realizăm un prototip putem avea diferite obiective în minte.
Putem construi un prototip pentru a investiga cerinţele utilizator; în acest scop ne
putem focaliza efortul de dezvoltare pe realizarea interfeţei cu utilizatorul pentru a
stabili ce date aşteaptă utilizatorul de la sistem şi ce date furnizează utilizatorul
sistemului.
Prototipul poate fi folosit pentru a determina cel mai adecvat gen de interfaţă.
Putem construi un prototip pentru a stabili dacă o platformă de implementare
anume poate suporta anumite cerinţe de prelucrare.
În sfârşit, un prototip ar putea să urmărească determinarea eficienţei unui limbaj
particular, a unui SGBD sau a unei infrastructuri de comunicaţie.
O perspectivă mai clară asupra proprietăţilor modelului MP putem obţine şi din
Figura 5.1.
Analiza Definire
iniţială obiective
prototip
Specificar
e prototip
Prototip
complet
69
Aşadar, fazele principale necesare pentru a pregăti un prototip sunt:
Specificarea prototipului;
Construirea prototipului;
Specificarea prototipului
Deşi prototipul nu este realizat în perspectiva unor operaţii de extindere este,
evident, important să aibă un comportament scontat. De aceea, este absolut firesc să
luăm în calcul posibilitatea unor modificări care să apropie prototipul cât mai mult de
comportamentul scontat.
Aceste modificări sunt mult mai uşor de făcut dacă softul este realizat potrivit
unor principii de proiectare profunde.
Construirea prototipului
Deoarece este important ca prototipul să fie realizat rapid este firesc ca în această
fază să se apeleze la un mediu de dezvoltare rapidă a plicaţiilor (Delphi, Visual Basic,
Visual C, C-Builder, etc.).
70
Dacă obiectivele nu au fost îndeplinite, evaluarea are drept consecinţă o serie de
modificări care urmăresc apropierea prototipului de obiectivele asumate.
După cum se vede şi din Figura 5.1, ultimele trei faze sunt parcurse ciclic, până
când toate obiectivele asumate de exerciţiul de prototipizare sunt îndeplinite.
În cele ce urmează putem prezenta avantajele acestui model dar şi o serie de
aspecte de care ar trebui să ţinem cont înainte de a ne “aventura” în prototipizare.
Avantaje:
Realizabilitatea şi utilitatea sistemului soft pot fi testate chiar dacă, prin natura
lui, prototipul este incomplet.
Probleme:
Bara meniu
71
Această secţiune este unul dintre cele mai comune elemente ale aplicaţiilor
Windows. În Delphi, bara meniu asigură mecanisme de acces la toate funcţiile IDE
Delphi, precum: instalarea componentelor, setarea mediului şi a opţiunilor de
compilare, crearea de noi forme şi unit-uri, etc. Bara meniu apare imediat sub bara de
titlu a ferestrei principale.
72
13 Trace into Execuţia pas cu pas a programului (inclusiv
instrucţiunile conţinute în subprograme).
Echivalentă cu comanda Run/Trace into
(F7).
14 Step over Execuţia pas cu pas a programului.
Subprogramele apelate sunt execuate într-un
singur pas.
Echivalentă cu comanda Run/Step over (F8).
Paleta de componente
Conţine peste 100 de componente utilizate în dezvoltarea aplicaţiilor, care sunt
organizate în mai multe pagini. Componentele pot fi vizuale (de exemplu butoane,
linii de editare,etc.) sau nevizuale (de exemplu ferestrele standard de dialog, ceasul
sistemului, etc.). O componentă se numeşte vizuală dacă dacă este vizibilă în timpul
execuţiei proiectului în care apare. O componentă se numeşte nevizuală dacă în
timpul proiectării este prezentă ca icoană, iar la execuţia proiectului nu se vede sau
este vizibilă doar dacă este activată prin metode dedicate. Paleta de componente
repartizează componentele în liste astfel:
73
Componentele din această listă permit realizarea legăturilor spre articolele
diferitelor baze de date. Ele sunt componente invizibile (în timpul execuţiei nu sunt
afişate pe ecran). Dintre componentele din această listă semnalăm:
- Componenta DataSource – care realizează legătura între componentele
invizibile Table, Query, StoredProc şi componentele vizibile de acces spre
baze de date (de exemplu TDBGrid).
- Componenta Table – Încarcă date dintr-un tabel, care se transmit, prin
intermediul componentei DataSource) spre componentele vizuale de acces la
baze de date.
- Query – Permite utilizarea diferitelor instrucţiuni SQL.
Inspectorul de obiecte
Inspectorul de obiecte al mediului Delphi este prevăzut cu două pagini. Pagina
Properties permite stabilirea proprietăţilor componentelor în timpul procesului de
proiectare. Pagina Events gestionează diferitele evenimente legate de componentele
aplicaţiei.
La rândul ei, pagina Properties este prevăzută cu două coloane. În coloana din
stânga sunt listate denumirile proprietăţilor. În coloana din dreapta sunt afişate
valorile actuale aferente diverselor proprietăţi. Pentru a atribui o anumită valoare unei
proprietăţi, se efectuiază un click de mouse pe numele proprietăţii. Numele
proprietăţii fiind selectat, atribuirea unei valori la o proprietate poate fi realizată în
trei moduri diferite:
- prin linia de editare aferentă proprietăţii;
- prin lista derulantă corespunzătoare proprietăţii;
- prin intermediul unei ferestre de dialog.
Fereastra formei
74
În procesul de dezvoltare a unei aplicaţii Delphi, forma ocupă un loc central prin
proprietăţile şi evenimentele cu care se poate asocia. Se poate afirma, pe drept cuvânt,
că în jurul conceptului de formă se desfăşoară partea cea mai importantă a
activităţilor specifice unui demers RAD de realizare a unei aplicaţii utilizator.
Pentru descrierea formelor se poate apela, potenţial, la 38 de proprietăţi, care pot
fi stabilite, în perioada de proiectare prin intermediul inspectorului de obiecte, sau
modificate, la nevoie în timpul execuţiei aplicaţiei.
Totodată, formele pot reacţiona la 21 de evenimente. De semnalat faptul că,
majoritatea proprietăţilor şi evenimentelor formelor sunt identice cu proprietăţile şi
evenimentele altor componente importante pentru realizarea aplicaţiilor Delphi.
Acesta este motivul pentru care, vom prezenta, mai jos, cele mai importante
proprietăţi şi evenimente referitoare la forme.
Proprietăţile formelor
Proprietatea ActiveControl
Este utilizată atunci când pe formă au fost aşezate mai multe componente şi se
doreşte specificarea componentei care trebuie să fie în focar în momentul activării
formei sau la un moment dat în timp ce forma este activă. Proprietatea poate fi setată
atât prin intermediul inspectorului de obiecte, în faza de proiectare, cât şi în timpul
execuţiei programului, printr-o atribuire de tipul:
<Variabilă_Formă_gazdă>.ActiveControl:=<Nume_Componentă_focalizată>;
Proprietatea AutoScroll
Este o proprietate de tip boolean care se referă la modul de utilizare a barelor de
defilare ataşate formei. În cazul în care pentru această proprietate se stabileşte
valoarea True, care este şi valoarea implicită, atunci în caz de nevoie, în execuţie
forma va fi prevăzută cu bare de defilare, dacă dimensiunile componentelor
“aşezate” pe formă depăşesc dimensiunile formei. Dacă proprietate este setată la
False, atunci forma nu va mai fi înzestrată automat cu bare de defilare. În acest caz
ataşarea barelor de defilare poate fi realizată prin intermediul proprietăţilor
HorzScrollBar şi VertScrollBar.
Proprietatea BorderIcons
Este o proprietate compusă care se referă la existenţa, în linia de titlu a formei, a
meniului sistem şi a butoanelor de minimizare/maximizare a formei. Această
proprietate este de tip mulţime, valorile posibile fiind:
Valoare Semnificaţie
biSystemMenu Forma este prevăzută cu meniul sistem
biMinimize Forma este prevăzută cu un buton de minimizare
75
biMaximize Forma este prevăzută cu un buton de maximizare
biHelp Dacă proprietatea BorderStyle conţine valoarea
bsDialog sau dacă sunt excluse valorile biMinimize şi
biMaximize, atunci în bara de titlu apare un semn de
întrebare. Dacă se efectuiază un click pe acest semn,
cursorul de mouse va avea forma definită de constanta
crHelp.
Proprietatea BorderStyle
Se referă la stilul chenarului formei. Valorile posibile ale acestei proprietăţi sunt:
Valoare Semnificaţie
bsDialog Chenar neredimensionabil; chenarul standard al
ferestrelor de dialog.
bsSingle Chenar neredimensionabil, desenat cu o linie simplă
bsNone Chenar neredimensionabil, desenat cu linie invizibilă
bsSizeable Chenar redimensionabil standard
bsToolWindows Similar cu bsSingle, dar este prevăzut cu un mic titlu
bsSizeToolWin Similar cu bsSizeable, dar este prevăzut cu un mic titlu
Proprietatea Caption
Este o proprietate de tip string care specifică un şir de caractere care este afişat în
linia de titlu a formei. În cazul componentelor această proprietate desemnează
eticheta ataşată componentei. În acest ultim caz, litera precedată de caracterul “&”
este litera de selecţie a componentei, care va apare subliniată (Componenta poate fi
selectată prin combinaţia Alt+Litera subliniată).
Proprietatea Color
Proprietatea este de tip TColor=longint, stabilind culoarea de fond a formei.
Pentru iniţializarea valorică a acestei proprietăţi pot fi folosite constante predefinite
sau valori returnate de funcţia RGB. Valoarea implicită este clBtnFace . Dacă pentru
proprietatea ParentColor corespunzătoare unei componente se ia valoarea True , şi se
modifică valoarea proprietăţii Color corespunzătoare formei proprietar al
componentei, atunci se va modifica automat şi culoarea componentei.
Proprietatea Ctl3D
Fiind de tip boolean, această proprietate stabileşte aspectul tridimensional al
formei pentru True şi aspect bidimensional pentru False. Valoarea implicită este True.
Dacă pentru proprietatea ParentCtl3D corespunzătoare unei componente se ia
76
valoarea True, şi se modifică valoarea proprietăţii Ctl3D corespunzătoare formei
proprietar al componentei, atunci se va modifica automat şi aspectul componentei.
Proprietatea Cursor
Stabileşte imaginea utilizată pentru reprezentarea cursorului de mouse. Pentru
selectarea unei imagini se vor folosi diferitele constante predefinite asociate. Valoarea
implicită este crDefault.
Proprietatea Enabled
Şi această proprietate este de tip boolean şi se referă la accesibilitatea formei sau
componentei.Dacă proprietatea este setată la True, care este şi valoarea implicită,
atunci forma sau componenta va reacţiona la diferite evenimente pe care este abilitată
să le trateze. Dacă se alege varianta False, forma sau componenta este inhibată.
Valoarea acestei proprietăţi se modifică, de regulă, în timpul execuţiei. Astfel, dacă la
un moment dat, un anumit buton trebuie dezactivat, proprietatea Enabled a acestuia
este setată la False. Evident, la nevoie, componenta dezactivată poate fi reactivată.
Font.Color:=clBlue;
Font.Size:=18;
Font.Style:=[fsBold];
Proprietatea FormStyle
Stabileşte stilul formei. Valorile posibile ale acestei proprietăţi sunt următoarele:
Valoare Semnificaţie
fsNormal Forma crează o fereastră normală (nici MDI copil,
nici MDI părinte). Valoare implicită.
fsMDIChild Forma creează o fereastră MDI copil.
fsMDIForm Forma creează o fereastră MDI părinte.
fsStayOnTop Forma va fi afişată deasupra celorlaltor forme
utilizate în proiect.
Proprietatea Hint
77
Proprietate de tip string, specifică un text explicativ care va fi afişat atunci când
cursorul de mouse este aşezat deasupra unei forme sau componente. Acest text este
afişat numai atunci când proprietatea ShowHint (de tip boolean) este setată la True.
Subproprietate Descriere
Increment Stabileşte distanţa de deplasare a componentei sau imaginii
(O valoare cuprinsă din formă în momentul în care utilizatorul efectuează un
între 1 şi 32767, click pe unul din butoanele ci săgeţi situate în extremităţile
valoarea implicită barelor de defilare.
este 8)
Margin Stabileşte momentul de afişare a barei de defilare.
(De tip word, Această proprietate determină numărul minim de puncte
valoarea implicită 0) care separă componentele formei şi muchia formei. În
execuţie, dacă o componentă ajunge să fie la o distanţă mai
mică decât Margin puncte de la muchie şi dacă proprietatea
Visible este setată la True, atunci se afişează o bară de
defilare.
Position Comunică poziţia curentă a cursorului glisat al barei de
(De tip integer, defilare. Valoarea acestei proprietăţi este actualizată
valoarea implicită 0) automat, în timpul execuţiei aplicaţiei.
Range Dimensiunea maximă de defilare, exprimată în puncte. La
(De tip integer, bara de defilare verticală această valoare trebuie să fie mai
valoarea implicită 0) mare decât valoarea proprietăţii Height (în caz contrar, bara
verticală este invizibilă). La bara de defilare orizontală
această valoare trebuie să fie mai mare decât valoarea
proprietăţii ClientWidth (În caz contrar, bara orizontală este
invizibilă).
Tracking Dacă se alege valoarea True, imaginea / componenta din
(De tip boolean, formă se deplasează împreună cu butonul de glisare tras de
valoarea implicită utilizator. Dacă se alege valoarea False, imaginea rămâne
false) statică cât timp utilizatorul trage butonul de glisare,
adică actualizarea imaginii defilate are loc numai în
momentul eliberării butonului glisant al barei de defilare.
Visible Se referă la vizibilitatea barei de defilare. Dacă se alege
(De tip boolean, valoarea True şi dacă componenta se află la o distanţă mai
valoare implicită mică decât Margin puncte de muchia formei, atunci bara de
True) defilare devine vizibilă.
Proprietatea Icon
Specifică simbolul grafic care va fi utilizat când forma este minimizată.
Proprietatea KeyPreview
78
De tip boolean, se referă la modul de gestiune al evenimentelor referitoare la
tastatură (OnKeyDown, OnKeyPress, OnKeyUp). Dacă pentru această proprietate se
alege valoarea True, atunci evenimentele referitoare la tastatură sunt gestionate de
forma actuală, nu de componentele aşezate pe formă, chiar dacă în momentul
respectiv în focar se află o componentă. Astfel că, dacă, de exemplu, forma conţine
un buton de comandă care este în focar, dacă utilizatorul apasă o tastă, evenimentul
aferent va fi gestionat de procedurile formei, nu de procedurile butonului.
Proprietatea Menu
De tip TmainMenu , stabileşte componenta de tip meniu principal care este
utilizată de formă la un moment dat. În perioada de elaborare a proiectului această
proprietate este iniţializată automat cu prima componentă MainMenu aşezată pe
formă. În timpul execuţiei această valoare poate fi modificată, printr-o instrucţiune de
atribuire, ceea ce înseamnă că o formă poate să folosească mai multe componente
MainMenu.
De analizat şi exemplul de mai jos.
procedure TForm1.SchimbMeniu_1;
begin
Menu:=MainMenu2;
end;
procedure TForm1.SchimbMeniu_2;
begin
Menu:=MainMenu1;
end;
Proprietatea PopupMenu
De tip TPopupMenu, identifică componenta de meniu flotant care este utilizată de
formă la un moment dat. Se menţionează faptul că această proprietate nu este
iniţializată automat cu componenta PopupMenu aşezată pe formă. În execuţie
valoarea acestei proprietăţi poate fi modificată printr-o instrucţiune de atribuire ,
astfel că o formă poate să folosesscă, în funcţie de context, mai multe componente
PoppupMenu.
Proprietatea Name
De tip string, este utilizată pentru atribuirea unui nume( ca variabile obiect) unei
forme sau componente. Atribuirile de nume sunt realizate automat de sistemul
Delphi, însă aceste denumiri predefinite (Form1,Form2,…Button1,Button2,…,etc.),
nu întotdeauna pe gustul oricărui programator, pot fi modificate, codul aplicaţiei
putând fi personalizat şi devenind astfel mai lizibil.Dacă proprietatea Caption nu a
79
fost încă modificată şi dacă se atribuie un nou nume unei forme, atunci proprietatea
Caption va fi modificată automat la noul nume.
Proprietatea ParentFont
De tip boolean, se referă la modul de selecţie al fontului corespunzător unei
componente. Dacă se alege valoarea True , atunci fontul utilizat de o componentă este
identic cu fontul utilizat de forma proprietar. Dacă se alege varianta False, atunci
fontul componentei nu va depinde de fontul formei proprietar (adică proprietatea
Font a componentei este prioritară faţă de proprietatea Font a formei gazdă. Valoarea
implicită a acestei proprietăţi este False.
Proprietatea Position
Se referă la dimensiunea şi locul de plasare a formei în timpul execuţiei, faţă de
dimensiunea şi locul de amplasare care au fost utilizate în timpul proiectării. Valorile
posibile ale acestei proprietăţi sunt următoarele:
Valoare Semnificaţie
poDesigned Dimensiunea şi poziţia formei în execuţie coincid cu
dimensiunea şi poziţia formei utilizată în timpul proiectării.
Valoare implicită.
poDefault Nu se conservă nici dimensiunea, nici poziţia iniţială a
formei; noile valori sunt determinate de sistemul Delphi.
poDefaultPosOnly În execuţie va fi conservată dimensiunea formei, însă
poziţia acesteia va fi stabilită de sistemul Delphi.
poDefaultSizeOnly În execuţie va fi conservată poziţia formei, însă
dimensiunea acesteia va fi stabilită de sistemul Delphi.
poScreenCenter La execuţie se conservă dimensiunea formei, însă aceasta
va fi plasată centrat pe ecran.
Proprietatea PrintScale
Se referă la modul de tipărire a formei, mai precis la modul de alegere a scalei
utilizate în procesul de tipărire. Valorile posibile ale acestei proprietăţi sunt :
Valoare Semnificaţie
poNone Nu se face nici o scalare specială, astfel încât forma tipărită
la imprimantă poate să se deosebeasă de forma afişată pe
ecran
poProporţional Se va utiliza o scală prin care dimensiunea formei tipărite va
fi aprozimativ egală cu dimensiunea formei afişate pe ecran
(WYSIWYG). Valoare implicită.
poPrintToFit Forma este tipărită în aşa fel încât se conservă proporţiile
afişate pe ecran, dar dimensiunea de tipărire este determinată
în aşa fel încât forma va încape pe foaia utilizată.
Proprietatea Scaled
80
De tip boolean, stabileşte modul de dimensionare a formei, în funcţie de
proprietatea PixelsPerInch. Dacă se alege valoarea True, care este şi valoarea
implicită, atunci proprietatea PixelsPerIInch stabileşte numărul de puncte care va
corespunde într-un inch al formei. Dacă se alege valoarea False, atunci valoarea
specificată în proprietatea PixelsPerInch va fi neglijată.
Proprietatea Tag
De tip longint, este utilizată atât în cazul formelor cât şi în cazul componentelor.
Cu ajutorul acestei proprietăţi, se poate adăuga o valoare formelor sau
componentelor. Această proprietate nu are o semnificaţie predefinită, putând fi
utilizată în diverse scopuri de către programatori. Prezentăm , în continuare un
exemplu de utilizare a proprietăţii Tag.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
B:TButton;
implementation
{$R *.DFM}
81
B:=Button2;
end;
end.
Proprietatea Visible
De tip boolean, se referă la vizibilitatea formei. Dacă se alege valoarea True,
forma va fi vizibilă în timpul execuţiei. Dacă se alege valoarea False, forma va fi
invizibilă în timpul execuţiei. Proprietate Visible a unei forme poate primi valoarea
True şi prin intermediul metodelor Show şi ShowModal.
Proprietatea WindowMenu
De tip TMenuItem, este utilizată numai în cazul formelor MDI părinte (al căror
stil este fsMDIForm). Cu ajutorul acestei proprietăţî se desemnează un element de
meniu din linia meniului principal, la care sistemul Delphi va adăuga automat meniul
Window (lista ferestrelor copil deschise în fereastra părinte, cu indicarea ferestrei
active).
Proprietatea WindowState
Se referă la modul de afişare pe ecran a formei. Valorile posibile ale acestei
proprietăţi sunt următoarele:
Valoare Semnificaţie
wsNormal Forma este afişată în stare normală; nici minimizată, nici
maximizată. Valoare implicită.
wsMinimized Forma este afişată în stare minimizată.
wsMaximized Forma este afişată în stare maximizată.
Evenimentul OnActivate
Acest eveniment apare în momentul în care o formă ajunge în focar (De exemplu,
utilizatorul lucrează simultan cu mai multe forme şi efectuiază un click de mouse pe
una dintre ele, ceea ce determină ajungerea respectivei forme în focar). În cazul în
care proiectul conţine o singură formă, în momentul lansării în execuţie a proiectului
82
forma respectivă va fi automat activată. Proceduta ataşată acestui eveniment are
următorul prototip:
Evenimentul OnClick
Se produce atunci când utilizatorul unui program efectuiază un click de mouse pe
o zonă liberă a formei sau pe o componentă care în momentul respectiv este inhibată.
Procedura ataşată acestui eveniment are prototipul următor:
Evenimentul OnDblClick
Apare atunci când utilizatorul efectuiază un dublu click de mouse pe o zonă liberă
a formei sau pe o componentă care în momentul respectiv este inhibată. Procedura
ataşată acestui eveniment are prototipul următor:
Evenimentul OnCloseQuery
Apare în momentul în care utilizatorul este autorul unei acţiuni prin care
semnalează faptul că doreşte să închidă forma. Astfel de acţiuni sunt: apelarea
metodei Close, efectuarea unui click pe butonul de închidere, efectuarea unui dublu
click pe meniul sistem al formei sau apelarea comenzii Close din meniul sistem.
Procedura ataşată acestui eveniment are următorul prototip:
83
evenimentului OnClose. Dacă variabile CanClose i se atribuie valoarea False, forma
nu poate fi închisă.
Evenimentul OnClose
Se produce în momentul în care utilizatorul a cerut închiderea formei. El se
declanşează după evenimentul OnCloseQuery. Procedura ataşată are prototipul:
Parametrul variabil Action stabileşte dacă forma trebuie să fie într-adevăr închisă.
Valorile posibile ale acestui parametru sunt următoarele:
Valoare Semnificaţie
caNone Nu se autorizează închiderea ferestrei
caHide Forma nu este închisă ci doar ascunsă. În continuare
utilizatorul poate să aibă acces la această formă şi poate să
ceară reafişarea formei cu metoda Show. Această valoare
este valoarea implicită în cazul formelor care au stil diferit
de fsMDIChild.
caFree Forma este închisă şi memoria alocată formei este eliberată.
caMinimize Forma nu este închisă, doar minimizată. Această valoare este
valoarea implicită în cazul formelor care au stilul
fsMDIChild.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TForm1 = class(TForm)
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;
84
var
Form1: TForm1;
implementation
{$R *.DFM}
end.
Evenimentul OnCreate
Apare în momentul în care se creează forma (adică la prima execuţie a formei).
De regulă se foloseşte pentru iniţializarea proprietăţilor formei şi a componentelor
aşezate pe aceasta. Procedura ataşată evenimentului OnCreate are următorul prototip:
OnCreate
OnShow
OnActivate
OnPaint
Evenimentul OnDeactivate
85
Apare în momentul în care forma urmează să piardă focarul, altfel spus atunci
când aplicaţia foloseşte mai multe forme şi utilizatorul printr-un click de mouse
activează altă formă. De menţionat faptul că trecerea de la o aplicaţie la alta (nu la o
altă formă a aplicaţiei curente) poate fi prelucrată prin evenimentul OnDeactivate
ataşat obiectelor de tip Tapplication.
Procedura ataşată evenimentului OnDeactivate al formei are prototipul:
Evenimentul OnDestroy
Apare în momentul în care se distruge forma actuală (adică se eliberează toate
resursele ataşate formei). Procedura ataşată acestui eveniment are prototipul următor:
În această procedură se vor distruge toate acele obiecte, care au fost create în
metoda de tratare a evenimentului OnCreate.
Evenimentul OnHide
Apare în momentul în care forma este ascunsă, adică proprietatea de vizibilitate a
formei Visible este iniţializată cu valoarea False. Procedura ataşată acestui eveniment
are următorul prototip:
Evenimentul OnShow
Apare în momentul în care forma este afişată, adică proprietatea de vizibilitate a
formei (Visible) este iniţializată cu valoarea True. Procedura ataşată acestui
eveniment are prototipul următor.
Evenimentul OnPaint
86
Este declanşat în momentul în care unele zone ale formei curente trebuie să fie
redesenate (de exemplu datorită faptului că unele zone ale formei au fost acoperite
temporar de alte ferestre). Procedura ataşată acestui eveniment are prototipul următor:
Evenimentul OnResize
Este declanşat în momentul în care forma a fost redimensionată de utilizator. De
regulă în procedura aferentă acestui eveniment se va realiza reaşezarea şi
redimensionarea componentelor aşezate pe formă. Se menţionează faptul că acest
eveniment este declanşat şi în procesul de creare a formei. Procedura ataşată acestui
eveniment are prototipul:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TForm1 = class(TForm)
87
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
end.
88
mentalitate formată în Pascalul clasic. Este vorba despre obiect orientare şi de
o serie de noutăţi în materie de sintaxă în zona obiect orientată, cu predilecţie.
89
6. Aplicaţii cu baze de date în Delphi
6.1. Introducere
90
Fără a exagera cu formalizarea, un set de date este o colecţie de linii de date,
fiecare linie având mai multe coloane, fiecare coloană fiind omogenă din punct
de vedere al tipului.
În limbaj de specialitate, o coloană se mai numeşte şi câmp iar o linie se mai
numeşte şi înregistrare. Putem spune că setul de date abstractizează un procedeu
de caracterizare informaţională a unei realităţi obiectuale sau de altă natură, ca
o coleţie de date structurate pe linii şi coloane.
VCL Delphi încapsulează un set de date într-o componentă abstractă numită
TDataSet. TDataSet introduce multe dintre proprietăţile şi metodele necesare pentru
manipularea şi navigarea într-un set de date. Pentru mai multă rigoare, noţiunile de
bază cu care se operează în lumea aplicaţiilor Delphi orientate pe baze de date sunt:
91
direct din componenta TDBDataSet care este, la rândul ei, derivată din
TBDEDataSet, având ca strămoş direct TDataSet.
Aşadar:
TDataSet
TBDEDataSet
TDBDataSet
În această ierarhie:
-TDataSet este o componentă abstractă care încapsulează capabilităţile de
management, navigare şi manipulare a dataset-urilor.
-TBDEDataSet este, de asemenea, o componentă abstractă care reprezintă un
dataset specific BDE.
-TDBDataSet introduce concepte precum: database şi sesiune BDE.
-TTable este o componentă care care reprezintă structura şi datele conţinute într-o
tabelă a unei baze de date.
-TQuery este o componentă care reprezintă un set de date returnate în urma unei
înterogări SQL.
-TStoredProc încapsulează o procedură stocată pe un server SQL.
:
Tabel1.Open;
:
92
ceea ce este echivalent cu setarea proprietăţii Active a unui tabel la valoarea True.
:
Tabel1.Active:=True;
Tabel1.Close;
sau
Tabel1.Active:=false;
Table1.First;
while not Table1.EOF do
begin
...
...
Tabel1.Next;
end;
Semne de carte
Semnele de carte permit salvarea poziţiei curente din tabel astfel că, ulterior se
poate reveni rapid în aceeaşi poziţie. Manevrarea semnelor de carte este doar o
problemă de setare/consultare a unei proprietăţi.
:
var
BM:TbookMarkStr;
Begin
93
BM:=Table1.BookMark;
:
Table1.BookMark:=BM;
:
:
var
S:string;
:
S:=Table1['Nume Client'];
Funcţia creează un tablou variant ale cărui limite sunt specificate de Bounds iar tipul
elementelor este specificat de paramatrul varType. Constanta Bounds este un vector
care trebuie să aibă un număr par de elemente, deoarece pentru fiecare dimensiune
trebuie specificată limita inferioară şi limita superioară. VarType este una din valorile
asociate tipurilor recunoscute ca variant mai puţin varArray, varByRef, varString.
Pentru a crea un vector de string-uri se poate folosi codul de tip varOleStr. Dacă
varType este varVariant atunci elementele vectorului sunt variant care pot conţine la
rândul lor alte tipuri variant.
94
Funcţia este folosită pentru a crea un vector unidimensional având tipul de bază
variant iar valorile care populează vectorul sunt specificate în Values.
:
const
Sir=' %s are funcţia %s şi are salariul %f ';
:
var
VarArr:variant;
F:double;
:
begin
VarArr:=VarArrayCreate([0,2],var Variant);
VarArr:=Table1['Nume;Funcţia;Salariul '];
F:=VarArr[2];
ShowMessage(Format(Sir,[VarArr[0],VarArr[1],F));
end;
95
AsString String
AsDataTime TDataTime
Value Variant
:
type
TFieldType=(ftUnknown, ftString, ftSmallint, ftInteger,
ftWord, ftBoolean, ftFloat, ftCurrency, ftBCD,ftDate,
ftTime, ftDateTime, ftBytes, ftVarBytes, ftAutoInc,
ftBlob, ftMemo, ftGraphic, ftFirstMemo, ftParadoxOLE,
ftDBazeOle, ftTypedBinary, ftCursor, ftFixedChar,
ftWideString,...)
:
:
var
S:string;
begin
S:=Table1.Fields[0].FieldName;
end;
:
var
I:integer;
begin
I:=Table1.FieldsByName('Name').FieldNo;
end;
96
Manipularea câmpurilor de date
Există trei paşi în editarea unuia sau a mai multor câmpuri ale înregistrării curente:
1. Apelarea metodei Edit() a unui DataSet pentru a trece un DataSet în modul Edit.
2. Asignarea noilor valori câmpurilor alese printr-o astfel de operaţie.
1. Validarea schimbărilor efectuate asupra DataSet-ului, sau prin apelul metodei
Post() sau prin trecerea la o nouă înregistrare, ceea ce validează automat
rezultatul editării.
:
Table1.Edit;
Table1['Nume']:= 'Corneliu Vadim';
Table1.Post;
:
1.Apelaţi una din metodele Insert() sau Append() ale DataSet-ului pentru a comuta
în modul insert sau append.
3.Validarea unei înregistrări în DataSet prin apelul metodei Post() sau prin trecerea la
o nouă înregistrare, care forţează validarea.
Dacă dintr-un anume motiv, adăugările sau modificările făcute, dar nevalidate,
trebuie abandonate, acest lucru este posibil prin apelul metodei Cancel(), ca mai jos:
:
Table1.Edit;
Table1['Nume']:= 'Corneliu Vadim';
Table1.Cancel;
:
:
Table1.Last;
Table1.Delete;
:
97
pentru a şterge ultima înregistrare din dataset.
Editorul de câmpuri
Delphi oferă un mare grad de control şi flexibilitate asupra câmpurilor unui
DataSet, prin intermediul Editorului de câmpuri.
Cu ajutorul editorului de câmpuri, care poate fi activat din meniul derulant asociat
unui DataSet (de cele mai multe ori tabel) se pot efectua următoarele operaţii:
1.Adăugarea unui câmp nou (prin ştergerea unui câmp existent, păstrarea numelui lui
şi schimbarea tipului).
3.Definirea unui câmp de tip lookup, ale cărui valori se obţin prin relaţionarea tabelei
la care se adaugă câmpul lookup cu o altă tabelă.
4.Activare fereastră de dialog new fields din meniul derulant asociat editorului de
câmpuri.
5.Completare nume câmp în caseta de editare Name asociată. Acest nume trebuie
să
coincidă cu numele câmpului şters.
98
2.Introducerea unui nume pentru câmpul calculat în caseta de editare Name. Se
va evita introducerea unui nume de câmp deja existent în DataSet-ul contextual.
6.Selectaţi OK.
Noul câmp este automat adăugat în lista câmpurilor persistente ale editorului de
câmpuri.
7.Adăugaţi codul care calculează valorile pentru câmpul calculat. Acest cod se
asociază evenimentului OnCalcFields al DataSet-ului.
De remarcat, totodată, că pentru a edita proprietăţile sau evenimentele asociate
unui câmp, selectaţi numele câmpului în lista editorului de câmpuri şi, vă puteţi folosi
de inspectorul de obiecte, ca de obicei.
TBlobType=ftBlob..ftOraClob;
99
Tip câmp Tipul de dată
ftBlob Dată fără tip sau definită de utilizator
ftMemo Text
ftGraphic Bitmap Windows
ftFmtMemo memo formatat Paradox
ftParadoxOle object OLE Paradox
ftDbase Ole object OLE DBase
ftTypedBinary
Reîmprospătare Dataset
DataSet-ul abstractizează de cele mai multe ori un tabel. În momentul în care un
dataset se cuplează la o tabelă (în urma unei operaţii de tip Open(), DataSet-ul se
comportă ca un flux în care adaugăm înregistrări, din care ştergem înregistrări sau în
care modificăm înregistrări. Din diverse motive, conţinutul DataSet-ului trebuie pus
de acord, din când în când cu conţinutul tabelei asociate.
În acest scop se foloseşte metoda Refresh().
100
Filtre
Filtrele permit programatorilor să efectueze căutări sau filtrări asociate cu un
DataSet, utilizând numai cod Object Pascal. Principalul avantaj al utilizării filtrelor
constă în faptul că nu sunt necesare fişiere index sau alte pregătiri ale DataSet-urilor
de acest gen.
Filtrele pot fi mai lente decât căutarea bazată pe indexare, dar sunt încă mult
folosite în o serie de aplicaţii, fie şi numai din motive de simplificare a portării unei
aplicaţii.
In acest cod s-a definit un filtru care permite prelucrarea doar a înregistrărilor din
tabelă pentru care câmpul ”Compania” începe cu “S”.
101
function Locate(const KeyFields:string; const KeyValue:Variant; Options:
TLocateOptions): boolean;
.
.
type
TLocateOption = (loCaseInsensitive, loPartialKey);
TLocateOptions = set of TLocateOption;
.
.
Căutarea înregistrărilor
Dacă aveţi nevoie să căutaţi înregistrări într-un tabel, VCL furnizează câteva
metode de ajutor în acest caz
Dacă lucraţi cu tabele dBase sau Paradox, Delphi presupune că tabelele sunt
indexate după câmpurile implicate în procesul de căutare. În deosebi în cazul
tabelelor SQL, performanţa procesului de căutare va avea de suferit dacă fişierele în
care căutăm nu sunt indexate.
Pentru căutare putem folosi:
tehnica FindKey()
sau
tehnica SetKey()..GotoKey().
102
Metoda FindKey() permite căutarea unei înregistrări după unul sau mai multe
câmpuri cheie. FindKey() acceptă ca parametru un vector de constante (reprezentând
criteriul de căutare) şi returnează True în caz de reuşită a procesului de căutare.
Exemplu:
.
.
if not Table1.FindKey([123,’Ionescu Victor’])
then MessageBeep(0);
.
.
Codul de mai sus determină poziţionarea în DataSet pe înregistrarea pentru care
primul câmp-index are valoarea 123 iar al doilea câmp-index are valoarea ‘Ionescu
Victor’.
SetKey()..GotoKey()
Apelarea metodei SetKey() trece tabelul într-un mod care pregăteşte câmpurile lui
pentru a fi încărcate cu valori reprezentând criterii de căutare. Odată ce criteriul de
căutare a fost stabilit se foloseşte metoda GotoKey() pentrua face o căutare top-down
a unei înregistrări specificate în criteriul de căutare. În varianta SetKey()..GotoKey()
exemplul precedent se scrie:
.
.
with Table1 do
begin
SetKey;
Fields[0].AsInteger:=123;
Fields[1].AsString:=’Ionescu Victor’;
if not GotoKey then MessageBeep(0);
end;
.
103
.
.
AssignFile(VFText,’Fişier.txt’);
.
.
5. Închiderea fişierului:
CloseFile(VFText).
.
.
type
.
.
TPersonRecord=packed record
Nume:string[20];
Iniţiala:string[3];
Prenume:string[20];
DataNaşterii:TdateTime;
end;
.
.
104
.
.
sau
.
.
var
IPersRec:TPersonRecord;
VFTip:Tfile;
begin
AssignFile(VFTip,’Persoana.dat’);
Reset(VFTip);
Seek(VFTip, FileSize(VFTip));
try
write(VFTip, IPersRec);
finally
CloseFile(VFTip);
end;
end;
105
Utilizând TFileStream se poate realiza foarte uşor un browser
specializat pe un anumit tip de înregistrare.
De fapt TFileStream abstractizează noţiunea de fişier cu tip în ideea de a
simplifica efortul de programare depus pentru gestionarea datelor păstrate într-un
fişier cu o structură oarecare.
O instanţă a clasei TFileStream este creată cu ajutorul constructorului Create,
care are sintaxa:
Aşadar, la crearea unei instanţe de tip TFile Stream trebuie să specificăm numele
fişierului asociat şi modul de operare asupra acestuia. Consultaţi help-ul Delphi
pentru a vedea valorile posibile pentru parametrul Mode şi semnificaţia acestora. Tot
cu ajutorul help-ului se poate învăţa sintaxa metodelor cu ajutorul cărora se fac citiri,
scrieri poziţionări în fişiere asociate cu o instanţă TFile Stream. Protocolul de lucru
cu instanţe TFileStream poate fi urmărit şi în exemplul de mai jos.
{
Exemplu de cod Object Pascal care ilustreaza utilizarea
tipului TFileStream
}
unit persrec;
interface
uses Classes, dialogs, sysutils;
type
TRecordStream = class(TFileStream)
private
function GetNumRecs: Longint;
function GetCurRec: Longint;
procedure SetCurRec(RecNo: Longint);
106
protected
function GetRecSize: Longint; virtual;
public
function SeekRec(RecNo: Longint; Origin: Word):
Longint;
function WriteRec(const Rec): Longint;
function AppendRec(const Rec): Longint;
function ReadRec(var Rec): Longint;
procedure First;
procedure Last;
procedure NextRec;
procedure PreviousRec;
// NumRecs arata numarul de inregistrari in stream
property NumRecs: Longint read GetNumRecs;
// CurRec arata inregistrarea curenta in stream
property CurRec: Longint read GetCurRec write
SetCurRec;
end;
implementation
function TRecordStream.GetRecSize:Longint;
begin
{ Returneaza lungimea in octeti a unei inregistrari de
tip
TpersonRec din stream}
Result := SizeOf(TPersonRec);
end;
107
function TRecordStream.SeekRec(RecNo: Longint; Origin:
Word):
Longint;
begin
Result := Seek(RecNo * GetRecSize, Origin);
end;
procedure TRecordStream.First;
begin
//Pozitionarea la inceput in stream
Seek(0, 0);
end;
procedure TRecordStream.Last;
begin
// Pozitionarea pe ultima inregistrare din stream
Seek(0, 2);
Seek(-GetRecSize, 1);
end;
procedure TRecordStream.NextRec;
begin
if ((Position + GetRecSize) div GetRecSize) =
GetNumRecs then
raise Exception.Create('Cannot read beyond end of
file')
else
108
Seek(GetRecSize, 1);
end;
procedure TRecordStream.PreviousRec;
begin
if (Position - GetRecSize >= 0) then
Seek(-GetRecSize, 1)
else
Raise Exception.Create('Cannot read beyond beginning
of
the file.');
end;
end.
.
.
var VFFărăTip:File;
sau
{pentru operaţii de citire / scriere atunci când fişierul nu există ; dacă fişierul
există
atunci este vidat la deschidere}
.
Rewrite(VFFărăTip[,<RecSize.]);
.
.
109
Pentru scrierea datelor într-un fişier fără tip avem procedura:
.
.
procedure BlockWrite(var F:File; var Buf;
const:Integer[; var Result:Integer]);
.
.
Dimensiunea implicită a blocului elementar de transfer: 128.
Consultaţi help-ul sau [6] pentru a vedea cum se lucrează profesional cu fişierele,
structurile de tip directoare şi drive-urile în Object Pascal. Consultaţi, de asemenea,
paragraful 4 al acestui suport de curs pentru a afla mai multe despre capabilităţile
Delphi relativ la lucru cu fişiere şi directoare.
110
Când va fi cazul, important este să ştim de unde să începem demersul de
soluţionare a unei probleme, care necesită mai mult decât ştim la un moment dat
despre un anume univers.
Bibliografie minimală
1. Blaga, A., Ultima provocare Borland Delphi, Editura Promedia Plus, 1998
2. Kovacs, S., Delphi 3.0 Ghid de utilizare, Editura Albastră, 1998
3. Miller, T., Powell, D., ş.a., Ghid de referinţă complet Delphi 3, Editura
Teora, 1998
4. Norton, P., Ghid complet pentru Delphi 2, Editura Teora, 1997
5. Oltean, M., Programarea avansată în Delphi, Editura Albastră, 1999
6. Teixeira, S., Pacheco, X., Delphi 5 Developer’s Guide, SAMS Publishing,
2000
111
Propuneri de teme pentru proiecte la disciplina
Metode evoluate de programare
Tema nr. 1
Să se realizeze o aplicaţie Delphi care asistă învăţarea matematicii de
gimnaziu. Se vor lua în considerare următoarele cerinţe:
Tema nr. 2
Să se realizeze o aplicaţie Delphi care gestionează fluxurile
informaţionale ale unei familii. Exemple de activităţi ale unei familii care
ar putea prezenta interes din apunct de vedere al analizei informaţionale:
gestiunea veniturilor şi a cheltuielilor, gestiunea împrumuturilor(cărţi,
casete video, etc.), gestiunea mijloacelor fixe (cărţi, casete video, alte
obiecte), planificarea activităţilor zilnice, săptămânale, lunare, etc., date
despre cunoştinţele apropiate sau cu care există relaţii de diferite tipuri,
etc.
Sunt valabile şi pentru această temă cerinţele:
112
Tema nr. 3
Să se realizeze o aplicaţie Delphi care modelează ideea de dicţionar
explicativ enciclopedic. Aplicaţia trebuie să permită:
• Încărcarea dicţionarului cu date
• Consultarea polivalentă a dicţionarului
În afară de explicaţiile asociate cuvintelor, dicţionarul trebuie să poată
conţine şi obiecte grafice, la care se fac referire din textele explicative
asociate cuvintelor.
Alte idei sunt binevenite.
Sunt valabile şi pentru această temă cerinţele:
113
Toate aceste „piese” vor fi realizate în format
electronic şi, opţional, listate pe format A4 şi
îndosariate!!
114