Sunteți pe pagina 1din 27

Controale

5. Controale

Un control reprezintă un obiect care are o componentă grafică. Un control este situat pe un
formular (o fereastră) și interacționează cu utilizatorul, furnizând informații pe care utiliza-
torul le poate utiliza. Exemple de controale sunt casetele text, etichetele, butoanele, listele
derulante, elementele de meniu, barele cu instrumente și, în general, tot ceea ce se poate
vedea și cu care se poate interacționa într-o aplicație Windows.
O componentă este similară unui control, cu diferența că nu are nicio componentă vizuală în
timpul rulării. Atunci când adăugați o componentă pe un formular (în modul design), aceasta
nu apare pe suprafața formularului, ci în component tray, situată sub formular (Figura 5.1).
Puteți să selectați componentele, apoi să utilizați panoul de proprietăți pentru a le vizualiza
și modifica proprietățile. În timpul rulării componentele sunt invizibile utilizatorului, deși
acestea pot afișa unele obiecte vizibile cum ar fi meniuri, ferestre dialog sau pictograme.

Figura 5.1. Componentele sunt plasate în component tray.

Figura 5.2 prezintă toolbox-ul asociat cu Visual C#, care afișează o gamă standard de 67 de
controale și componente. Săgeata (arrow tool) din colțul stânga sus nu reprezintă practic un
control sau o componentă, ci instrumentul de selecție.

97
Medii și Tehnologii de Programare – curs

Figura 5.2. Visual C# oferă o gamă largă de controale și componente.

În continuare vor fi descrise diversele tipuri de controale și componente și va fi explicat


modul în care aplicațiile le pot utiliza în modul design și în timpul rulării pentru a furniza
informații utilizatorilor și pentru a permite acestora să controleze aplicația. Va fi explicat de
asemenea modul în care puteți lucra cu proprietățile, metodele și evenimentele furnizate de
clasa Control. Alte controale derivate din această clasă moștenesc modul de utilizare a
acestor proprietăți, metode și evenimente în afara cazului în care acestea sunt supraîncăr-
cate.

5.1. Programarea orientată pe evenimente


Programarea orientată pe evenimente (programarea condusă de evenimente) este o paradig-
mă a programării calculatoarelor. Spre deosebire de programele tradiționale, care își urmea-
ză propriul flux de instrucțiuni, schimbându-și cursul numai în puncte de ramificație
(instrucțiuni de testare etc.), cursul execuției unui program orientat pe evenimente este
condus în mare parte de evenimente externe.
Programele orientate pe evenimente sunt formate de obicei dintr-un număr de secvențe de
cod numite proceduri eveniment (event handlers), care sunt apelate de către un coordonator
(dispatcher) ca răspuns la evenimente externe. Acesta apelează procedurile eveniment,
folosind de obicei o coadă de așteptare a evenimentelor, care reține evenimentele ce
așteaptă să fie procesate (Figura 5.3). În multe cazuri, procedurile eveniment pot declanșa la
rândul lor alte evenimente, provocând astfel o cascadă de evenimente.

98
Controale

Figura 5.3. Tratarea mesajelor de către o aplicație Windows

Aplicațiile cu interfețe grafice sunt de obicei programate astfel încât sunt conduse de
evenimente. Sistemele de operare sunt un alt exemplu clasic de programe conduse de
evenimente pe cel puțin două nivele. La cel mai de jos nivel, handlerele de întreruperi se
comportă ca handlere de evenimente hardware, cu procesorul în rol de coordonator
(dispatcher). Sistemele de operare se comportă, de asemenea, ca și coordonatori pentru
procese, transmițând datele și întreruperile soft către procese utilizator, care de multe ori
sunt programate ca și handlere de eveniment.

5.2. Controale și componente


Majoritatea controalelor sunt grafice prin natura lor. Butoanele, casetele text și etichetele
furnizează în mod grafic intrări și feedback pentru utilizatori. Acestea afișează date și permit
utilizatorului să comande prin intermediul acestora programul.
Atât controalele cât și componentele pot fi create în modul design sau în timpul rulării.
Prima variantă este mai comodă și permite modificarea aspectului și a proprietăților contro-
lului sau a componentei fără a necesita scrierea de cod. Totuși, pot exista situații în care este
mai utilă crearea controalelor în timpul rulării prin scrierea de cod. De exemplu, dacă nu știți
de câte casete text veți avea nevoie în timpul rulării aplicației, nu puteți să le creați în modul
design.
Unele controale pot conține la rândul lor alte controale. De exemplu, controalele GroupBox și
Panel pot găzdui alte controale. Acestea se numesc controale container.

99
Medii și Tehnologii de Programare – curs

5.2.1. Crearea și distrugerea controalelor


În mod normal veți adăuga controale pe un formular în modul design. Totuși, uneori este
mult mai convenabil să creați controale noi în timpul rulării. De exemplu, poate vreți să
afișați interfețe diferite pentru fiecare utilizator al unei aplicații (în funcție de gradul de
autorizare al fiecărui utilizator).
Următorul cod arată modul în care un program poate crea un control nou de tip Label. Întâi
se creează un obiect nou de tip Label, inițializat prin folosirea cuvântului cheie new, i se
setează proprietățile dorite, iar în final controlul este adăugat la colecția de controale a
formularului curent.
Label lbl = new Label();
lbl.SetBounds(100, 100, 50, 16);
lbl.Text = "Eticheta";
this.Controls.Add(lbl);

De obicei, un control etichetă are doar rol de afișare a unui text, astfel că nu vă veți folosi de
evenimentele acestuia. În schimb, alte controale, cum ar fi butoanele sau barele de derulare,
nu ne vor fi de mare folos dacă programul nu poate răspunde la evenimentele lor. De
exemplu, doriți să creați pe un formular câte un buton pentru fiecare fișier dintr-un director,
iar la click pe un buton să se deschidă fișierul asociat. Dacă nu cunoașteți dinainte numărul
de fișiere din director, nu veți ști de câte controale veți avea nevoie.
O soluție la această problemă este utilizarea operatorului += care vă permite adăugarea unei
proceduri eveniment pentru un control sau componentă. Următoarea secvență de cod
ilustrează acest mod de lucru:
private void Form1_Load(object sender, EventArgs e)
{
Button btn = new Button();
btn.SetBounds(100, 100, 50, 32);
btn.Text = "Mesaj";
this.Controls.Add(btn);
btn.Click += btn_Click;
}

// handlerul de eveniment generat automat


void btn_Click(object sender, EventArgs e)
{
throw new NotImplementedException();
}

Atunci când scrieți cod pentru adăugarea unei noi proceduri eveniment folosind operatorul
+=, mediul Visual Studio vă propune, la apăsarea tastei TAB, în prima etapă asocierea
evenimentului în cauză cu o procedură eveniment (având numele compus din numele
controlului și al evenimentului: numeControl_numeEveniment), apoi crearea efectivă a proce-
durii eveniment respective (vezi Figura 5.4).

Figura 5.4. Oferirea de ajutor din partea Visual Studio pentru inserarea unei proceduri eveniment

Puteți utiliza aceeași metodă ca procedură eveniment pentru mai multe controale, de
exemplu butoane. În acest caz, codul poate converti parametrul sender într-un obiect buton,
putând astfel să determinați prin proprietățile Name sau Text butonul care a fost apăsat.
Pentru a șterge un control de pe un formular ștergeți-l din colecția de controale asociată
formularului. Pentru eliberarea resurselor asociate controlului în cauză, setați orice variabilă
care se referă la acesta la valoarea null. Iată un exemplu:
this.Controls.Remove(btn);
btn = null;

100
Controale

În acest mod puteți să ștergeți atât controalele create dinamic, cât și pe cele create în modul
design. De asemenea, puteți să ștergeți asocierea dintre evenimentul unui control și o
procedură eveniment, prin utilizarea operatorului -=, precum puteți vedea în exemplul de
mai jos:
btn.Click -= btn_Click;

5.2.2. Proprietăți ale controalelor


O proprietate reprezintă o valoare asociată unui control. Adesea, o proprietate corespunde în
mod evident unei caracteristici vizuale a controlului. De exemplu, proprietatea Text
reprezintă textul afișat de către control, BackColor reprezintă culoarea de fundal a
controlului, Top și Left indică poziția controlului ș.a.m.d.
Puteți manipula proprietățile unui control atât în modul design cât și în timpul rulării.

Proprietăți în modul design


Pentru modificarea proprietăților unui control în modul design deschideți formularul în
Form Designer și selectați controlul printr-un click. Fereastra de proprietăți va afișa pro-
prietățile controlului. Puteți observa în Figura 5.5 fereastra de proprietăți asociată unui
control de tip buton. Proprietatea Text are valoarea “Sterge”, iar proprietatea TextAlign (care
determină amplasarea textului pe buton) este setată la valoarea MiddleCenter.
Lista derulantă (controlul ComboBox) din partea superioară a ferestrei de proprietăți indică
faptul că acest control se numește button1 și este de tip System.Windows.Forms.Button.

Figura 5.5. Fereastra de proprietăți vă permite modificarea proprietăților unui control în modul design.

Proprietăți compuse
Doar câteva proprietăți au valori compuse. Proprietatea Location include coordonatele X și Y
ale colțului stânga-sus al controlului. Proprietatea Size conține lățimea și înălțimea controlu-
lui. Proprietatea Font include numele fontului, dimensiunea acestuia și alte caracteristici
specifice fonturilor (bold, italic etc.).
Fereastra de proprietăți afișează aceste proprietăți cu un semn plus („+”) în stânga acestora,
prin intermediul căruia puteți desfășura proprietățile respective. Figura 5.6 afișează aceeași
fereastră de proprietăți ca cea din Figura 5.5, însă cu proprietățile Font și Location
desfășurate.

101
Medii și Tehnologii de Programare – curs

Puteți modifica toate caracteristicile unei proprietăți compuse prin intermediul unei ferestre
dialog afișate la click pe butonul situat în partea dreaptă a proprietății compuse. De exemplu,
pentru proprietatea Font va fi afișată fereastra dialog din Figura 5.7.

Figura 5.6. Fereastra de proprietăți vă permite modificarea proprietăților complexe în modul design.

Figura 5.7. Fereastra dialog care vă permite modificarea caracteristicilor unui font.

Proprietăți restrictive
Unele proprietăți permit valori restrictive. De exemplu, proprietatea Visible poate primi
numai valorile true sau false. Dacă dați click pe o asemenea proprietate, vă va fi afișată o listă
derulantă din care puteți alege una dintre valorile permise pentru acea proprietate.

102
Controale

Alte proprietăți restrictive au asociate valori de tip enumerare. Proprietatea FlatStyle a unui
buton permite selectarea valorilor Flat, Popup, Standard și System. Puteți da dublu click pe
valoarea unei proprietăți restrictive pentru ciclarea valorilor posibile pe care le poate lua
acea proprietate.
Unele proprietăți pot conține referințe la alte controale. De exemplu, proprietatea ImageList
reprezintă o referință la o componentă ImageList care conține imaginile pe care controlul le
poate afișa.
În fine, alte proprietăți restrictive pot afișa diferite editoare care permit introducerea în mod
grafic a valorilor unei proprietăți. Un astfel de exemplu este proprietatea Anchor, care
permite „ancorarea” marginilor unui control la marginile containerului, astfel încât controlul
își păstrează poziția relativă în cazul redimensionării containerului.

Proprietăți colecție
Unele proprietăți reprezintă colecții de obiecte. De exemplu, un control de tip ListBox
afișează o listă de elemente text. Proprietatea Items a acestuia reprezintă o colecție ce
conține acele elemente. Inițial, fereastra de proprietăți afișează valoarea acestei proprietăți
ca și “(Collection).” La apăsarea butonului din dreapta proprietății de tip colecție va apărea o
fereastră dialog în care puteți edita elementele colecției.
Alte proprietăți pot conține o colecție de obiecte care, la rândul lor, să conțină o colecție de
obiecte. De exemplu, controlul ListView are proprietatea Items care reprezintă o colecție de
elemente de tip ListViewItem. Fiecare element din colecție reprezintă un obiect care are o
proprietate SubItems, care la rândul ei este o colecție (Figura 5.8). La afișarea controlului în
mod detaliat, un obiect din colecția Items reprezintă un rând din afișarea tabelară, iar
proprietatea SubItems reprezintă valorile secundare de pe acel rând.

Figura 5.8. Obiectele din colecția Items a controlului ListView au fiecare câte o proprietate SubItems, care
reprezintă de asemenea o colecție.

Accesarea proprietăților în timpul rulării


Visual C# permite setarea majorității proprietăților controalelor în modul design, însă
adeseori aveți nevoie să le modificați în timpul rulării.

103
Medii și Tehnologii de Programare – curs

O proprietate poate fi văzută ca orice membru public al obiectului de tip control, putând să o
accesați prin numele controlului urmat de caracterul punct și de numele proprietății. Dacă o
proprietate conține o referință la un obiect, puteți utiliza proprietățile acelui obiect folosind
aceeași sintaxă:
if (textBox1.Font.Bold)
MessageBox.Show("Bold");
else
MessageBox.Show("Not bold");

Dacă o proprietate reprezintă o colecție sau un vector, puteți să parcurgeți într-o buclă
valorile din colecție la fel cum parcurgeți o colecție sau un vector:
foreach (Object selected_item in lstChoices.SelectedItems())
Debug.WriteLine(selected_item.ToString());

Rețineți faptul că unele proprietăți ale controalelor sunt read-only, astfel că nu veți putea să
le modificați. Un astfel de exemplu este proprietatea Bottom care este calculată automat în
funcție de alte două proprietăți:
control.Bottom = control.Top + control.Height;

Proprietăți utile ale controalelor


În Tabelul 5.9 sunt prezentate succint proprietățile implementate de clasa Control. Toate
controalele care moștenesc clasa Control moștenesc și aceste proprietăți, dacă nu cumva
supraîncarcă comportamentul clasei Control.
Proprietate Descriere
AllowDrop Determină dacă controlul permite operații drag-and-drop.
Anchor Determină care dintre marginile controlului sunt ancorate de marginile
controlului container.
AutoSize Determină dacă controlul se redimensionează automat în funcție de
conținutul acestuia.
BackColor Determină culoarea de fundal a controlului.
BackgroundImage Determină imaginea de fundal a controlului.
BackgroundImageLayout Determină modul în care este utilizată imaginea de fundal a controlului.
Bottom Returnează distanța dintre marginea de sus a controlului container și
marginea de jos a controlului. Proprietatea este read-only. Modificați
proprietățile Top și Height pentru modificarea valorii acesteia.
Bounds Determină dimensiunile și locația controlului.
CanFocus Determină dacă controlul poate primi focalizarea.
CanSelect Determină dacă controlul poate selecta. De exemplu, un TextBox poate
selecta o parte sau tot conținutul text.
Capture Determină dacă controlul a captat mouse-ul.
CausesValidation Determină dacă controlul validează alte controale atunci când primește
focalizarea.
ClientRectangle Această structură de tip Rectangle reprezintă suprafața client a
controlului.
ClientSize Această structură de tip Size reprezintă înălțimea și lățimea controlului.
ContainsFocus Indică dacă controlul sau unul dintre controalele conținute de acesta a
primit focalizarea. Este read-only.
ContextMenu Determină meniul context asociat cu controlul.
ContextMenuStrip Determină banda de meniu context asociat cu controlul.
Controls Această colecție conține referințe la controalele conținute de acest
control.
Cursor Determină cursorul pe care îl va afișa controlul atunci când mouse-ul
este deasupra lui.

104
Controale

DataBindings Returnează DataBindings asociat cu controlul, utilizat pentru legarea


controlului la o sursă de date.
DefaultBackColor Returnează culoarea de fundal implicită a controlului.
DefaultFont Returnează fontul implicit al controlului.
DefaultForeColor Returnează culoarea de desenare implicită pe suprafața controlului.
DisplayRectangle Returnează o structură Rectangle care conține suprafața afișată a
controlului.
Dock Determină marginile controlului părinte la care controlul va fi andocat.
Enabled Determină dacă controlul va interacționa cu utilizatorul.
Focused Indică dacă controlul are focalizarea. Este read-only.
Font Determină fontul asociat controlului.
ForeColor Determină culoarea de desenare pe suprafața controlului.
Handle Returnează handle-ul ferestrei controlului. Este read-only.
HasChildren Indică dacă controlul conține alte controale. Este read-only.
Height Determină înălțimea controlului.
InvokeRequired Returnează true dacă codul apelant rulează pe un fir de execuție diferit
de firul de execuție al controlului și, ca urmare, trebuie utilizată o
metodă invoke pentru a putea interacționa cu controlul.
Left Determină coordonata X a marginii din stânga a controlului.
Location Această structură Point determină poziția colțului stânga-sus a
controlului.
Margin Determină spațiul dintre acest control și marginea altui control din
cadrul unui container.
MaximumSize Determină dimensiunea maximă permisă pentru acest control.
MinimumSize Determină dimensiunea minimă permisă pentru acest control.
ModifierKeys Indică ce taste speciale (Shift, Ctrl, Alt) sunt apăsate. Este read-only.
MouseButtons Indică ce butoane de mouse (stânga, dreapta, mijloc, nici unul) sunt
apăsate. Este read-only.
MousePosition Returnează o structură Point care returnează poziția curentă a mouse-
ului (punctul (0, 0) este situat în colțul stânga-sus al ecranului). Este
read-only.
Name Determină numele controlului.
Padding Determină spațierea conținutului controlului.
Parent Determină părintele care conține controlul.
PreferredSize Returnează o dimensiune care este suficient de mare pentru a cuprinde
conținutul controlului.
Region Determină regiunea ferestrei controlului. Aceasta reprezintă suprafața în
care controlul poate desena.
Right Returnează distanța dintre marginea din stânga a controlului container
și marginea din dreapta a controlului. Este read-only. Modificați
proprietățile Left și Width pentru modificarea acestei valori.
Size Această structură Size determină dimensiunea controlului incluzând
suprafețele client și non-client.
TabIndex Determină poziția controlului în cadrul ordinii de selectare a
containerului său. Dacă mai multe controale au același TabIndex,
acestea sunt parcurse din față în spate conform cu ordinea lor de
suprapunere (pe axa Z).
TabStop Determină dacă utilizatorul poate selecta controlul prin apăsarea
succesivă a tastei TAB.
Tag Această proprietate poate conține un obiect pe care doriți să îl asociați
cu controlul.
Text Determină textul afișat de control.
Top Determină coordonata Y a marginii de sus a controlului.

105
Medii și Tehnologii de Programare – curs

TopLevelControl Returnează cel mai de sus ascendent al controlului. De obicei este cea
mai din afară fereastră care conține controlul. Este read-only.
Visible Determină dacă controlul este vizibil.
Width Determină lățimea controlului.

Tabelul 5.9. Proprietăți specifice clasei Control

5.2.3. Metode
O metodă execută cod asociat cu un control. Metodele pot primi parametri la fel ca orice altă
funcție. Deoarece metodele execută cod, nu le puteți apela în modul design, ci puteți să le
apelați numai prin cod, în timpul rulării.

Metode utile ale controalelor


Tabelul 5.10 prezintă succint metode utile implementate de clasa Control. Toate controalele
care moștenesc clasa Control moștenesc și aceste metode, dacă nu supraîncarcă comporta-
mentul clasei Control.
Metoda Descriere
void BringToFront () Aduce controlul în fața celorlalte controale (pe axa Z).
bool Contains (Control ctl) Returnează true dacă controlul ctl este conținut de acest
control.
Graphics CreateGraphics() Creează un obiect Graphics pe care îl puteți utiliza pentru
desenare pe suprafața controlului.
DragDropEffects DoDragDrop Inițiază o operație drag-and-drop.
(Object data, DragDropEffects
allowedEffects)
void DrawToBitmap(Bitmap bitmap, Desenează o imagine a controlului (inclusiv controalele
Rectangle targetBounds) conținute) în obiectul Bitmap în suprafața indicată de
Rectangle.
Form FindForm () Returnează formularul care conține controlul.
bool Focus () Dă controlului focalizarea.
Control GetChildAtPoint (Point pt) Returnează controlul fiu care conține punctul indicat. Dacă
mai multe controale conțin punctul, este returnat controlul cel
mai de sus pe axa Z.
Control GetNextControl(Control ctl, Dacă forward este true, returnează următorul control în
bool forward) ordinea de selectare a fiului acestui control după controlul ctl.
Dacă forward este false, returnează controlul anterior din lista
de selectare. Setați ctl = null pentru a porni de la
început/sfârșit. Returnează null când ajungeți la
început/sfârșit.
Size GetPreferredSize (Size Returnează dimensiunea unei suprafețe dreptunghiulare în
proposedSize) care poate să încapă controlul.
Type GetType () Returnează un obiect Type care reprezintă clasa asociată cu
controlul. Puteți utiliza acest obiect pentru a obține informații
despre clasă.
void Hide () Ascunde controlul prin setarea proprietății Visible pe false.
void Invalidate () Invalidează întreaga suprafață a controlului și forțează
redesenarea acestuia (apare evenimentul Paint).
Object Invoke (Delegate method) Execută delegatul specificat pe firul de execuție care deține
controlul.
Point PointToClient (Point p) Convertește punctul p din coordonate ecran în sistemul de
coordonate a controlului.

106
Controale

Point PointToScreen (Point p) Convertește punctul p din coordonatele controlului în


sistemul de coordonate al ecranului.
Rectangle RectangleToClient Convertește dreptunghiul r din coordonate ecran în sistemul
(Rectangle r) de coordonate a controlului.
Rectangle RectangleToScreen Convertește dreptunghiul r din coordonatele controlului în
(Rectangle r) sistemul de coordonate al ecranului.
void Refresh () Forțează controlul să își invalideze suprafața client și imediat
după aceea controlul se redesenează pe el și controalele
conținute.
void Scale (SizeF factor) Scalează controlul și controale conținute cu factorul de scalare
specificat.
void Select () Mută focalizarea asupra controlului. Unele controale au
versiuni supraîncărcate.
bool SelectNextControl(Control ctl, Mută focalizarea asupra următorului control conținut
bool forward, bool tabStopOnly, împreună cu acesta.
bool nested, bool wrap)
void SendToBack() Trimite controlul în poziția cea mai din spate pe axa Z.
void SetBounds (int x, int y, int Setează poziția și dimensiunea controlului.
width, int height)
void Show() Afișează controlul prin setarea proprietății Visible pe true.
string ToString() Returnează o reprezentare textuală a controlului. În general
aceasta reprezintă tipul controlului, împreună proprietatea
Text a acestuia (dacă o are).
void Update() Duce la redesenarea din partea controlului a regiunilor
invalidate din suprafața client a lui.

Tabelul 5.10. Metode specifice clasei Control

5.2.4. Evenimente
Un control sau un alt obiect generează un eveniment pentru înștiințarea programului despre
apariția unor modificări în anumite circumstanțe. Adesea acțiunea de generare a unui
eveniment se mai numește „aruncarea” unui eveniment. Clasele specifice controalelor
furnizează evenimente relevante pentru scopul pentru care au fost create. De exemplu,
controlul Button furnizează un eveniment Click pentru înștiințarea programului despre
apăsarea unui buton de către utilizator.
Programul răspunde la un eveniment prin crearea unui handler de eveniment care „prinde”
evenimentul și întreprinde acțiunile potrivite acestuia. Fiecare eveniment își definește pro-
priul format al handlerului și determină parametrii pe care handlerul de eveniment îi va
primi. Adesea, acești parametri oferă informații suplimentare legate de eveniment.
De exemplu, atunci când o parte a formularului este acoperită sau expusă, formularul
generează evenimentul Paint. Handler-ul evenimentului Paint primește ca parametru un
obiect de tip PaintEventArgs. Proprietatea Graphics a acestui parametru reprezintă o
referință la un obiect de tip Graphics pe care programul îl poate folosi pentru redesenarea
conținutului formularului.
Unele handlere de eveniment primesc parametri care sunt utilizați pentru trimiterea de
informații legate de eveniment înapoi la obiectul care le-a generat. De exemplu, handlerul
evenimentului FormClosing al unei clase formular are un parametru de tip
FormClosingEventArgs. Acesta reprezintă un obiect care are o proprietate Cancel. Dacă
aceasta este setată pe true, formularul anulează evenimentul FormClosing și formularul
rămâne deschis în continuare. De exemplu, handlerul de eveniment poate verifica dacă
datele introduse de utilizator sunt formatate corect, în caz contrar programul afișând un
mesaj de eroare, iar formularul rămânând deschis.

107
Medii și Tehnologii de Programare – curs

Majoritatea evenimentelor asociate unui control sunt specifice acelui tip de control.
Controalele moștenesc un set de evenimente de la clasa de bază Control, însă le pot
supraîncărca, modificându-le astfel comportamentul.

Crearea handlerelor de eveniment în modul design


Există mai multe modalități prin care puteți să creați handlere de evenimente în modul
design. Dacă deschideți un formular în Form Designer și dați dublu-click pe un control, se
deschide editorul de cod și va fi afișat handlerul implicit al acelui control. De exemplu,
pentru un control TextBox va fi deschis handlerul evenimentului TextChanged, pentru un
control Button handlerul evenimentului Click, iar pentru formular handlerul evenimentului
Load.
Pentru crearea unor handlere de eveniment, altele decât cel implicite ale controalelor, din
Form Designer selectați un control sau componentă, apoi în fereastra de proprietăți a
acestuia dați click pe pictograma Events , și dați apoi dublu click pe un eveniment. Editorul
de cod va crea un handler de eveniment, urmând ca dumneavoastră să scrieți codul care
doriți să fie executat la apariția evenimentului respectiv.

Setarea handlerelor de eveniment în timpul rulării


Ați văzut cum puteți să adăugați handlere de evenimente în faza de design. În continuare veți
învăța cum puteți să le asignați în timpul rulării. Întâi trebuie să creați un handler de
eveniment. Aici trebuie să fiți atenți ca parametrii procedurii să fie dați în mod corect pentru
tipul de handler de eveniment pe care doriți să îl creați. De exemplu, pentru un control
TextBox, handlerul evenimentului Click trebuie să primească doi parametri având tipurile
System.Object și System.EventArgs.
Prin utilizarea operatorilor += și -= puteți să adăugați sau să ștergeți handlerul unui
eveniment de la un control. Codul de mai jos ilustrează modul în care un program poate
comute handlerul de eveniment pe care un buton îl execută atunci când este apăsat.
Atunci când RadioButton1 este bifat sau debifat, handlerul evenimentului CheckedChanged
adaugă sau șterge handlerul de eveniment ButtonHandler1 asociat evenimentului Click
pentru butonul Button1. Similar, când RadioButton2 este bifat sau debifat, handlerul
evenimentului CheckedChanged adaugă sau șterge handlerul de eveniment ButtonHandler2
asociat evenimentului Click pentru butonul Button1.
Handlerele de evenimente ButtonHandler1 și ButtonHandler2 afișează un mesaj care indică
handlerul de eveniment care este executat. Handler-ul evenimentului Load asociat formula-
rului selectează primul buton radio.
private void Form3_Load(object sender, EventArgs e)
{
//Selecteaza radioButton1
radioButton1.Checked = true;
}

private void radioButton1_CheckedChanged(object sender, EventArgs e)


{
//Adauga sau sterge ButtonHandler1
if(radioButton1.Checked)
button1.Click += ButtonHandler1;
else
button1.Click -= ButtonHandler1;
}

private void radioButton2_CheckedChanged(object sender, EventArgs e)


{

108
Controale

//Adauga sau sterge ButtonHandler2


if (radioButton2.Checked)
button1.Click += ButtonHandler2;
else
button1.Click -= ButtonHandler2;
}

private void ButtonHandler1(object sender, EventArgs e)


{
//Afiseză un mesaj care indica handlerul de eveniment
MessageBox.Show("ButtonHandler1");
}

private void ButtonHandler2(object sender, EventArgs e)


{
//Afiseză un mesaj care indica handlerul de eveniment
MessageBox.Show("ButtonHandler2");
}

Evenimente utile ale controalelor


Tabelul 5.11 prezintă evenimente utile implementate de clasa Control. Toate controalele
care moștenesc clasa Control moștenesc și aceste evenimente, dacă nu supraîncarcă compor-
tamentul clasei Control.
Eveniment Descriere
AutoSizeChanged Apare atunci când se modifică proprietatea AutoSize a
controlului.
BackColorChanged Apare atunci când se modifică proprietatea BackColor a
controlului.
BackgroundImageChanged Apare atunci când se modifică proprietatea BackgroundImage a
controlului.
BackgroundImageLayoutChanged Apare atunci când se modifică proprietatea
BackgroundImageLayout a controlului.
Click Apare atunci când utilizatorul dă click pe control. Acest
eveniment se situează pe un nivel logic mai înalt decât
evenimentul MouseClick și poate fi declanșat de către alte
acțiuni decât un click de mouse (apăsarea tastei Enter sau un
shortcut).
ContextMenuChanged Apare atunci când se modifică proprietatea ContextMenu a
controlului.
ContextMenuStripChanged Apare atunci când se modifică proprietatea ContextMenuStrip a
controlului.
ControlAdded Apare atunci când este adăugat un nou control la colecția de
controale copil conținute de controlul curent.
ControlRemoved Apare atunci când un control este șters din colecția de
controale copil conținute de controlul curent.
CursorChanged Apare atunci când se modifică proprietatea Cursor a
controlului.
DockChanged Apare atunci când se modifică proprietatea Dock a controlului.
DoubleClick Apare atunci când utilizatorul dă dublu-click pe control.
DragDrop Apare atunci când utilizatorul eliberează ceva pe control în
urma unei operații drag-and-drop. Acest eveniment ar trebui să
prelucreze informația lăsată într-un mod corespunzător.
DragEnter Apare atunci când utilizatorul trage ceva deasupra controlului
într-o operație drag-and-drop.

109
Medii și Tehnologii de Programare – curs

DragLeave Apare atunci când utilizatorul părăsește suprafața controlului în


cursul operației drag-and-drop.
DragOver Apare atunci când utilizatorul a tras ceva deasupra controlului
într-o operație drag-and-drop. Acest eveniment se declanșează
în mod repetat până când utilizatorul părăsește suprafața
controlului, eliberează ceva pe control sau anulează operația.
EnabledChanged Apare atunci când se modifică proprietatea Enabled a
controlului.
Enter Apare atunci când controlul este selectat. Acest eveniment se
declanșează înaintea evenimentului GotFocus.
FontChanged Apare atunci când se modifică proprietatea Font a controlului.
ForeColorChanged Apare atunci când se modifică proprietatea ForeColor a
controlului.
GiveFeedback Apare în timpul unei operații drag-and-drop pentru a permite
controlului sursă să întreprindă anumite acțiuni.
GotFocus Apare atunci când controlul primește focalizarea. Acest
eveniment se declanșează după evenimentul Enter. În general
este preferat evenimentul Enter.
HelpRequested Apare atunci când utilizatorul cere ajutor pentru control. De
exemplu, dacă utilizatorul selectează un control TextBox și
apasă F1, controlul TextBox declanșează acest eveniment.
Invalidated Apare atunci când o parte a controlului este invalidată.
KeyDown Apare atunci când utilizatorul apasă o tastă atunci când
controlul are focalizarea.
KeyPress Apare atunci când utilizatorul apasă și eliberează o tastă atunci
când controlul are focalizarea.
KeyUp Apare atunci când utilizatorul eliberează o tastă atunci când
controlul are focalizarea.
Layout Apare atunci când controlul trebuie să își aranjeze controalele
copil. Acest eveniment apare înainte de evenimentele Resize și
SizeChanged și este preferat pentru aranjarea controalelor
copil.
Leave Apare atunci când controlul pierde focalizarea. Aceste
eveniment se declanșează înaintea evenimentului LostFocus.
LocationChanged Apare atunci când se modifică proprietatea Location a
controlului. Acest eveniment se declanșează după evenimentul
Move.
LostFocus Apare atunci când controlul pierde focalizarea. Acest eveniment
se declanșează dup evenimentul Leave. În general, este preferat
evenimentul Leave.
MarginChanged Apare atunci când se modifică proprietatea Margin a
controlului.
MouseCaptureChanged Apare atunci când controlul primește sau pierde captarea
mouse-ului.
MouseClick Apare atunci când utilizatorul dă click pe control.
MouseDoubleClick Apare atunci când utilizatorul dă dublu-click pe control.
MouseDown Apare atunci când utilizatorul apasă un buton de mouse
deasupra controlului.
MouseEnter Apare atunci când mouse-ul intră pe suprafața controlului.
MouseHover Apare atunci când mouse-ul este deasupra controlului.
MouseLeave Apare atunci când mouse-ul părăsește controlul.
MouseMove Apare atunci când mouse-ul se mișcă deasupra controlului.
MouseUp Apare atunci când utilizatorul eliberează un buton de mouse
deasupra controlului.

110
Controale

MouseWheel Apare atunci când utilizatorul învârte rotița mouse-ului în timp


ce timp controlul are focalizarea.
Move Apare atunci când controlul este mutat. Aceste eveniment se
declanșează înaintea evenimentului LocationChanged.
PaddingChanged Apare atunci când se modifică proprietatea Padding a
controlului.
Paint Apare atunci când controlul trebuie să se redeseneze. În mod
normal, programul desenează controlul în timpul acestui
eveniment.
ParentChanged Apare atunci când se modifică proprietatea Parent a
controlului.
QueryContinueDrag Apare atunci când se modifică ceva în timpul unei operații
drag-and-drop astfel încât controlul sursă poate decide
modificarea sau anularea operației.
RegionChanged Apare atunci când se modifică proprietatea Region a
controlului.
Resize Apare în timp ce se redimensionează controlul. Acest
eveniment se declanșează după evenimentul Layout, însă
înainte de evenimentul SizeChanged.
SizeChanged Apare în timp ce se redimensionează controlul. Acest
eveniment se declanșează după evenimentele Layout și Move.
SystemColorsChanged Apare atunci când se modifică culorile sistem. De exemplu,
poate doriți să desenați ceva folosind aceeași culoare ca cea
utilizată sistemul de operare. Dacă un utilizator modifică o
anumită culoare sistem, puteți utiliza acest eveniment pentru
actualizarea aplicației.
TabIndexChanged Apare atunci când se modifică proprietatea TabIndex a
controlului.
TabStopChanged Apare atunci când se modifică proprietatea TabStop a
controlului.
TextChanged Apare atunci când se modifică proprietatea Text a controlului.
Validated Apare atunci când controlul a terminat cu succes validarea
propriilor date.
Validating Apare atunci când controlul ar trebui să își valideze datele.
VisibleChanged Apare atunci când se modifică proprietatea Visible a
controlului.

Tabelul 5.11. Evenimente specifice clasei Control

Secvențe de evenimente
În unele situații sunt generate o serie de evenimente care apar într-o anumită ordine.

Evenimente de mouse
Atunci când dați click pe un control, apar următoarele evenimente în ordinea indicată. Prima
instanță a evenimentului MouseMove poate apărea de oricâte ori mișcați mouse-ul cât timp
butonul de mouse este apăsat. Evenimentul final MouseMove apare indiferent dacă mișcați
mouse-ul sau nu.
MouseDown
[MouseMove]
Click
MouseClick
MouseUp

111
Medii și Tehnologii de Programare – curs

MouseCaptureChanged
MouseMove

Atunci când dați dublu-click pe un control, apar următoarele evenimente în ordinea indicată:
MouseDown
[MouseMove]
Click
MouseClick
MouseUp
MouseCaptureChanged
MouseMove
MouseDown
DoubleClick
MouseDoubleClick
MouseUp
MouseCaptureChanged
MouseMove

Evenimente de redimensionare
Atunci când redimensionați un control, apar următoarele evenimente în ordinea indicată.
Aceste evenimente sunt repetate atât timp cât redimensionați controlul.
Layout
Resize
SizeChanged

Formularele furnizează de asemenea evenimentele ResizeBegin și ResizeEnd care apar


înainte, respectiv după celelalte evenimente specifice redimensionării.

Evenimente de mutare
Atunci când mutați un control, apar următoarele evenimente în ordinea indicată. Aceste
evenimente sunt repetate atât timp cât mutați controlul.
Move
LocationChanged

Formularele furnizează de asemenea evenimentele ResizeBegin și ResizeEnd care apar


înainte, respectiv după celelalte evenimente specifice mutării.

5.3. Controale Windows


Controalele reprezintă o parte extrem de importantă a oricărei aplicații interactive. Acestea
oferă informații utilizatorului (controalele Label, ToolTip, TreeView, PictureBox etc.) și orga-
nizează informația astfel încât aceasta să fie mai ușor de perceput (controalele GroupBox,
Panel, TabControl etc.). Ele permit utilizatorului să introducă date (controalele TextBox,
RichTextBox, ComboBox, MonthCalendar etc.), să selecteze opțiuni (controalele
RadioButton, CheckBox, ListBox etc.), să controleze aplicația (controalele Button, MenuStrip,
ContextMenuStrip etc.) și să interacționeze cu obiecte din afara aplicației (componentele
OpenFileDialog, SaveFileDialog, PrintDocument, PrintPreviewDialog etc.). Unele controale și
componente oferă suport pentru alte controale (componentele ContextMenuStrip,
ErrorProvider, ImageList etc.).

112
Controale

5.3.1. Scurtă trecere în revistă a controalelor


Tabelul 5.12 descrie succint controalele standard oferite de Visual C# .NET.
Control Descriere
Pointer Acesta este instrumentul de selecție, nu un control.
BackgroundWorker Execută un task în mod asincron și notifică programul principal când acesta s-
a terminat.
BindingNavigator Oferă o interfață utilizator pentru navigarea printr-o sursă de date (butoane
pentru parcurgerea înregistrărilor, butoane de adăugare, ștergere ș.a.m.d.).
BindingSource Încapsulează sursa de date a unui formular și pune la dispoziție metode
pentru navigarea prin date.
Button Un buton simplu. Când un utilizator dă click pe el, programul poate efectua
unele acțiuni.
CheckBox O casetă pe care utilizatorul o poate bifa sau debifa.
CheckedListBox O listă de elemente cu casete de bifare pe care utilizatorul le poate bifa sau
debifa.
ColorDialog Permite utilizatorului selectarea unei culori.
ComboBox O casetă text cu o listă sau listă derulantă atașată pe care utilizatorul o poate
folosi pentru introducerea sau selectarea unei valori text.
ContextMenuStrip Un meniu care apare atunci când utilizatorul dă click dreapta pe un control.
DataGridView Un control tabelar care permite afișarea unui volum mare de date complexe.
DataSet Stochează în memorie date având proprietăți similare unei baze de date
relaționale. Conține obiecte care reprezintă tabele care conțin înregistrări
(rows) și câmpuri (columns), și poate reprezenta multe concepte ale bazelor
de date, cum ar fi indecși și relații de tip foreign key.
DateTimePicker Permite utilizatorului selectarea în mai multe moduri a unei date
calendaristice și a orei.
DirectoryEntry Reprezintă un nod într-o ierarhie de tip Active Directory.
DirectorySearcher Efectuează căutări într-o ierarhie de tip Active Directory.
DomainUpDown Permite utilizatorului derularea unei liste de opțiuni prin click pe butoanele
„săgeată sus” și „săgeată jos”.
ErrorProvider Permite afișarea unui indicator de eroare în dreptul unui control asociat în
cazul apariției unei erori (de exemplu, validarea unor date).
EventLog Oferă acces la jurnalul de evenimente Windows.
FileSystemWatcher Notifică aplicația despre modificări asupra unui director sau fișier.
FlowLayoutPanel Afișează controalele pe care le conține pe rânduri și coloane.
FolderBrowserDialog Afișarea unui dialog care permite utilizatorului selectarea unui director.
FontDialog Afișarea unui dialog care permite utilizatorului să specifice caracteristicile unui
font.
GroupBox Grupează, pentru mai multă claritate, controale aflate în legătură.
HelpProvider Afișează help pentru controalele care au setat așa ceva, dacă utilizatorul
selectează controlul și apasă F1.
HScrollBar Afișează o bară de derulare orizontală.
ImageList Conține o serie de imagini pe care alte controale le pot utiliza. De exemplu,
imaginile pe care le afișează un TabControl pe tab-urile proprii sunt stocate
într-un control ImageList asociat. Puteți extrage și prin cod imagini dintr-un
astfel de control.
Label Afișează text pe care utilizatorul nu îl poate modifica sau selecta prin
intermediul interfeței grafice în timpul rulării.
LinkLabel Afișează o etichetă care poate conține hyperlink-uri. Atunci când utilizatorul
dă click pe un hyperlink, programul poate efectual unele acțiuni.
ListBox Afișează o listă de elemente text pe care utilizatorul le poate selecta. În
funcție de setările controlului, utilizatorul poate selecta unul sau mai multe
elemente.
ListView Afișează o listă de elemente într-unul din cele patru moduri posibile de

113
Medii și Tehnologii de Programare – curs

vizualizare: LargeIcon, SmallIcon, List, and Details.


MaskedTextBox O casetă text care impune ca textul introdus de utilizator să corespundă unui
anumit format (număr de telefon, adresă IP etc.).
MenuStrip Reprezintă meniurile principale, sub-meniurile și elementele de meniu afișate
pe un formular.
MessageQueue Oferă acces la queue pe un server de Message Queuing.
MonthCalendar Afișează un calendar care permite utilizatorului să selecteze o dată
calendaristică.
NotifyIcon Specifică o componentă care afișează o pictogramă în system tray.
NumericUpDown Permite utilizatorului modificarea unui număr prin click pe butoanele „săgeată
sus” și „săgeată jos”.
OpenFileDialog Afișează un dialog care permite utilizatorului selectarea unui fișier pentru
deschidere.
PageSetupDialog Afișează un dialog care permite utilizatorului să specifice proprietățile pentru
paginile ce urmează a fi tipărite.
Panel Control container. Utilizând proprietățile Anchor și Dock ale controlului, puteți
face ca controlul să se redimensioneze singur astfel încât controalele copil să
se redimensioneze de asemenea. Controlul mai oferă automat bare de
derulare.
PerformanceCounter Oferă acces la Windows performance counter.
PictureBox Afișează o imagine. Oferă de asemenea o suprafață de desenare foarte utilă.
PrintDialog Afișează un dialog standard de tipărire. Utilizatorul poate selecta imprimanta,
paginile care să fie tipărite și setări ale imprimantei.
PrintDocument Reprezintă ieșirea care să fie trimisă la imprimantă. Un program poate utiliza
acest obiect pentru a tipări și afișa previzualizări ale documentului de tipărit.
PrintPreviewControl Afișează pe una dintre ferestrele aplicației o previzualizare a ceea ce urmează
a fi tipărit.
PrintPreviewDialog Afișează o previzualizare a ceea ce urmează a fi tipărit într-o fereastră
standard.
Process Permite programului să interacționeze cu procesele, să le pornească și să le
oprească.
ProgressBar Indică într-un mod vizual progresul unei operații de durată.
PropertyGrid Afișează informații despre proprietățile unui obiect într-un format similar celui
afișat în fereastra de proprietăți din Visual Studio.
RadioButton Permite alegerea unei singure opțiuni dintr-un grup de controale de același
tip. Atunci când un utilizator selectează un RadioButton, Visual C#
deselectează toate celelalte controale RadioButton din cadrul aceluiași grup.
Grupurile sunt definite în controale container diferite.
RichTextBox Reprezintă un control în care utilizatorul poate introduce și edita text.
Controlul oferă formatări mult mai avansate decât cele oferite de un control
TextBox, putând afișa fișiere în format RTF. Controlul permite formatarea
textului la nivel de caractere și paragrafe (alinieri, bullets etc.).
SaveFileDialog Afișează un dialog care permite utilizatorului selectarea numelui unui fișier în
care programul să salveze date.
SerialPort Reprezintă un port serial și pune la dispoziție metode pentru controlul, citirea
și scrierea acestuia.
ServiceController Reprezintă un serviciu Windows care permite manipularea serviciilor.
SplitContainer Control container care permite utilizatorului să mute o bară de despărțire
verticală sau orizontală care împarte spațiul disponibil între două zone din
cadrul controlului.
StatusStrip Oferă o zonă (de obicei în partea de jos a ferestrei) unde aplicația poate afișa
mesaje de stare, pictograme și alți indicatori ai stării aplicației.
TabControl Control container care afișează o serie de tab-uri atașate paginilor care au
propriul lor conținut. Utilizatorul dă click pe un tab pentru a putea vizualiza
conținutul paginii asociate.
TableLayoutPanel Control container care afișează controalele pe care le conține în formă

114
Controale

tabelară.
TextBox Afișează text pe care utilizatorul îl poate modifica în timpul rulării.
Timer Implementează un temporizator care declanșează un eveniment la intervale
de timp definite de utilizator.
ToolStrip Oferă un container pentru obiecte Windows toolbar (controale Button, Label,
ComboBox, TextBox, ProgressBar etc.).
ToolStripContainer Oferă panouri pe fiecare parte a ferestrei (acestea pot conține controale de
tip ToolStrip, MenuStrip și StatusStrip) și un panou central (acesta poate
conține orice controale).
ToolTip Afișează un text ajutător dacă utilizatorul poziționează cursorul de mouse
deasupra controlului asociat.
TrackBar Permite utilizatorului să deplaseze un cursor de-a lungul unei bare pentru a
selecta o valoare numerică.
TreeView Afișează date ierarhice într-o formă grafică, arborescentă.
VScrollBar Afișează o bară de derulare verticală.
WebBrowser Permite navigarea prin pagini web din cadrul ferestrei. Controlul afișează
rezultatele exact ca browserul Internet Explorer. O posibilă utilizare a acestui
control este afișarea de help în format web.

Tabelul 5.12. Prezentarea controalelor și componentelor standard oferite de Visual C# .NET.

Chiar dacă aveți la îndemână atâtea unelte puternice, nu întotdeauna este ușor să alegeți cel
mai potrivit control pentru o anumită situație. Pentru simplificarea codului de tratare a
erorilor, ar trebui să alegeți cel mai restrictiv control care poate să îndeplinească sarcina
dorită, deoarece cu cât controalele sunt mai restrictive, cu atât utilizatorul are mai puține
opțiuni de introducere a datelor invalide.

115
Medii și Tehnologii de Programare – curs

6. Formulare

Clasa Form din Visual C# este derivată indirect din clasa Control. Lanțul complet de
moșteniri este următorul: Control → ScrollableControl → ContainerControl → Form. Un
formular moștenește proprietățile, metodele și evenimentele definite de clasa Control, cu
excepția cazului în care acestea sunt supraîncărcate. Din multe puncte de vedere, un
formular este doar un alt tip de control.

6.1. Transparență
Obiectul Form oferă, suplimentar față de obiectul Control, o serie de proprietăți pe care le
puteți folosi pentru a face o fereastră total sau parțial transparentă. Proprietatea Opacity
determină opacitatea unei ferestre. În modul design, fereastra de proprietăți arată valoarea
acestei proprietăți sub formă de procentaj, unde 100% semnifică faptul că formularul este
complet opac, iar 0% că fereastra este complet transparentă. În timpul rulării trebuie să
tratați valoarea proprietății Opacity ca număr în virgulă mobilă cu valori între 0.0 (complet
transparent) și 1.0 (complet opac).
O aplicație poate utiliza pentru Opacity valori mai mici de 100% pentru a permite
utilizatorului să vadă ce se întâmplă în spatele ferestrei. De exemplu, puteți construi o
fereastră parțial transparentă pentru implementarea unui dialog de căutare, astfel încât
utilizatorul să poată vedea documentul pe măsură ce căutarea avansează.
Figura 6.1 prezintă un formular cu opacitatea 66%. Puteți vedea încă marginile ferestrei,
bara de titlu, meniurile și butoanele, însă puteți observa de asemenea fereastra de dedesubt.

Figura 6.1. O fereastră cu opacitate 66% permite vizualizarea ferestrei situate dedesubt.

116
Controale

Dacă opacitatea este mai mare de 0%, fereastra se comportă normal, cu excepția aspectului
imaterial al acesteia, utilizatorii putând interacționa cu aceasta ca și cu orice altă fereastră.
Dacă opacitatea este 0%, fereastra este complet transparentă, iar utilizatorul poate interac-
ționa cu ea numai prin intermediul tastaturii (schimbarea focalizării controalelor cu tasta
TAB, acționarea comenzilor prin combinații de taste). În orice caz, fereastra nu va detecta
click-urile de mouse.
Dacă opacitatea este 1%, fereastra rămâne invizibilă în continuare, însă recunoaște click-
urile de mouse.
O a doua proprietate care poate determina transparența unei ferestre este TransparencyKey.
Această proprietate reprezintă o culoare care indică mediului care parte a ferestrei trebuie
să fie complet transparentă. La afișarea ferestrei, suprafețele care au ca fundal această
culoare nu vor fi desenate.
Figura 6.2 prezintă o fereastră cu proprietatea TransparencyKey setată la culoarea de fundal a
ferestrei. Atât fereastra cât și eticheta cu textul „Spațiu gol” au același fundal, astfel că vor fi
transparente la afișare. Evenimentul Paint al ferestrei desenează o elipsă în interiorul
ferestrei.

Figura 6.2. Proprietatea TransparencyKey a unei ferestre permite crearea unor zone complet transparente.

Nu numai că pixelii care nu sunt desenați sunt transparenți, ci de asemenea fereastra nu


răspunde la evenimentele de mouse pe care le primește. Dacă utilizatorul dă click pe o zonă
transparentă de pe fereastră, cursorul de mouse trece prin fereastră la aplicația de dedesubt.
TransparencyKey se aplică atât suprafeței ferestrei cât și controalelor de pe fereastră. Aceasta
poate duce la efecte ciudate. De exemplu, dacă setați TransparencyKey la culoarea
SystemColors.Control, fereastra, controalele, până și fundalul marginilor și butoanele de
maximizare, minimizare și închidere a ferestrei vor dispărea. Dacă dați click pe porțiunile
netransparente ale butoanelor, acoperite de text, butoanele vor funcționa normal.
Cea mai frecventă utilizare a proprietății TransparencyKey este aceea de creare a unor
ferestre de diverse forme. Setați pentru formular proprietatea FormBorderStyle la None
pentru îndepărtarea marginilor, a barei de titlu și a butoanelor sistem. Setați apoi
proprietățile BackColor și TransparencyKey la o culoare care nu doriți să fie afișată pe
formular. Desenați apoi cu altă culoare forma pe care doriți să o aibă formularul.

117
Medii și Tehnologii de Programare – curs

Figura 6.3 prezintă o fereastră de forma unui smiley. Handler-ul evenimentului Paint al
ferestrei desenează imaginea dintr-un fișier bitmap. În acest fel puteți construi de exemplu
splash screen-uri1 sau alte ferestre dialog interesante.

Figura 6.3. Proprietatea TransparencyKey permite crearea unor ferestre de diverse forme, precum aceasta.

Această fereastră nu prezintă nici margini, nici bară de titlu și nici butoane sistem, astfel că
utilizatorul nu o poate muta, redimensiona, maximiza sau închide (se setează proprietatea
FormBorderStyle a formularului la None). Pentru utilizarea acestei ferestre ca splash screen,
adăugați un control Timer pentru a face ca fereastra să dispară după câteva secunde. Pentru
utilizarea ferestrei ca o fereastră obișnuită, adăugați pe suprafața ei un buton de închidere.
Dacă utilizați împreună proprietățile Opacity și TransparencyKey, pixelii care corespund cu
TransparencyKey nu sunt afișați, iar ceilalți pixeli sunt afișați corespunzător cu valoarea setată
de proprietatea Opacity.

6.2. Aplicații SDI și MDI


O aplicație uni-document (SDI – Single Document Interface) afișează numai un singur
document în fiecare fereastră (Figura 6.4). Un exemplu de aplicație SDI este Microsoft Paint,
care poate gestiona numai o singură imagine la un moment dat. Unele aplicații SDI pot afișa
mai mult de un singur document la un moment dat, însă fiecare într-o fereastră separată.
O aplicație multi-document (MDI – Multiple Document Interface) poate afișa la un moment
dat mai multe documente în ferestre separate (ferestre copil), acestea fiind cuprinse într-o
fereastră mai mare numită fereastră părinte (Figura 6.5).

1 O fereastră de tip splash screen este afișată în timp ce o aplicație inițializează sau încarcă datele necesare,
pregătindu-se de lucru. Aplicația va închide fereastra splash screen după ce inițializarea este completă, sau după
trecerea unui număr de secunde.

118
Controale

Figura 6.4. O aplicație SDI afișează documente separate în ferestre separate

Aplicațiile MDI oferă de obicei unelte pentru gestionarea ferestrelor copil pe care acestea le
conțin. Aceste unelte permit utilizatorului minimizarea ferestrelor copil, aranjarea acestora
în cadrul ferestrei părinte, ș.a.m.d. Visual Studio este o aplicație MDI deoarece poate afișa în
cadrul ferestrei principale mai multe ferestre copil (designere de formulare, editoare de cod,
editoare de bitmap, ș.a.m.d.).

Figura 6.5. O aplicație MDI afișează documentele în ferestre copil conținute de fereastra părinte

6.2.1. Caracteristici ale aplicațiilor MDI


O fereastră MDI container oferă câteva funcții legate de ferestrele copil. Fereastra container
cuprinde ferestrele și le ține grupate astfel încât acestea pot fi ușor de găsit. Dacă mutați o

119
Medii și Tehnologii de Programare – curs

fereastră copil astfel încât acesta să depășească marginile ferestrei părinte, fereastra părinte
va afișa în mod automat bare de derulare pentru a putea vizualiza fereastra copil.
Programul va afișa o pictogramă în taskbar și Task Manager pentru fereastra părinte, însă nu
și pentru ferestrele copil. Dacă minimizați containerul MDI, toate ferestrele pe care le
conține vor fi ascunse împreună cu acesta. Dacă minimizați însă o fereastră copil, pictograma
acesteia va fi afișată în interiorul containerului, iar nu separat în taskbar. În cazul în care
maximizați o fereastră copil MDI, aceasta va umple suprafața ferestrei părinte.
Un container MDI oferă de asemenea unele metode pentru aranjarea ferestrelor copil. Codul
de mai jos ilustrează modul în care, din cadrul containerului MDI, pot fi aranjate ferestrele
copil în diverse configurații:
private void CascadeToolStripMenuItem_Click(object sender, EventArgs e)
{
LayoutMdi(MdiLayout.Cascade);
}

private void TileVerticalToolStripMenuItem_Click(object sender, EventArgs e)


{
LayoutMdi(MdiLayout.TileVertical);
}

private void TileHorizontalToolStripMenuItem_Click(object sender, EventArgs e)


{
LayoutMdi(MdiLayout.TileHorizontal);
}

private void ArrangeIconsToolStripMenuItem_Click(object sender, EventArgs e)


{
LayoutMdi(MdiLayout.ArrangeIcons);
}

Alte comenzi utile pe care le puteți adăuga unei aplicații MDI sunt: Minimize All, Restore All,
Maximize All și Close All. Puteți implementa aceste comenzi prin parcurgerea colecției
MdiChildren asociate containerului MDI, precum se poate observa în continuare:
private void CloseAllToolStripMenuItem_Click(object sender, EventArgs e)
{
foreach (Form childForm in MdiChildren)
{
childForm.Close();
}
}
private void minimizeAllToolStripMenuItem_Click(object sender, EventArgs e)
{
foreach (Form childForm in MdiChildren)
{
childForm.WindowState = FormWindowState.Minimized;
}
}
private void maximizeAllToolStripMenuItem_Click(object sender, EventArgs e)
{
foreach (Form childForm in MdiChildren)
{
childForm.WindowState = FormWindowState.Maximized;
}
}
private void restoreAllToolStripMenuItem_Click(object sender, EventArgs e)
{
foreach (Form childForm in MdiChildren)
{
childForm.WindowState = FormWindowState.Normal;
}
}

120
Controale

Multe aplicații MDI includ un meniu „Windows” care afișează o listă a ferestrelor copil
deschise. Apăsarea uneia dintre aceste comenzi de meniu permite mutarea ferestrei copil
deasupra tuturor celorlalte ferestre conținute de containerul MDI.
Construirea unei liste de ferestre copil este o sarcină ușoară în Visual C#. Selectați controlul
principal MenuStrip, iar în fereastra de proprietăți a acestuia setați proprietatea
MdiWindowListItem la meniul care doriți să conțină lista de ferestre copil. După fiecare
operație de deschidere sau închiderea unei ferestre copil, Visual C# va actualiza automat
această listă.
Figura 6.6 arată un meniu care afișează o listă de ferestre copil MDI. Fereastra cu titlul
„Program.cs” are focalizarea, astfel că lista afișează o bifă în dreptul comenzii de meniu
asociate ferestrei.

Figura 6.6. Proprietatea MdiWindowListItem asociată controlului MenuStrip determină care element de meniu
va afișa lista cu ferestrele copil MDI.

Majoritatea aplicațiilor Visual C# utilizează SDI, iar la crearea unei noi aplicații, interfața
acesteia va fi implicit SDI. Pentru a avea o aplicație MDI, creați întâi o aplicație nouă, apoi
setați proprietatea IsMdiContainer a formularului de start pe true. În Form Designer, acest
formular își va schimba înfățișarea, astfel încât va fi evident că este un formular părinte MDI.
Ca metodă alternativă puteți selecta din meniul Project comanda „Add Windows Form”. În
fereastra dialog ce se va deschide selectați „MDI Parent Form” și dați ferestrei un nume
rezonabil. Visual C# va adăuga un nou formular părinte MDI având un control meniu care va
include meniuri standard (File, Edit, View, ș.a.m.d.) și o bară de unelte cu unelte standard
(New, Open, Save, ș.a.m.d.).
În faza de design, un formular copil MDI are aceeași înfățișare cu a unui formular standard.
Pentru a face ca formularul copil să fie afișat în interiorul unui container MDI, trebuie să îi
setați acestuia în timpul rulării proprietatea MdiParent la containerul MDI.
Puteți vedea mai jos secvențele de cod adăugate automat la comanda de deschidere a unei
noi ferestre copil din fereastra părinte MDI. Ferestrele copil nou create vor fi automat afișate
în interiorul containerului MDI și vor fi adăugate în lista de ferestre copil deschise.
private void OpenFile(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.InitialDirectory = Application.StartupPath;
openFileDialog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*";

121
Medii și Tehnologii de Programare – curs

if (openFileDialog.ShowDialog(this) == DialogResult.OK)
{
string FileName = openFileDialog.FileName;
// Aici adaugarea codului pentru afisarea continutului fisierului
// ...
}
}

6.2.2. Evenimente MDI


Evenimentele pentru o fereastră copil MDI apar în general înaintea evenimentelor
corespunzătoare ale ferestrei părinte. De exemplu, dacă încercați să închideți o fereastră
MDI, toate ferestrele copil vor recepționa evenimentele FormClosing înaintea ferestrei
părinte. În continuare, ferestrele copil vor recepționa evenimentele FormClosed, iar numai
după aceea fereastra părinte va recepționa evenimentul FormClosed.
Dacă handlerul unui eveniment FormClosing setează parametrul e.Cancel pe true, operația
de închidere a ferestrei este anulată iar fereastra va rămâne deschisă mai departe. Un
formular poate utiliza acest mecanism pentru garantarea consistenței datelor proprii și a
salvării corecte a acestora.

6.2.3. MDI Versus SDI


Atât aplicațiile MDI cât și cele SDI au fiecare avantajele lor. Într-o aplicație SDI, construirea și
înțelegerea meniurilor este simplă. Un meniu corespunde numai unui formular, neexistând
nicio modificare în meniuri odată cu deschiderea sau închiderea altor ferestre.
Aplicațiile SDI se pretează situațiilor particulare în care programul operează numai cu un
fișier la un moment dat. Exemple de aplicații SDI sunt: Notepad, Microsoft Paint și alte
aplicații similare care permit utilizatorului lucrul asupra unui singur fișier. De regulă, aceste
programe nu sunt mari consumatoare de resurse, astfel că utilizatorul poate să deschidă alte
instanțe ale acestora în cazul în care dorește să lucreze cu mai multe fișiere odată.
Aplicațiile MDI ajută utilizatorul să afișeze la un moment dat mai multe fișiere care au
legătură unele cu altele fără să încarce inutil desktop-ul. De exemplu, Visual Studio utilizează
o interfață MDI pentru a permite utilizatorilor vizualizarea împreună a tuturor fișierelor
dintr-un proiect. Afișarea în ferestre separate a acestora ar aglomera foarte mult desktop-și
taskbar-ul, și ar face mai dificil pentru utilizator lucrul cu toate aceste documente (cum ar fi,
de exemplu, aplicația GIMP).
Puteți construi de asemenea aplicații hibride care să afișeze câteva containere MDI, fiecare
conținând un număr de ferestre copil. În practică, acest gen de aplicații hibride sunt adesea
greoaie și prost concepute. În general ar fi mai simplu de construit aplicații standard MDI.
Puteți să evitați utilizarea de ferestre multiple prin folosirea unor controale care ajută la
afișarea unei cantități mari de informații pe un singur formular: ComboBox, ListBox,
TreeView, SplitContainer și alte controale care afișează cantități mari de date într-un spațiu
limitat, oferind la nevoie bare de derulare.
Controlul TabControl vă permite afișarea de date pe pagini multiple, toate situate pe un
singur formular. Utilizarea acestui tip de controale în interiorul unui container MDI duce la
crearea unor aplicații robuste care permit utilizatorilor să gestioneze cu ușurință cantități
mari de informații.

122
Controale

6.3. Ferestre Dialog


Utilizarea unui formular ca dialog este relativ simplă. Creați formularul, adăugați controalele
de care aveți nevoie, apoi unul sau mai multe butoane care să permită utilizatorului
părăsirea dialogului. Multe ferestre dialog utilizează butoanele OK și Cancel, însă puteți
utiliza și alte butoane, cum ar fi Yes, No, Retry ș.a.
Setați pentru formularul în cauză proprietatea AcceptButton la butonul care doriți să fie
apelat la apăsarea tastei „Enter”, iar proprietatea CancelButton la butonul care doriți să fie
apelat la apăsarea tastei „Esc”.
Proprietatea DialogResult a formularului indică valoarea returnată de dialog. Dacă fereastra
dialog este apelată prin metoda ShowDialog(), aceasta va returna o valoare DialogResult.
Metoda ShowDialog() are ca rezultat afișarea modală a ferestrei dialog. O fereastră modală
menține focalizarea asupra ferestrei, astfel încât utilizatorii nu pot să interacționeze cu alte
componente ale aplicației cât timp fereastra modală este deschisă.
Secvența de cod de mai jos ilustrează modul în care programul poate să afișeze un dialog și
să reacționeze la rezultatul întors de acesta.
private void button1_Click(object sender, EventArgs e)
{
DialogAngajat dlg = new DialogAngajat();
if (dlg.ShowDialog() == DialogResult.OK)
MessageBox.Show(dlg.txtNume.Text + " " + dlg.txtPrenume.Text);
else
MessageBox.Show("Anulat");
}

Dacă utilizatorul apasă butonul „Cancel” sau închide formularul din meniul sistem, atunci
formularul setează automat proprietatea DialogResult la Cancel și se închide. Dacă
utilizatorul apasă alt buton, handlerul de eveniment va seta DialogResult la o valoare
corespunzătoare. Setarea acestei valori va duce la închiderea automată a formularului.

123

S-ar putea să vă placă și