trei

33
3. Alte controale Câteva noi controale, ce urmează să fie introduse în continuare, sunt controale de tip data, respectiv controale bazate pe liste. 3.1 Controlul MonthCalendar Controlul Month-Calendar permite vizualizarea sau setarea informaţiilor de tip data. Este un obiect de clasă MonthCalendar. Câteva proprietăţi specifice ar fi: CalendarDimensions – stabileşte dimensiunile controlului de tip Calendar; FirstDayOfWeek – stabileşte prima zi din săptămână. Implicit este duminică; MaxDate – marchează ultima dată reprezentabilă pe calendar; MinDate – marchează prima dată reprezentabilă pe calendar; SelectionRange – marchează numărul maxim de zile ce pot fi selectate în control. SelectionStart – furnizează dada de început a zonei selectate în control. ShowToday – precizează dacă data curentă este sau nu afişată în partea de jos a controlului. TodayDate – furnizează data curentă. Ce este interesant de remarcat, ca proprietăţile de tip dată, sunt manipulate prin intermediul unor obiecte de clasă DateTime. Câteva proprietăţi ale acestei clase, mai des utilizate sunt: Date – furnizează data conţinută în instanţa curentă a obiectului; Day furnizează numărul zilei din lună conţinută în instanţa curentă a obiectului; DayOfWeek furnizează numărul zilei din săptămână conţinută în instanţa curentă a obiectului; DayOfYear furnizează numărul zilei din an conţinută în instanţa curentă a obiectului; Hour – furnizează ora conţinută în instanţa curentă a obiectului; Minute – furnizează minutul conţinută în instanţa curentă a obiectului; Month – furnizează luna conţinută în instanţa curentă a obiectului; Now – furnizează un obiect care conţine data si ora curentă a computerului, setate la nodul de reprezentare locală. Second – furnizează secunda conţinută în instanţa curentă a obiectului; Today – furnizează data curentă; Year – furnizează anul conţinut în instanţa curentă a obiectului; Câteva evenimente produde controlul MonthCalendar sunt: DateChanged – se produce la schimbarea datei din calendar; DateSelected – se produce atunci când utilizatoru realizează o selecţie explicită cu mouse-ul a unor date; Pentru a exemplifica modul de funcţionare al controlului, să deschidem un nou proiect. Haideţi să-l intitulăm trei. Să construim interfaţa din fig. 3.1. Pentru aceasta, marim lăţimea formei iniţiale şi adăugăm un control MonthCalendar şi un control Label. Asupra lor facem următoerele modificări de proprietăţi: 28

Upload: nitu-mihai

Post on 29-Sep-2015

224 views

Category:

Documents


5 download

DESCRIPTION

Curs 3 C#

TRANSCRIPT

  • 3. Alte controale Cteva noi controale, ce urmeaz s fie introduse n continuare, sunt controale de tip data, respectiv controale bazate pe liste.

    3.1 Controlul MonthCalendar Controlul Month-Calendar permite vizualizarea sau setarea informaiilor de tip data. Este un obiect de clas MonthCalendar. Cteva proprieti specifice ar fi: CalendarDimensions stabilete dimensiunile controlului de tip Calendar; FirstDayOfWeek stabilete prima zi din sptmn. Implicit este duminic; MaxDate marcheaz ultima dat reprezentabil pe calendar; MinDate marcheaz prima dat reprezentabil pe calendar; SelectionRange marcheaz numrul maxim de zile ce pot fi selectate n

    control. SelectionStart furnizeaz dada de nceput a zonei selectate n control. ShowToday precizeaz dac data curent este sau nu afiat n partea de jos a

    controlului. TodayDate furnizeaz data curent.

    Ce este interesant de remarcat, ca proprietile de tip dat, sunt manipulate prin intermediul unor obiecte de clas DateTime. Cteva proprieti ale acestei clase, mai des utilizate sunt: Date furnizeaz data coninut n instana curent a obiectului; Day furnizeaz numrul zilei din lun coninut n instana curent a obiectului; DayOfWeek furnizeaz numrul zilei din sptmn coninut n instana

    curent a obiectului; DayOfYear furnizeaz numrul zilei din an coninut n instana curent a

    obiectului; Hour furnizeaz ora coninut n instana curent a obiectului; Minute furnizeaz minutul coninut n instana curent a obiectului; Month furnizeaz luna coninut n instana curent a obiectului; Now furnizeaz un obiect care conine data si ora curent a computerului, setate

    la nodul de reprezentare local. Second furnizeaz secunda coninut n instana curent a obiectului; Today furnizeaz data curent; Year furnizeaz anul coninut n instana curent a obiectului;

    Cteva evenimente produde controlul MonthCalendar sunt: DateChanged se produce la schimbarea datei din calendar; DateSelected se produce atunci cnd utilizatoru realizeaz o selecie explicit

    cu mouse-ul a unor date;

    Pentru a exemplifica modul de funcionare al controlului, s deschidem un nou proiect. Haidei s-l intitulm trei. S construim interfaa din fig. 3.1. Pentru aceasta, marim limea formei iniiale i adugm un control MonthCalendar i un control Label. Asupra lor facem urmtoerele modificri de proprieti:

    28

  • pentru controlul MonthCalendar schimbam proprietatea Name n Data i schimbm la false proprietatea ShowToday;

    pentru controlul Label schimbm proprietatea Name n EData, schimbm proprietatea Font n Papyrus, 12pt, Bold, Italic.

    Dorim ca data selectat pe controlul MonthCalendar, s apar n limba romn nscris n controlul Label. S ne reamintim c evenimentul produs la fiecare schimbare a datei n controlul MonthCalendar este DateChanged. Ce va trebui s facem? Deja stim: s inserm un handler pentru acest eveniment i s scriem funcia care va fi lansat prin intermediul acestui handler n execuie.

    Figura 3.1

    public partial class Form1 : Form { public Form1() { InitializeComponent(); EData.ForeColor=Color.Red; this.Data.DateChanged += new DateRangeEventHandler(this.Data_SchimbareData); } }

    Am creat noul handler. Se poate observa c obiectul care genereaz evenimentul DateChanged este Data, iar funcia asociat se va numi Data_SchimbareData(). Nu ne rmne dect s-o implementm:

    private void Data_SchimbareData(object sender, DateRangeEventArgs e) { this.Data.TodayDate=this.Data.SelectionStart; CompleteazaData(); } }

    Funcia ncarc n proprietatea TodayDate (seteaz ca i dat curent) data pe care s-a fcut click cu mouse-le. Apoi apeleaz funcia CompleteazData(). Va trebui s scriem i aceast funcie. Ce va trebui s fac aceasta? S determine ziua curent din sptmn (ziua curent fiind meninut de proprietatea TodayDate a controlului Data) i s-o transforme n denumirea corespunztoare a zilei din sptmn. S extrag ziua din lun, apoi s transforme luna n denumirea

    29

  • corespunztoare i s adauge anul. Toate aceste informaii trebuie stocate ntr-un string, pentru a putea modifica proprietatea Text a controluli EData.

    private void CompleteazaData() { string d; switch (this.Data.TodayDate.DayOfWeek) { case DayOfWeek.Sunday: EData.Text = "Duminica "; break; case DayOfWeek.Monday: EData.Text = "Luni "; break; case DayOfWeek.Tuesday: EData.Text = "Marti "; break; case DayOfWeek.Wednesday: EData.Text = "Miercuri "; break; case DayOfWeek.Thursday: EData.Text = "Joi "; break; case DayOfWeek.Friday: EData.Text = "Vineri "; break; case DayOfWeek.Saturday: EData.Text = "Sambata "; break; } d = Convert.ToString(this.Data.TodayDate.Day); EData.Text += d; switch (this.Data.TodayDate.Month) { case 1: EData.Text += " Ianuarie "; break; case 2: EData.Text += " Februarie "; break; case 3: EData.Text += " Martie "; break; case 4: EData.Text += " Aprilie "; break; case 5: EData.Text += " Mai "; break; case 6: EData.Text += " Iunie "; break; case 7: EData.Text += " Iulie "; break; case 9: EData.Text += " Septembrie "; break; case 10: EData.Text += " Octombrie "; break; case 11: EData.Text += " Noiembrie "; break; case 12: EData.Text += " Decembrie "; break; } d = Convert.ToString(this.Data.TodayDate.Year); EData.Text += d; }

    Ce ne mai ramne de fcut? n forma actual a programului, data curent este afiat de EData doar dac se face o schimbare de dat n controlul Data. Dar n mod normal ea trebuie afiat de la nceput. Ce trebuie s face pentru aceasta? Evident, s apelm funcia CompleteazaData() n zona de iniializare a formei:

    public Form1() { InitializeComponent(); this.Data.DateChanged += new DateRangeEventHandler(this.Data_SchimbareData); CompleteazaData(); }

    Compilai i executai programul. Ce ne deranjeaz? Faptul c datele pe care le poate reprezenta calendarul nu sunt limitate la un interval dorit de noi. S ncercm s realizm acest lucru. Dar pentru aceasta, s introducem un nou control, numit

    3.2 Controlul ComboBox Acest control combin n fapt mai multe controale. n acest control vom regsi un control TextBox, prezentat anterior i respectiv un control ListBox despre care vom

    30

  • vorbi puin mai trziu. Controlul ComboBox apare ca un TextBox avnd n partea stng un buton cu sgeat. Dac se apas oe acesta, controlul se deschide, prezentnd o list de elemente. Orice astfel de control este un obiect de clas ComboBox. Proprieti ale acestui control sunt: DropDownStyle - stilul n care este afiat controlul la deschiderea listei. DropDown utilizatorul poate edita partea de de TextBox a controlului i

    trebuie s apese butonul sgeat pentru a deschide partea de ListBox. Simple la fel ca i DropDown, cu excepia faptului c partea de ListBox a

    controlului este tot timpul vizibil. DropDownList utilizatorul nu poate edita partea de TextBox a controlului

    i trebuie s apese butonul sgeat pentru a deschide partea de ListBox. DroppedDown Indic dac partea de list a controlului este deschis sau nu. Items este reprezentat sub forma unei colecii care stocheaz obiectele

    coninute de ComboBox. MaxLength prin setarea acestei proprieti la o valoare diferit de 0, se

    specific numrul maxim de caractere ce pot fi introduse n partea de TextBox a controlului.

    SelectedIndex indic indexul obiectului curent selctat n lista controlului. Obiectele sunt ordonate n list pe baza unui index bazat pe 0.

    SelectedItem indic obiectul curent selectat n list. SelectionStart indic indexul primului obiect selctat n lista asociat

    controlului. SelectionLength lungimea textului selectat n partea de TextBox asociat

    controlului. Sorted dac aceast proprietate este true, elementele din lista asociat

    controlului vor fi sortate n ordine alfabetic.

    Cteva evenimente sunt: DropDown se produce cnd partea de ListBox a controlului se deschide. SelectedIndexChanged se produce la schimbarea seleciei n zona de list a

    controlului. KeyDown se produce cnd o tast este apsat n zona de TextBox a

    controlului. KeyUp - se produce cnd o tast este eliberat n zona de TextBox a controlului. TextChanged se produce la schimbarea textului din partea de TextBox a

    controlului.

    Figura 3.2

    31

  • S revenim la programul nostru. Dorim s stabilim prin intermediul unor controale

    ComboBox, anul reprezentat pe MonthCalendar, luna de nceput i luna de sfrit al intervalului de timp prezentat. Pentru aceasta, introducem pe form un control GroupBox, trei controale Label i 3 controale ComboBox, ca n fig. 3.2.

    Pentru proprietile controalelor, vom face urmtoarele modificri: pentru controlul GroupBox vom schimba proprietatea Text n SelecieInterval. pentru controalele Label, vom schimba proprietile Text (de la stnga la dreapta)

    n An, Luna inceput i respectiv Luna sfarsit. pentru controalele ComboBox vom pune proprietatea DropDownStyle la

    DropDownList i vom modifica proprietatea Name (de la stnga la dreapta) astefel: comboAn, comboLuna i respectiv comboLunaS.

    Primul lucru pe care trebuie s-l facem, este s populm controalele ComboBox

    cu informaia corespunztoare. Pentru aceasta, vom adiga 3 noi funcii, ca mai jos:

    private void PopulezAn() { this.comboAn.Items.Add(Convert.ToString(this.Data.TodayDate.Year)); this.comboAn.Items.Add(Convert.ToString(this.Data.TodayDate.Year + 1)); this.comboAn.Items.Add(Convert.ToString(this.Data.TodayDate.Year + 2)); this.comboAn.Items.Add(Convert.ToString(this.Data.TodayDate.Year + 3)); this.comboAn.SelectedIndex = 0; } private void PopulezLuna() { this.comboLuna.Items.Add("Ianuarie"); this.comboLuna.Items.Add("Februarie"); this.comboLuna.Items.Add("Martie"); this.comboLuna.Items.Add("Aprilie"); this.comboLuna.Items.Add("Mai"); this.comboLuna.Items.Add("Iunie"); this.comboLuna.Items.Add("Iulie"); this.comboLuna.Items.Add("August"); this.comboLuna.Items.Add("Septembrie"); this.comboLuna.Items.Add("Octombrie"); this.comboLuna.Items.Add("Noiembrie"); this.comboLuna.Items.Add("Decembrie"); this.comboLuna.SelectedIndex = 0; } private void PopulezLunaS() { this.comboLunaS.Items.Add("Ianuarie"); this.comboLunaS.Items.Add("Februarie"); this.comboLunaS.Items.Add("Martie"); this.comboLunaS.Items.Add("Aprilie"); this.comboLunaS.Items.Add("Mai"); this.comboLunaS.Items.Add("Iunie"); this.comboLunaS.Items.Add("Iulie"); this.comboLunaS.Items.Add("August"); this.comboLunaS.Items.Add("Septembrie"); this.comboLunaS.Items.Add("Octombrie"); this.comboLunaS.Items.Add("Noiembrie"); this.comboLunaS.Items.Add("Decembrie"); this.comboLunaS.SelectedIndex = 11; }

    32

  • Prima funcie completeaz coninutul controlului comboAn. Extrage anul curent i-l convertete ntr-un ir de caractere i apoi l adaug n lista controlului. Adaug apoi urmtorii 3 ani convertii la string. n final, precizeaz faptul ca indexul implicit al elementelor din control este 0, adic va fi selectat anul curent. Bazat pe cele spuse atnerior, ncercai s explicai implementtrile celorlalte 2 funcii. Aceste funcii trebuie apelate. Le vom apela n zouna de iniializare a formei:

    public Form1() { PopulezAn(); PopulezLuna(); PopulezLunaS(); }

    Compilai i executai programul. Ce n-am fcut nc? Pe baza datelor implicite, nc nu am limitat intervalul de timp prezentat de calendar. Va trebui ca la modificarea seleciei n controalele de tip ComboBox, valorile selectate s se aplice n calculul datelor minim i mxim reprezenztabil pe calendar. Adic, s interceptm evenimentul SelectedItemChanged produs de controale. Ce avem de fcut? Evident, urmeaz scrierea handlerilor.

    public Form1() { PopulezLunaS(); this.comboAn.SelectedIndexChanged += new EventHandler(combo_Selectie); this.comboLuna.SelectedIndexChanged += new EventHandler(combo_Selectie); this.comboLunaS.SelectedIndexChanged += new EventHandler(combo_Selectie); }

    i acum implementarea funciei combo_Selectie():

    private void combo_Selectie(object sender, EventArgs e) { ComboBox cb = (ComboBox)sender; if (cb == comboLuna) { this.comboLunaS.Items.Clear(); if (this.comboLuna.SelectedIndex

  • Ce face funcia? Verific sursa evenimentului. Dac evenimentul a fost generat de comboAn sau comboLuna, apeleaz funcia SeteazaIntervalTimp(), n care se face setarea datelor minime i maxime din calendar. Dac ns sursa evenimentului este comboLunaS, terge coninutul acestui control i l repopuleaz doar cu lunile ulterioare lunii selectate n controlul comboLuna. Aceasta pentru c data maxim n calendar nu poate fi mai mic dect data minim. i acum, s scriem funcia SeteazaIntervalTimp():

    private void SeteazaIntervalTimp() { int d=0; switch (this.comboLunaS.SelectedIndex) { case 0: d=31; break; case 1: if (Convert.ToInt16(this.comboAn.SelectedItem.ToString()) % 4 == 0) d=29; else d=28; break; case 2: d=31; break; case 3: d=30; break; case 4: d=31; break; case 5: d=30; break; case 6: d=31; break; case 7: d=31; break; case 8: d=30; break; case 9: d=31; break; case 10: d=30; break; case 11: d=31; break; } this.Data.MaxDate = new DateTime(Convert.ToInt32(this.comboAn.SelectedItem.ToString()), this.comboLuna.SelectedIndex+this.comboLunaS.SelectedIndex + 1, d, 23, 59, 59); this.Data.MinDate = new DateTime(Convert.ToInt32(this.comboAn.SelectedItem.ToString()), this.comboLuna.SelectedIndex + 1, 1, 0, 0, 0); }

    Funcia seteaz data minim i maxim reprezentabile n calendar convertind n format DateTime informaiile din cele 3 controale ComboBox, respectiv considernd ora 23:59:59 ca or de final i respectiv 0:0:0 ca or de nceput. Funcia ine de asemenea cont dac anul este sau nu bisect. Aceast funcie mai trebuie apelat i n faza de iniializare a formei, pentru a limita de la lansarea programului intervalul de timp reprezentabil pe baza valorilor implicite din controalelele ComboBox.

    public Form1() { ... SeteazaIntervalTimp(); }

    Compilai i executai programul.

    34

  • 3.3 Controlul TabControl Controlul TabControl furnizeaz un mod elegant de organizare a unei interfee n componente logice, aaccesibile prin intermediul unor taburi localizate n partea superioar a controlului. Controlul TabControl este organizat n pagini (TabPages) care opereaz de o manier oarecum similar controlului GroupBox, dar ntr-o modalitate mai complex. Cteva din proprietile controlului sunt: Alignment precizeaz poziia taburilor. Implicit, acestea sunt afiate n partea

    superioar a controlului. Appearance Precizeaz modul de afiare al taburilor. Acestea pot fi afiate ca

    butoane normale sau bidimensionale. HotTrack dac aceast proprietate este true, modul de afiare al taburilor se

    schimb la trecerea prompterului mouse-lui pe deasupra lor. Multiline dac aceast proprietate este true, se pot insera mai multe linii de text

    in tab-uri. RowCount conine numarul de linii al taburilor care sunt afiate n mod curent. SelectedIndex conine indexul tab-ului curent selectat. TabCount conine numrul curent de taburi coninut de control. TabPages conine sub forma unei colecii paginile din TabControl.

    n cele ce urmeaz, vom dezvolta o

    aplicaie mai complex, componentele acesteia fiind gzduite de paginile unui control TabControl.

    Figura 3.3

    Figura 3.4

    Vom aduga un cotrol TabControl aplicaiei noastre (fig. 3.3).

    Urmeaz s formatm tab-urile existente. Se apas click n zona de lucru a controlului i se modific pentru prima pagin proprietatea Name n tabPGeneral i proprietateaText n setari. Se face click

    35

  • pe al doilea tab i se modific proprietatea Name n tabCalculator i proprietatea Text n calculator. Mai dorim s adugm nc 2 pagini. Pentru aceasta, se slecteaz din nou controlul TabControl i se face click pe proprietatea TabPages. n caseta aprut se apas de dou ori butonul Add (fig. 3.4) pentru a insera 2 noi pagini. Apoi, pentru fiecare pagin n parte, se modific proprietatea Text la editor texte, respectiv agenda i proprietatea Name la pagEditor i pagAgenda. n acest fel, am reuit s dm controlului TabControl aspectul dorit. Urmeaz popularea paginilor controlului TabControl.

    3.4 Controalele ListBox i CheckedListBox Controalele de acest tip sunt utilizate pentru a afia un set de stringuri, din care unul sau mai multe pot fi selectate la un momentdat. Clasa ListBox ofer funcionalitate att controlului ListBox ct controlului ComboBox. Clasa CheckedListBox este derivat din aceasta i adaug fiecrui string din list un control de tip CheckBox, utilizat pentru selectare. Ctve din proprietile furnizate de clasa ListBox sunt: SelectedIndex indic indicele bazat pe 0 a elementului selctat n list, sau a

    primului element selctat n lista, n cazul seleciei multiple. ColumnWidth specific limea coloanelor, n listele cu coloane multiple. Items conne sub forma unei colecii toate elementele stocate n list. Multicolumn specific numrul de coloane din list. SelectedIndices o colecie care conine toi indicii elementelor selectate din

    list. SelectedItem aceast proprietate conine elementul selectat n list dac

    selecia este simpl, respectiv primul elemen selectat din list n cazul seleciei multiple.

    SelectedItems o colecie care conine elementele selectate din list. Sorted dac aceast proprietate este true, elementele vor fi afiate n list n

    ordine alfabetic. CheckedIndices - o colecie care conine indicii elementelor din list care au

    caseta checkbox bifat su n stare nedeterminat (doar pentru CheckedListBox). CheckedItems - o colecie care conine elementele din list care au caseta

    checkbox bifat su n stare nedeterminat (doar pentru CheckedListBox). CheckOnClick dac acaest proprietate este true, starea unui element se

    schimb cnd asupra lui se efectueaz click.

    Cteva din metodele clasei: ClearSelected() terge toate seleciile (nu elementele selectatae!) din list. FindString() caut primul string care ncepe cu irul specificat ca parametru n

    list. GetSelected() returneaz o valoare care specific dac un element este

    selectat. SetSelected() seteaz sau terge selectarea unui element. GetItemChecked() returneaz o valoare care indic faptul c checkbox-ul

    asociat unui elemenz este bifat (doar pentru CheckedListBox). GetItemCheckState() returneaz o valoare care indic starea casetei

    checkbox sociat elementului (doar pentru CheckedListBox).

    36

  • SetItemChecked() seteaz starea casetei checkbox a elmenetului specificat ntr-una din strile posibile (doar pentru CheckedListBox).

    SetItemCheckState() Seteaz starea unui element(doar pentru CheckedListBox).

    Cteva evenimente:

    ItemCheck se produce cnd starea de check a unui element se schimb. SelectedItemChanged se produce la schimbarea indexului elementelor

    selectate.

    i acum, iar la program. S adugm n prima pagina a TabControl-ului2 controale CheckedListBox i 2 butoane, ca n fig. 3.5.

    Figura 3.5

    Fecm urmtoarele modificari de proprieti pentru controale: vom schimba proprietile Name a butoanelor (de sus n jos) n btnAdaug

    respectiv btnSterge i proprietile Text n Adauga-> respectiv Sterge

  • public Form1() { SeteazaIntervalTimp(); Completeaza_LBTotal(); }

    i acum funciile care rspund la apsarea celor 2 butoane: dubli click pe ele i la drum!

    private void btnAdauga_Click(object sender, EventArgs e) { if (this.chkLBTotal.CheckedItems.Count > 0) { this.chkLBExistent.Items.Clear(); foreach (string item in this.chkLBTotal.CheckedItems) { this.chkLBExistent.Items.Add(item.ToString()); } for (int i = 0; i < this.chkLBTotal.Items.Count; i++) this.chkLBTotal.SetItemChecked(i, false); } } private void btnSterge_Click(object sender, EventArgs e) { for (int i=this.chkLBExistent.Items.Count-1; i>=0; i--) if (this.chkLBExistent.GetItemCheckState(i).ToString()=="Checked") this.chkLBExistent.Items.RemoveAt(i); }

    n prima funcie se testeaz nti dac n list exist elemente selectate. Dac da, sterge coninutul celui de-al doilea control CeckedListBox. Apoi, fiecare element aflat n colecia elementelor cu checkbox-ul bifat din prima list este adugat celui de-al doilea control. n final, starea de marcare a checkbox-urilor asociate tuturor elementelor din prima list este tears. Este nevoie ca ciclul se fac descendent, deoarece odat cu tergerea unui obiect indicii acestora se reaeaz. ntr-un ciclu ascendent, va rmne ntotdeauna ultimul obiect neters. De remarcat instruciunea foreach, pe care nu am mai ntlnit-o n C. Sintaxa acestei instruciuni este foreach ( in ) { } i are ca efect parcurgerea tuturor elementelor din din irul de elemente n interiorul unui ciclu. Cea de-a doua funcie, parcurge toate elementele din list, de la indice 0 la indicele maxim i dac sterge fiecare elemen (pe baza indicelui) dac starea checkbox-ukui asociat este marcat.

    38

  • Compilai i executai programul. S ncepem s completm acum urmtoarele tab-uri ale TabControl-ului. Pentru nceput, vom popula pagina calculator. Pentru acesta, s ncerc, s realizm interfaa din fig. 3.6.

    Figura 3.6

    Se observ c pe interfa avem 20 de butoane, un control GroupBox, un control TextBox i un control ListBox (n care este scris textul afisare). Vom asocia controalelor urmtoarele nume: Tabelul 3.1

    Control Control.Text Control.Name Restul proprietilor Button 1 unu BackColor blue, la alegere Button 2 doi BackColor blue, la alegere Button 3 trei BackColor blue, la alegere Button 4 patru BackColor blue, la alegere Button 5 cinci BackColor blue, la alegere Button 6 sase BackColor blue, la alegere Button 7 sapte BackColor blue, la alegere Button 8 opt BackColor blue, la alegere Button 9 noua BackColor blue, la alegere Button 0 zero BackColor blue, la alegere Button +/- semn BackColor blue, la alegere Button . zecimal BackColor blue, la alegere Button + plus BackColor cyan, la alegere Button - minus BackColor cyan, la alegere Button * ori BackColor cyan, la alegere Button / supra BackColor cyan, la alegere Button = egal BackColor red, la alegere Button MS memorystore BackColor red, la alegere

    Image Icon2.ico Button MC memorycall BackColor red, la alegere Button C clear BackColor red, la alegere GroupBox BacColor yellow, la alegere TextBox introducere TextAlign Left

    BackColor blue, la alegere ListBox afisare BackColor blue, la alegere

    S ne reamintim, c toate controalele sunt iniial dezactivate, urmnd a fi activate la trecerea lor n lista de controale active din prima pagin. Vom implementa 2 funcii, una care dezactiveaz controalele de lucru ale calculatorului i alta care le activeaz. n principiu, este suficient s dezactivm controalele de tip buton care introduc numere, astfel nct nu se vor putea introduce operanzi pentru calcul.

    39

  • private void DezactiveazaCalculator() { this.unu.Enabled = false; this.doi.Enabled = false; this.trei.Enabled = false; this.patru.Enabled = false; this.cinci.Enabled = false; this.sase.Enabled = false; this.sapte.Enabled = false; this.opt.Enabled = false; this.noua.Enabled = false; this.zero.Enabled = false; } private void ActiveazaCalculator() { this.unu.Enabled = true; this.doi.Enabled = true; this.trei.Enabled = true; this.patru.Enabled = true; this.cinci.Enabled = true; this.sase.Enabled = true; this.sapte.Enabled = true; this.opt.Enabled = true; this.noua.Enabled = true; this.zero.Enabled = true; }

    La iniializarea formei, calculatorul trebuie s fie dezactivat, deci va trebui s apelm aceast funcie n zona de iniializare a formei. De asemenea, la inserarea numelui paginii n lista chkLBExistent, calculatorul va trebui s se activeze, iar la tergerea din aceast list, calculatorul se va dezactiva.

    public Form1() { DezactiveazaCalculator(); } private void btnAdauga_Click(object sender, EventArgs e) { this.chkLBExistent.Items.Add(item.ToString()); if (item.ToString() == "Calculator") ActiveazaCalculator(); } private void btnSterge_Click(object sender, EventArgs e) { foreach (string item in this.chkLBExistent.CheckedItems) { if (item.ToString()=="Calculator") DezactiveazaCalculator(); } }

    40

  • Ce face codul implementat n cele 2 funcii? n btnAdauga_Click(), dup adugarea fiecrui element n lista chkLBExistent, numele elementului se transform n ir de caractere. Dac irul este Calculator, se activeaz calculatorul. Funcia btnSterge_Click() efectueaz aceleai operaii. Se verific toate elementele din lista chkLBExistent bifate i nainte de afi terse, se dezactiveaz obiectele din paginile corespunztoare (n cazul nostru, deocamdat doar calculatorul).

    Acum, va trebui s definim handlerii care leag evenimentele Click produse de butoane de funciile corespunztoare. Vom implementa n fapt o singur funcie, care va rezolva n totalitate funcionalitatea calculatorului. Adugm zonei de iniializare a formei codul:

    public Form1() { DezactiveazaCalculator(); this.unu.Click += new EventHandler(this.buton_Click); this.doi.Click += new EventHandler(this.buton_Click); this.trei.Click += new EventHandler(this.buton_Click); this.patru.Click += new EventHandler(this.buton_Click); this.cinci.Click += new EventHandler(this.buton_Click); this.sase.Click += new EventHandler(this.buton_Click); this.sapte.Click += new EventHandler(this.buton_Click); this.opt.Click += new EventHandler(this.buton_Click); this.noua.Click += new EventHandler(this.buton_Click); this.zero.Click += new EventHandler(this.buton_Click); this.zecimal.Click += new EventHandler(this.buton_Click); this.semn.Click += new EventHandler(this.buton_Click); this.plus.Click += new EventHandler(this.buton_Click); this.minus.Click += new EventHandler(this.buton_Click); this.ori.Click += new EventHandler(this.buton_Click); this.supra.Click += new EventHandler(this.buton_Click); this.egal.Click += new EventHandler(this.buton_Click); this.clear.Click += new EventHandler(this.buton_Click); this.memorystore.Click += new EventHandler(this.buton_Click); this.memorycall.Click += new EventHandler(this.buton_Click); }

    Se poate observa c, indiferent de butonul apsat, va fi lansat n execuie aceeai funcie, buton_Click(). S implementm acum aceast funcie:

    private void buton_Click(object sender, EventArgs e) { if (sender == unu) CitesteButon("1"); if (sender == doi) CitesteButon("2"); if (sender == trei) CitesteButon("3"); if (sender == patru) CitesteButon("4"); if (sender == cinci) CitesteButon("5"); if (sender == sase) CitesteButon("6"); if (sender == sapte) CitesteButon("7"); if (sender == opt) CitesteButon("8"); if (sender == noua) CitesteButon("9"); if (sender == zero) CitesteButon("0"); if (sender == zecimal) CitesteButon(",");

    41

  • if (sender == semn) { if (prim) { if (snr1.Length == 0) snr1 += "-"; else if (snr1[0] != '-' && snr1[0] != '+') snr1 = snr1.Insert(0, "-"); else if (snr1 == "-") snr1 = snr1.Replace("-", "+"); else snr1 = snr1.Replace("+", "-"); } else { if (snr2.Length == 0) snr2 += "-"; else if (snr2[0] != '-' && snr2[0] != '+') snr2 = snr2.Insert(0, "-"); else if (snr2 == "-") snr2 = snr2.Replace("-", "+"); else snr2 = snr2.Replace("+", "-"); } } if (sender == plus) { Operatie("+", 1); } if (sender == minus) { Operatie("-",2); } if (sender == ori) { Operatie("*", 3); } if (sender == supra) { Operatie("/", 4); } if (sender == egal) { switch (op) { case 1: rez = Convert.ToDouble(snr1) + Convert.ToDouble(snr2); break; case 2: rez = Convert.ToDouble(snr1) - Convert.ToDouble(snr2); break; case 3: rez = Convert.ToDouble(snr1) * Convert.ToDouble(snr2); break; case 4: rez = Convert.ToDouble(snr1) / Convert.ToDouble(snr2); break; } snr2 = ""; snr1 = Convert.ToString(rez); afisare.Items.Add("--------- "); afisare.Items.Add(snr1); op = 0; }

    42

  • if (sender == clear) { snr1 = ""; rez = 0; prim = true; } if (sender == memorystore) { memory = rez; if (memory == 0) memorystore.Image = Image.FromFile("/Icon2.ico"); else memorystore.Image = Image.FromFile("/Icon7.ico"); } if (sender == memorycall) if (prim) snr1 = Convert.ToString(memory); else snr2 = Convert.ToString(memory); if ((sender == plus) || (sender == minus) || (sender == ori) || (sender == supra) || (sender== egal) || (prim)) introducere.Text = snr1; else introducere.Text = snr2; }

    nainte de a vedea cum funcioneaz aceast funcie, va trebui s declarm variabilele de lucru utilizate i s implementm funciile apelate. Vom declara urmtoarele variabile:

    public partial class Form1 : Form { string snr1 = "", snr2=""; double rez, memory; int op; bool prim = true;

    va fi completat cu p t timpul rezultatul o ilea operand. Sunt v la double pentru e se face referitor la s l care s specifice f asta este prim, care v roducerea primului o double va fi stocat re va fi stocat n m anzilor, va trebui s l re:2, nmulire:3 i r public Form1()

    Variabilele snr1 i snr2 reprezint cei 2 operanzi. snr1 rimul operand, la prima introducere i n plus, va menine toperaiilor efectuate. snr2 va conine ntotdeauna cel de-al doariabile de tip string, deci valorile lor vor trebui convertitefectuarea operaiilor. Cum ntotdeauna prima introducere de datenr1 i apoi toate celelalte la snr2, vom avea nevoie de o variabiaptul c valoarea introdus este primul operand, sau al doilea. Acea lua valoarea true nainte de prima introducere, odat cu intperand ea fiind facuta false. Rezultatul fiecrei operaii, n formatn rez, iar valoarea memorat la apsarea butonului memorystoemory. Pentru a putea identifica operaiile executate asupra oper

    e codificm. Vom codifica operaiile astfel: adunare: 1, scdeespectiv mprire:4.

    Funcia CitesteButon() are implementarea: 43

  • private void CitesteButon(string s) { if (prim) snr1 += s; else snr2 += s; }

    Funcia primete ca parametru un ir de caractere. Dac prim==true, l adaug la snr1, altfel la snr2. n acest fel, se permite completarea irurilor de caractere care conin cei 2 operanzi. Funcia Operaie() are implementarea:

    private void Operatie(string s, int oper) { if (prim) { prim = false; } else { switch (op) { case 1: rez = Convert.ToDouble(snr1) + Convert.ToDouble(snr2); break; case 2: rez = Convert.ToDouble(snr1) - Convert.ToDouble(snr2); break; case 3: rez = Convert.ToDouble(snr1) * Convert.ToDouble(snr2); break; case 4: rez = Convert.ToDouble(snr1) / Convert.ToDouble(snr2); break; } snr2 = ""; snr1 = Convert.ToString(rez); } afisare.Items.Add(snr1 + s); op = oper; }

    S explicm puin funcia. Ea este lansat n execuie doar la apsarea butoanelor care definesc operaii aritmetice, adic doar dup ce cel puin un operand este introdus. Dac deja s-a introdus un operand, prim este facut false pentru ca urmtorul operand s fie stocat n snr2. Apoi se calculeaz rezultatul (dar doar dac exist ambii operanzi), se stocheaz i n snr1 pentru operaiile urmtoare i se salveaz n op codul operaiei. Operaia ce se va executa este ntotdeauna cea stocat n op. De asemenea, rezultatul i semnul operaiei (primit ca i parametru) este afiat n controlul list. i acum s trecem la funcia lansat la apsarea butoanelor. Dac butonul care a lansat-o este un buton numeric, valoarea acestuia se adaug la snr1 sau snr2, n funcie de valoarea lui prim. Dac butonul este semn, se adaug sau + n faa lui snr1 sau snr2, n funcie de valoarea lui prim. Dac irul este gol sau nu exist semn, se adaug pe prima poziie -, altfel se schimb semnul existent cu cel complementar. Dac butonul care a lansat n execuie funcia este un buton de operaie aritmetic, se memoreaz codul operaiei i se execut operaia anterioar, conform funciei Operatie(). Dac butonul este =, se execut ultima operaie, se afieaz rezultatul n controlul ListBox i se actualizeaz sir1 cu valoarea rezultatului pentru operaii ulterioare. De asemnea, op este setat la o valoare care nu reprezint o operaie

    44

  • aritmetic, pentru ca operaia s se efectueze doar dup introducerea urmtorului operand. Dac butonul este clear, se marcheaz prim=true pentru ca toate operaiunile s fie reiniializate i se terge rezultatul i irul snr1, pentru a-l pregti s primeasc un nou operand. Dac butonul este memorystore, se salveaz rezultatul n variabila tampon memory. De asemenea, se schimb pictograma de pe buton n cerc verde, pentru a marca faptul c n memorie exist o valoare utilizabil. Stocarea n memorie a valorii 0 este echivalent cu tergerea memorie, deci va fi afiat din nou pictograma cerc roi. Dac butonul este memorycall, valoarea stocat n memorie va fi ncrcat (dup conversie) n snr1 sau snr2, n funcie de valoarea lui prim. Dac funcia a fost lansat n execuie de un buton operaie aritmetic, sau a fost introdus primul operand, n controlul TextBox este afiat valoarea lui snr1 (s ne reamintim c n cazul operaiilor aritmetice acesta menine i rezultatul). Altfel, este afiat operandul nou introdus, adic snr2. Compilai i executai programul.

    3.6 Controlul RichTextBox Este un control asemntor cu controlul TextBox, dar permite afiarea de texte formatate. Cteva din proprietile acestui control sunt: CanRedo aceast proprietate este true dac a fost executat o aciune undo n

    interiorul controlului. CanUndo aceast proprietate este true dac n interiorul controlului se poate

    executa o aciune undo. RedoActionName proprietatea stocheaz numele aciunii care a fost utilizat

    pentru a executa redo asupra a ceva care a fost fcut undo. DetectUrls dac aceast proprietate este true, controlul este capabil s

    detecteze url-uri i s le formateze (s le sublinieze, la fel ca i n browser) Rtf este echivalent cu proprietatea Text din TextBox, dar conine un text

    formatat. SelectedRtf aceast proprietate poate fi utilizat pentru a prelua sau a

    introduce text formatat din/n control. Dac de exemplu textul preluat va fi introdus n MsWord, i va pstra formatul.

    SelectedText la fel ca i proprietatea anterioar, dar textul este neformatat, deci orice informaii asupra formatului acestuia se vor pierde.

    SelectionAlignment reprezint alinierea textului selectat. Poate fi Left, Center sau Right.

    SelectionBullet proprietatea poate fi utilizat dac textul este formatat cu bullets sau poate fi utilizat pentru adugarea sau tergerea unei asemenea formatri.

    BulletIndent specific numrul de pixeli pn la bullet, de la marginea stng a controlului.

    SelectionColor permite schimbarea culorii textului selectat. SelectionFont permite schimbarea fonturilor textului selctat. SelectionLength permite setarea sau obinerea lungimii textului selectat. SelectionType conine informaii cu privire la tipul obiectelor selectate.

    45

  • ShowSelectionMargin dac aceast proprietate este true, o margine va fi afiat n stnga controlului pentru a uura selectarea textului.

    UndoActionName precizeaz numele aciunii ce se va efectua dac utilizatorul execut un undo.

    SelectionProtected permite specificarea cror pri din text s nu poat fi schimbate, prin setarea la true a acestei proprieti.

    Controlul poate genera o serie de evenimente, dintre care putem aminti:

    LinkedClick este generat cnd utilizatorul face click pe un link din text. Protected este generat atunci cnd utilizatorul ncearc s modifice un text

    care a fost protejat. SelectionChanged este generat cnd textul selectat n interiorul controlului se

    schimb.

    i acum s vedem cum funcioneaz controlul. Pentru aceasta, s completm tab-ul editor texte ca n fig. 3.7.

    Figura 3.7

    Se pot observa 10 controale de tip Button i un control RichTextBox. Vom asocia controalelor urmtoarele nume (pentru butoane de la stnga la dreapta): Tabelul 3.2

    Control Control.Image/Text Control.Name Button /FileSave.bmp btnSave Button /FileOpen.bmp btnOpen Button B btnBold Button I btnItalic Button U btnUnderline Button /Left.bmp btnLeft Button /Center.bmp btnCenter Button /Right.bmp btnRight Button /Color.bmp btnCuloare Button Font btnFont RichTextBox rtbText

    Fiierele de tip Bitmap cu imaginile de pe butoane pot fi descrcate de pe pagina cursului (directorul Butoane). Acum, haideti s apsm dublu-click pe fiecare din butoane, pentru a genera funciile care se execut la apsarea lor i s le implementm. Vom ncepe cu btnBold, btnItalic i btnUnderline din considernte de simplitate. Celelalte butoane necesit nite cunotine suplimentare, pe care le vom descrie n cele ce urmeaz.

    46

  • private void btnBold_Click(object sender, EventArgs e) { Font oldFont, newFont; oldFont = this.rtbText.SelectionFont; newFont=new Font(oldFont, oldFont.Style ^ FontStyle.Bold); this.rtbText.SelectionFont = newFont; this.rtbText.Focus(); } private void btnItalic_Click(object sender, EventArgs e) { Font oldFont, newFont; oldFont = this.rtbText.SelectionFont; newFont = new Font(oldFont, oldFont.Style ^ FontStyle.Italic); this.rtbText.SelectionFont = newFont; this.rtbText.Focus(); } private void btnUnderline_Click(object sender, EventArgs e) { Font oldFont, newFont; oldFont = this.rtbText.SelectionFont; newFont = new Font(oldFont, oldFont.Style ^ FontStyle.Underline); this.rtbText.SelectionFont = newFont; this.rtbText.Focus(); }

    Cele trei funcii sint oarecum similare. nti, definesc doua obiecte de clas Font, oldFont i respectiv newFont. n obiectul oldFont se salveaz fontul implicit din zona de text selectat. Apoi, se creaz un nou font, care se ncarc n obiectul newFont. Contructorul clasei Font are prototipul Font(Famile de fonturi, Stilul fontului) Se observ c n constructor se pstreaz aceeai familie ca i fontul din textul selctat (cu alte cuvinte nu se schimb fontul) dar, stilul vechiului font este supus unei operaii ^ (SAU exclusiv) cu stilul corespunztor funciei (Bold, Italic respectiv Underline). S ne reamintim c funcia SAU exclusiv pe bit are urmtorul tabel de adevr: ^ 0 1 0 0 1 1 1 0

    Ce nseamn asta? Prin SAU exclusiv, dac stilurile sunt identice, se terge stilul, iar dac stilurile sunt diferite, se aplic stilul. Adic dac textul selectat este normal i se apas de exemplu Bold, textul va fi fcut bold. Dar dac textul selectat era bold, acest stil se terge i textul redevine normal. Apoi, fontul nou este aplicat textului selectat i focusul este redat controlului. Tot relativ simplu sunt de implementat i funciile care aliniaz textul. private void btnLeft_Click(object sender, EventArgs e) { this.rtbText.SelectionAlignment = HorizontalAlignment.Left; this.rtbText.Focus(); }

    47

  • private void btnCenter_Click(object sender, EventArgs e) { this.rtbText.SelectionAlignment = HorizontalAlignment.Center; this.rtbText.Focus(); } private void btnRight_Click(object sender, EventArgs e) { this.rtbText.SelectionAlignment = HorizontalAlignment.Right; this.rtbText.Focus(); }

    Aceste funcii nu au nevoie de explicaii suplimentare. Ca s implementm aciunile butoanelor btnColor i btnFont, btnOpen i btnSave va trebui s discutm nti despre

    3.7 Casete de dialog Casetele de dialog sunt ferestre care sunt afiate n contextul altor ferstre. Sunt utilizate n general atunci cnd programul necesit un set de informaii suplimentare de la utilizator. Pentru a afia un astfel de control, se va utiliza metoda ShowDialog(), dup cum se va vedea n continuare. La rentoarcerea n fereastra principal, caseta de dialog va returna un cod, care n general poate fi DialogResult.OK dac modificrile fcute n caseta de dialog se confirm, respectiv DialogResult.Cancel dac acestea se anuleaz.

    Figura 3.9

    Figura 3.8

    3.7.1 FontDialog Caseta de dialog FontDialog este prezentat n fig. 3.8. Se poate observa c prin intermediul ei se poate alege tipul de font, dimensiunea fontului precum i stilul fontului. Aceast caset dorim s-o lansm la apsarea butonului btnFont.

    private void btnFont_Click(object sender, EventArgs e) { FontDialog dlgFont = new FontDialog(); if (dlgFont.ShowDialog() == DialogResult.OK) this.rtbText.SelectionFont = dlgFont.Font; this.rtbText.Focus(); }

    48

  • Funcia creeaz un obiect FontDialog, numit dlgFont. Apoi, l afieaz cu ajutorul finciei ShowDialog(). Aceasta va implementa n totalitate funcionalitatea casetei de dialog. Dac la ieire a fost appsat butonul OK, textului selectat i se schimb fontul n cel ales i returnat de caseta de dialog.

    3.7.2 ColorDialog Caseta de dialog ColorDialog este prezentat n fig. 3.9. Ea permite alegerea culorilor dintr-un set predefinit, sau definirea de culori utilizator. Modul de manifestare este similar casetei de dialog precedente. Deci, implementarea funciei btnCuloare_Click() va fi:

    private void btnCuloare_Click(object sender, EventArgs e) { ColorDialog dlgColor = new ColorDialog(); if (dlgColor.ShowDialog() == DialogResult.OK) this.rtbText.SelectionColor = dlgColor.Color; this.rtbText.Focus(); }

    Singura deosebire fa de funcia anterioar este faptul c nu se schimb fontul textului selectat, ci culoarea returnat la ieirea din caseta de dialog.

    3.7.3 OpenFileDialog Infrastructura C# ofer casete de dialog pentru manipularea numelor de fiiere. O astfel de caset este OpenFileDialog (fig. 3.10).

    Figura 3.10

    Figura 3.11

    n aceast caset se poate cuta numele unui fiier existent sau aduga un nou nume. De aseemenea, se permite specificarea tipului de fiier care urmeaz s fie ncrcat. Pentru specificarea tipurilor de fiiere acceptate, trebuie construit un filtru, dup urmtorul mecanism: mesaj1 | tip1 fiier | mesaj2 | tip2 fisier | | mesajn | tipn fiier ; Acest filtru trebuie aplicat casetei de dialog dup creare cu instruciunea new, dar nainte de afiare cu funcia ShowDialog(). Permite utilizarea aa numitelor wildcards (semnele ? , respectiv *). Caseta de dialog ofer o serie de proprieti utile pentru utilizator. Cteva din acestea sunt:

    49

  • Title permite modificarea textului afiat n bara de titlu a casetei de dialog; FileName numele fiierului (fiierelor) selectate;

    Deoarece fiierele sunt entiti externe programului, ncercarea de accesare a unui fiier cu nume eronat poate duce la erori n cadrul programului, respectiv la oprirea lui forat de ctre sistemul de operare. De aceea, nainte de a implementa funcia care se execut la apsarea butonului btnOpen, mai trebuie s vorbim despre

    3.7.4 Excepii Complexitatea aplicaiilor actuale, n special a celor orientate pe obiecte,

    presupune o modularizare pe nivele ierarhice. Aceast situaie impune tratarea deosebit de riguroas a situaiilor deosebite, n special a erorilor care pot s apar la nivelul diferitelor componente ale unui proiect. n cele ce urmeaz, vom nelege prin excepie o situaie deosebit care poate s apar pe parcursul execuiei unei componente soft parte a unei aplicaii. Erorile pot fi privite ca i un caz particular de excepii, dar n general nu toate excepiile sunt erori. Excepiile se mpart n dou categorii: excepii sincrone i excepii asincrone. Excepiile sincrone sunt excepii a cror apariie poate fi prevzut de programator (de exemplu, un fiier care se dorete a fi prelucrat nu se afl n directorul ateptat). Excepiile asincrone sunt excepii a cror apariie nu poate fi prevzut n momentul implementrii programului (de exemplu, defectarea accidental a hard-disk-ului). Mecanismul de tratare a excepiilor ia n considerare numai situaia excepiilor sincrone.

    Problema se pune astfel: n faza de programare, se poate presupune c un modul de program va detecta n anumite situaii o excepie, dar nu va putea oferi o soluie general de tratare a acesteia, n timp ce un alt modul al aplicaiei poate oferi o soluie de tratare a excepiei, dar nu poate detecta singur apariia excepiilor.

    Exemple tipice de excepii: mprire cu 0, accesul la un fiier inexistent, operaii cu o unitate logic nefuncional, etc.

    Uzual, la pariia unei excepii, sistemul de operare va opri forat execuia modului de program n care excepia s-a produs, pentru ca acesta s nu afecteze buna funcionare a celorlalte programe. De multe ori ns este necesar ca excepia aprut s nu fie transmis sistemului de operare, ci s fie prins i tratat n interiorul modulului care a generat-o. Acest lucru este posibil prin intermediul unui mecanism bazat pe 2 instruciuni: try i catch.

    Mecanismul este urmtorul: zona critic, adic zona de cod n care programatorul prevede posibilitatea apariiei unei excepii este scris ntr-un bloc try. Blocul try este urmat de unul su mai multe blocuri catch, cte unul pentru fiecare tip de execepie ce poate s apar. Execuia programelor n acest caz este prezentat n fig. 3.11 a i b.

    Fig. 3.11 a prezint situaia normal de execuie, cnd n seciunea critic nu

    apare excepie. n acest caz, se execut n succesiune normal toate instruciunile din seciunea critic, dup care, urmtoarea instruciune executat este prima de dup blocul catch, acesta fiind neglijat.

    50

  • try { Seciune critic } catch ( TipExceptie e) { }

    try { excepie } catch ( TipExceptie e) { }

    a b Figura 3.11

    Fig. 3.11 b prezint situaia apariiei unei excepii. n acest caz, urmtoarea unstruciune executat dup cea care a generat excepia este prima din blocul catch, n acesta urmnd a fi tratat excepia. Dup execuia instruciunilor din blocul catch, se continu n secven normal, cu prima instruciune de dup acesta. Marea majoritate a claselor care lucreaz cu entiti externe memoriei genereaz excepii, pentru ca posibilele erori s poat fi tratate nc din faza de programare. Este i cazul claselor care lucreaz cu fiiere i este indicat ca toate operaiile fcute asupra fiierelor s fie tratate prin mecanismul try-catch. Cu aceasta, putem implementa funcia btnOpen_Click():

    private void btnOpen_Click(object sender, EventArgs e) { OpenFileDialog dlgOpen = new OpenFileDialog(); dlgOpen.Title = "Deschide fisier"; dlgOpen.Filter = "Rich Text (*.rtf)|*.rtf | All Files | *.*"; if (dlgOpen.ShowDialog() == DialogResult.OK) { try { rtbText.LoadFile(dlgOpen.FileName); } catch (SystemException err) { MessageBox.Show(err.Message); } } }

    S o explicm puin. La nceput se creeaz o nou caseta OpenFileDialog, numit dlgOpen. Acesteia i se schimb titlul n Deschide fisier i se creeaz un filtru, astfel nct s se poat selecta fiiere de tip *.rtf, sau *.*. Apoi caseta este dechis i se verific revenirea cu OK. Dac s-a revenit cu OK, se ncarc fiierul cu numele returnat de dlgOpen n proprietatea FileName, dar ntr-o secven critic. Orice eroare

    51

  • va genera o excepie de clas SystemException, care este prins n blocul catch i este afiat mesajul asociat erorii, generat de obiectul de clas SystemException.

    3.7.5 SaveFileDialog n figura 3.10 este prezentat caseta de dialog SaveFileDialog. Aceasta permite salvarea cu un nume ales sau dat a unui fiier. Modul de lucru cu aceast caset de dialog este absolut similar casetei OpenFileDialog. Deci, funcia care se execut la apsarea butonului btnSave va fi:

    private void btnSave_Click(object sender, EventArgs e) { SaveFileDialog dlgSave = new SaveFileDialog(); dlgSave.Title = "Salveaza fisier"; dlgSave.Filter = "Rich Text (*.rtf)|*.rtf|All Files | *.*"; if (dlgSave.ShowDialog() == DialogResult.OK) { try { rtbText.SaveFile(dlgSave.FileName); } catch (SystemException err) { MessageBox.Show(err.Message); } } }

    ncercai s explicai singuri codul acestei fincii. Compilai i executai programul.

    3.8 List View Control Mai avem de implementat agenda. Pentru aceasta, vom studia un nou control, numit ListView. Acest control este uzual folosit pentru a permite utilizatorului s aib control asupra detaliilor i stilului de prezentare. Datele pot fi prezentate tabelar, pe linii i coloane, sub forma de gril, ntr-o singur coloan sau avnd asociate diferite pictograme (ImageList control). Similar celorlalte controale, ListView ofer un set de proprieti, metode i evenimente. Cteva din proprieti sunt: Activation pe baza acestei proprieti, utilizatorul poate controla modul de

    activare al unui element de list. Valorile posibile sunt: Standard mod de activare standard. OneClick un click asupra elementului de list are ca efect activarea lui. TwoClick - dublu click asupra elementului de list are ca efect activarea lui.

    Alignment specific alinierea elementelor de list. Sunt posibile 4 valori: Default dac utilizatorul efectueaz un drag-and-drop asupra unui element

    de list, el rmne acolo unde a fost pus de utilizator. Left elementele sunt aliniate spre stnfa n control. Top elementele sunt aliniate spre partea de sus a controlului. SnapToGrid elementele sunt aliniate n interuorul unei grile invizibile.

    52

  • AllowColumnReorder dac aceast proprietate este true, ordinea coloanelor n list poate fi schimbat n timpul execuiei programului. n acest caz trebuie acordat o atenie sporit funciilor care insereaz elemente n ListView, pentru ca inserarea s se fac n coloana potrivit.

    Autoarrange dac aceast proprietate este true, elementele de list se vor aranja singure conform valorii din proprietatea Alignment. Acesat proprietate funcioneaz doar dac proprietatea View este LargeIcon sau SmallIcon.

    CheckBoxes dac aceast proprietate este true, fiecare element de list va avea un checkbox n stnga. Funcioneaz doar dac proprietatea View este Details sau List.

    CheckedIndices, CheckedItems aceste proprieti reprezint colecii care stocheaz indicii elementelor, respectiv elementele care sunt bifate n list.

    Columns permite accesul la o colecie de coloane din list, permind tergerea sau adugarea de coloane.

    FocusedItem menine elementul care are focusul n interiorul listei. FullRowSelect dac aceast proprietate este true, la selectarea unui element se

    selecteaz ntreaga linie din care face parte. Dac este false, se selecteaz doar elementul asupra cruia s-a fcut click.

    GridLines - dac acaest proprietate este true, controlul va afia o gril de demarcare a liniilor i coloanelor. Funcioneaz doar dac proprietatea View este Details

    HeaderStyle permite specificarea modului de afiare a capetelor de coloane. Poate avea valorile: Clickable capetele de tabel funcioneaz ca i nite butoane NonClickable capetele de tabel nu rspund la apsarea butonului mousului. None capetele de tabel nu sunt afiate.

    Items colecia de elemente de list. LabelEdit dac este true, utilizatorul poate edita coninutul primei coloane ntr-

    o list cu View pus pe Details. LargeImageList proprietatea stocheaz ImageList care stocheaz la rndul ei

    imaginile. Funcioneaz dac View este LargeIcon. MultiSelect dac este true, este permis selectarea simultan a mai multor

    elemente de list. Scrollable dac este true, se afieaz bare de defilare. SelectedIndices, SelectedItems - aceste proprieti reprezint colecii care

    stocheaz indicii elementelor, respectiv elementele selectate n list. SmallImageList - proprietatea stocheaz ImageList care stocheaz la rndul ei

    imaginile. Funcioneaz dac View este SmallIcon. Sorting controlul poate sorta elementele de list nainte de afiare. Poate fi: Ascending Descending None

    TopItem returneaz elementul din capul listei. View precizeaz modul de afiare a elementelor n list. Poate fi: LargeIcon toate elementele sunt afiate cu o pictogram mare (32x32 pixeli)

    i o etichet. SmallIcon - toate elementele sunt afiate cu o pictogram mic (16x16 pixeli)

    i o etichet.

    53

  • List afiarea se face pe o singur coloan, care poate conine o pictogram i o etichet.

    Details afiarea se poate face pe oricte coloane, dar doar prima coloan poate conine pictograme.

    Cteva din metodele ce pot fi executate de control sunt:

    Add() adaug elemente de list. BeginUpdate() prin apelarea acestei metode, controlul ListView va nceta

    desenarea liniilor actualizate pn cnd va fi apelat metoda EndUpdate(). Aceast metod evit plpirea ecranului atunci cnd sunt inserate mai multe elemnte simultan i crete viteza de actualizare a listei.

    Clear() terge toate elementele listei. EndUpdate() termin actualizarea listei i toate elementele sunt afiate.

    Cteva din elementele mai semnificative generate de control:

    ColumnClick este generat atunci cnd se face click pe o coloana. ItemActivate este generat etunci cnd un element de list este activat

    i acum s construim agenda pe baza celor prezentate mai sus. Pentru nceput, vom aduce la tab-ul Agenda un control ListView. Pentru acesta vom schimba proprietatea Name n listAgenda, vom pune View pe Details i GridLines pe true. Vom aduga i un control ImageList, dar de data aceasta nu prind drag-and-drop, ci apsnd dublu click pe el. l gsii la seciunea Components al toolbox-ului. Pentru acest control vom schimba proprietatea Name n iList, iar la colecia Images vom aduga fiierele Intrebare.ico i Exclamare.ico (click n partea dreapt a proprietii, click pe butonul cu 3 puncte aprut i apoi Add i navigare pn sii fiierele) pe care le gsii n directorul Butoane din cadrul proiectului.

    Mai trebuie s adugm lista de imagini controlului ListView. Pentru acesta, la

    proprietatea SmallImageList a controlului listAgenda, selectai iList. Cu aceasta, am cam terminat cu proprietile. S trecem la funcii.

    Figura 3.12

    54

  • Primul lucru care avem de fcut este s activm, respectiv s dezactivm controlul ListView. Vom implementa deci funciile

    private void ActiveazaAgenda() { this.listAgenda.Enabled = true; } private void DezactiveazaAgenda() { this.listAgenda.Enabled = false; }

    Va trebui acum s dezactivm implicit controlul i s implementm funcionalitatea butoanelor Adauga i Sterge:

    public Form1() { DezactiveazaEditor(); DezactiveazaAgenda(); } private void btnAdauga_Click(object sender, EventArgs e) { foreach (string item in this.chkLBTotal.CheckedItems) { ... if (item.ToString() == "Editor texte") ActiveazaEditor(); if (item.ToString() == "Agenda") ActiveazaAgenda(); } } private void btnSterge_Click(object sender, EventArgs e) { foreach (string item in this.chkLBExistent.CheckedItems) { if (item.ToString() == "Editor texte") DezactiveazaEditor(); if (item.ToString() == "Agenda") DezactiveazaAgenda();

    ntm o funcie care definete capul de tabel i p a coloan a listei. Vom numi aceast funcie G area de mai jos. complet toate elementele din list. Apoi ncepe cc } }

    Acum urmeaz s implemeopuleaz cu intervale orare primenerezOre() i va avea implement

    Funcia ncepe prin a terge

    onstrucia capului de list, prin definirea unor capete de coloan, care sunt obiecte de las ColumnHeader. Fiecare apel new ColumnHeader() va defini o nou coloan n

    55

  • private void GenerezOre() { listAgenda.Items.Clear(); ColumnHeader capLista; capLista = new ColumnHeader(); capLista.Text = "Orele"; capLista.Width = 70; capLista.TextAlign = HorizontalAlignment.Center; this.listAgenda.Columns.Add(capLista); capLista = new ColumnHeader(); capLista.Text = "Activitate"; capLista.Width = listAgenda.Width-70; capLista.TextAlign = HorizontalAlignment.Center; this.listAgenda.Columns.Add(capLista); ListViewItem ore; this.listAgenda.BeginUpdate(); try { for (int i = 8; i
  • Funcia GenerezOre(), va trebui apelat la iniializarea formei, pentru a completa prima coloan i ori de cte ori se schimb data n controlul MonthCalendar. Vom insera apelul acestei funcii astfel:

    public Form1() { DezactiveazaAgenda(); GenerezOre(); } ... private void Data_SchimbareData(object sender, DateRangeEventArgs e) { this.Data.TodayDate = this.Data.SelectionStart; CompleteazaData(); GenerezOre(); }

    Compilai i executai programul. Se poate observa modul de afiare a listei. n mod normal, inserarea unei activiti n agend se face pri apsarea dublu-click asupra elementului care reprezint intervalul orar. Un dubli click asupra unui element de list, va genera evenimentul ItemActivate. Acest eveniment va trebui s-l interceptm i s-i asociem o funcie. Cum? tim deja foarte bine. nti construim un handler:

    public Form1() { GenerezOre(); listAgenda.ItemActivate +=new EventHandler(listAgenda_ItemActivate); }

    Acest handler, dup cum tim deja, la fecare dublu-click asupra unui element de list, va lansa n execuie funcia listAgenda_ItemActivate(). n mod normal, introducerea textului nu se face direct n list, ci ntr-o nou form, ce va fi lansat ca un DialogBox utilizator, pentru a se putea face validarea sau invalidarea textului introdus. Deci, nainte de a implementa funcia, s vedem cum putem construi o nou form pe care s-o definim ca DialogBox.

    3.8.1 Adugarea unui DialogBox utilizator Pentru definirea unui DialogBox particularizat, va trebui nti s adugm proiectului o nou form. Pentru aceasta, n SolutionExplorer se apas click dreapta pe rdcina proiectului (trei) i n meniul contextual se alege Add i apoi WindowsForm (fig. 3.13). Prin alegerea acestei opiuni, va fi afiat caseta Add New Item care ne va permite s alegem ce dorim s adugm proiectului dintr-o colecie de abloane. Vom alege i n acerst caz Windows Form i vom apsa butonul Add. O nou form este asociat n acest moment proiectului. Urmeaz s construim interfaa asociat acestei forme: vom aduga 2 controale Button, trei controale Label i trei controale TextBox, pentru a obine interfaa din fig. 3.15. Controalelor active le vom asocia proprietile Name i Text (de sus n jos) ca n tabelul 3.3.

    57

  • Figura 3.13

    Figura 3.14

    Tabelul 3.3 Control Text Name ReadOnly

    Button OK btnOK false Button Cancel btnCancel false TextBox txtData true TextBox txtOra true TextBox txtMes false

    Figura 3.15

    Acum va trebui s definim forma ca fiind DialogBox. Pentru aceasta, n Properties, se modific proprietatea FormBorderStyle n FixedDialog. n acest moment, forma este interpretat de ctre infrastructur ca fiind un DialogBox, deci va putea fi lansat prin intermediul funciei ShowDialog(). Mai trebue s definim funcionalitatea butoanelor btnOK i btnCancel, n aa fel nct la apsare s returneze DialogResult.OK, respectiv DialogResult.Cancel. Pentru aceasta, pentru fiecare buton n parte, proprietatea DialogResult se alege ca OK pentru btnOK i respectiv Cancel pentru btnCancel. Cu aceasta, din punctul de vedere al Windows Form Designer, noul

    58

  • D area f din f . De a orar c ctele utea a e de f cu c ext), c t i, r lului t plu: c vom s

    iialogBox este complet definit. Dar noi, mai avem o problem. Dorim ca la lansormei, n txtData.Text s fie scris data selectat n controlul MonthCalendarorma principal, iar n txtOra.Text s fie trecut intervalul orar din listAgendasemenea, la revenirea din DialogBox, s trecem n listAgenda, la intervalul orespunztor, coninutul txtMes.Text. Problema apare datorit faptului c obiei proprietile obiectelor sunt declarate private n fiecare form, adic nu vom pccesa direct obiecte su proprieti din forma principal n Form2 i reciproc. Cecut? Soluia e simpl. n Form2 vom implementa funcii publice de lucruontroalele. Astfel, vom avea 2 funcii SetData(String text) i SetOra(String tare vor nscrie n proprietatea Text a controalelor textul primit ca argumenespectiv GetMessage(), care va returna coninutul proprietii Text a controxtMes. Pentru a le implementa, vom intra n zona de cod a Form2 (cum? Simlick n Solution Explorer pe Form2.cs i apoi pe butonul care ne duce n cod) i crie urmtoarele linii de cod: public partial class Form2 : Form { public Form2() { InitializeComponent(); } public void SetData(String text) { this.txtData.Text = text; } public void SetOra(String text) { this.txtOra.Text = text; } public String GetMessage() { return this.txtMes.Text; } }

    Cu aceasta, definirea casetei DialogBox este complet. Putem trece la mplementarea funciei listAgenda_ItemActivate() din forma principal. private void listAgenda_ItemActivate(object sender, EventArgs e) { Form2 frm2 = new Form2(); frm2.SetData(EData.Text); ListView.SelectedIndexCollection indexes = this.listAgenda.SelectedIndices; this.listAgenda.BeginUpdate(); foreach (int index in indexes) { frm2.SetOra(this.listAgenda.Items[index].Text); this.listAgenda.Items[index].ImageIndex = 1; } if (frm2.ShowDialog() == DialogResult.OK) { ListViewItem.ListViewSubItem mes; mes = new ListViewItem.ListViewSubItem();

    59

  • mes.Text = frm2.GetMessage(); ListView.SelectedListViewItemCollection items = this.listAgenda.SelectedItems; foreach (ListViewItem item in items) { item.SubItems.Add(mes); } } this.listAgenda.EndUpdate(); }

    Ce face funcia? La nceput construiete un nou obiect Form2, numit frm2. Pentru acest obiect, apeleaz frm2.SetData() pentru a completa frm2.txtData.Text cu data selectat. Declar apoi un obiect de clas ListView.SelectedIndexCollection, care reprezint o colecie de elemente de indici ai elementelor de list selectate i populeaz aceast list cu indicii elementelor selectate n listAgenda (n cazul nostru, doar indicele elementului pe care s-a fcut dublu click). Marcheaz apoi nceputul actualizrii listei. Pentru toate elementele cu indicii salvai n colecie, seteaz ora din frm2.txtOra.Text la valoarea proprietii Text a alementelor de list selectate i respectiv schimb imaginea la indexul 1 din iList (fiierul Exclamare.ico). S ne reamintim c n list exist doar indicele elementului pe care s-a fcut dublu click. Apoi, lanseaz caseta DialogBox frm2. Dac din aceasta se revine prin apsarea butonului OK, creeaz un obiect de tip SubItem al unui element de list (s ne reamintim c statutul de Item l au doar elementele din prima coloan, toate celelalte fiind SubItem). Pentru obiectul nou creeat completeaz proprietatea Text cu textul din frm2.txtMes.Text. Urmeaz ca acest SubItem s fie aezat n coloana a doua, pe linia definit de Item-ul corespunztor. Pentru aceasta, declar un obiect ListView.SelectedListViewItemCollection, carec reprezint o colecie de elemente de list selectate i populeaz aceast colecie cu elementul selectat n listAgenda (s ne reamintim din nou, e doar cel pe care s-a fcut dublu click). Dup care, adaug elementului selectat subelementul nou format, prin intermediul funciei Add(). n final, marcheaz sfritul actualizrii listei, pentru a se putea desena coninutul ei. Cu aceasta, aplicaia este complet. Compilai i executai programul, verificnd modul de completare a listei. Dar ce se ntmpl dac schimbm data i apoi revenim la data iniial? Se observ c tot ce-am introdus, s-a pierdut. Acesta, deoarece informaiile nu au fost salvate nicieri. n mod normal, toate aceste informaii ar fi trebuit s fie salvate ntr-o baz de date. Dar despre aceasta, n capitolul urmtor.

    60

    3. Alte controale3.1 Controlul MonthCalendar3.2 Controlul ComboBox3.3 Controlul TabControl3.4 Controalele ListBox i CheckedListBox3.6 Controlul RichTextBox3.7 Casete de dialog3.7.1 FontDialog3.7.2 ColorDialog3.7.3 OpenFileDialog3.7.4 Excepii3.7.5 SaveFileDialog

    3.8 List View Control3.8.1 Adugarea unui DialogBox utilizator