t1.Start(); t2.Start();
}
}
Salvati fila cu numele Window7.cs si compilati.In mod similar,se poate
utiliza cate un thread separat pentru fiecare eveniment din interfata.In
acest caz,programul va putea executa in paralel mai multe seturi de
operatii,crescand viteza de executie si securitatea datelor.
Fereastra poate beneficia si de un meniu functional:
EXEMPLU: using System;
using System.Windows.Forms;
using System.Drawing;
public class AWindow : System.Windows.Forms.Form{
public AWindow(){ MainMenu meniu = new MainMenu();
MenuItem optiune1 = new MenuItem();
MenuItem optiune2 = new MenuItem();
optiune1.Text = "&File";
optiune2.Text = "&Open";
optiune1.MenuItems.Add(optiune2);
meniu.MenuItems.Add(optiune1);
optiune2.Click += new System.EventHandler(this.optiune2_Click);
this.Menu = meniu; }
private void optiune2_Click(object sender,System.EventArgs e)
( OpenFileDialog fd = new OpenFileDialog();
fd.DefaultExt = "*.*";
fd.ShowDialog(); }
static void Main(){ Application.Run(new AWindow()); } }
Slavati fila cu numele Window8.cs si compilati.Obsrevati etapele de
lucru: 1.-se creaza meniul 2.-se creaza optiunile 3.-se grupeaza optiunile
in seturi de optiuni 4.-se include meniul in fereastra (cu Menu=...) si
5.-se definesc evenimentele OnClick pentru fiecare optiune.
-100-
Obiectele din interfata se pot conecta si la resurse externe,fie pentru
a prelua,fie pentru a prelucra si arhiva datele.
EXEMPLU: -creati o fila text denumita Fructe.txt si editati o lista de
fructe pe mai multe randuri.Apoi utilizati aceasta fila pentru a popula
cu valori lista de optiuni a unui obiect de tip ComboBox:
using System;
using System.IO;
using System.Windows.Forms;
using System.Drawing;
public class Lista1 : System.Windows.Forms.Form {
public Lista1(){
this.Size = new Size(800,400);
ComboBox combo = new ComboBox();
combo.Location = new Point(10,10);
combo.Size = new System.Drawing.Size(300,20);
this.Controls.Add(combo);
string path = @"c:\Fructe.txt";
string[] readtext = File.ReadAllLines(path);
foreach( string s in readtext)
{ combo.Items.Add(s); } }
public static void Main(){ Application.Run(new Lista1()); }}
Salvati fila cu numele Window9.cs si compilati.Observati ca pentru
calea de acces spre resursa se adauga si @ (pentru a forma un pointer).
Casetele de dialog se pot popula si cu date preluate din tabele si baze
de date,sau chiar cu date preluate din retea,de la diferite adrese Web,
dar filele de tip text arhivate local asigura un grad sporit de siguranta.
Clasa ColorDialog permite utilizatorului sa personalizeze aspectul
interfetei grafice,dupa bunul plac:
EXEMPLU: using System;
using System.Windows.Forms;
using System.Drawing;
public class AWindow : System.Windows.Forms.Form {
public AWindow() {
Button buton1 = new Button();
buton1.Text = "Alegeti culoarea";
buton1.Location = new Point(70,100);
buton1.Size = new Size(150,24);
buton1.Click += new EventHandler (button_Click);
this.Controls.AddRange( new Control[] {buton1});
this.ShowDialog(); }
private void button_Click(object sender,EventArgs e) {
ColorDialog dialog1 = new ColorDialog();
dialog1.ShowHelp = true;
if (dialog1.ShowDialog() == DialogResult.OK)
this.BackColor = dialog.Color;
static void Main(){ Application.Run(new AWindow()); } }
Salvati fila cu numele Window10.cs si compilati.Aplicatia poate
contine o fereastra separata cu butoane,destinata special pentru
ca utilizatorul sa poata personaliza aspectul interfetei grafice.In acest
caz,setarile se arhiveaza local si se incarca la fiecare utilizare.
-101-
O alta fereastra independenta poate prezenta un calendar complet cu
ajutorul unui obiect de tip Month.Calendar.
EXEMPLU:
using System;
using System.Drawing;
using System.Windows.Forms;
public class Form1: System.Windows.Forms.Form {
private MonthCalendar calendar1;
static void Main(){ Application.Run(new Form1()); }
public Form1(){
calendar1 = new MonthCalendar();
calendar1.Location = new Point(47,16);
calendar1.CalendarDimensions = new Size(4,3);
calendar1.FirstDayOfWeek = System.Windows.Forms.Day.Monday;
calendar1.MaxDate = new DateTime(2100,12,31,0,0,0,0);
calendar1.MinDate = new DateTime(1900,1,1,0,0,0,0);
calendar1.ScrollChange = 12;
calendar1.ShowToday = true;
calendar1.ShowWeekNumbers = true;
calendar1.ShowTodayCircle = true;
ClientSize = new Size(800,500);
this.Controls.AddRange(new Control[] { calendar1});
this.Text = "Exemplu de calendar multianual";
}}
Salvati fila cu numele Window11.cs si compilati.O astfel de fereastra
independenta prezinta datele calendaristice doar orientativ.Daca este
necesar sa se execute operatii aritmetice cu data aleasa de utilizator,
se poate adauga o metoda suplimentara de genul:
calendar1_DataSchimbata(object sender,EventArgs e){
this.text1 = e.Start.ToShortDateString(); }
metoda se va conecta in Form1() cu un event handler:
this.calendar1.DateChanged +=
new System.Windows.DateRangeEventHandler(this.calendar1_DataSchimbata);
unde text1 este un string sau o caseta TextBox pentru afisarea datei.
Dupa ce fiecare obiect din interfata este conectat functional cu
restul obiectelor,se poate trece la etapa de design.In mediul Visual C#,
obiectele sunt vizibile in etapa de design,astfel incat nu trebuie decat
sa alegeti locatia,dimensiunile,culorile etc.In cazul codurilor editate
manual,se pot utiliza solutii standard,module mai vechi,sau pur si simplu
se vor face cateva tatonari succesive.Nu este recomandabil ca un singur
container sa fie incarcat cu prea multe obiecte,decat atunci cand este
vorba despre o colectie de obiecte de acelasi fel: lista,arie,dictionar.
Este bine ca obiectele legate intre ele prin functionalitate comuna sa
fie incluse in containere diferite,fie ca acestea sunt obiecte vizuale
sau containere simple.Se pot utiliza foldere,ferestre de tip Form sau
obiecte vizuale de tip Panel.Obiectele astfel grupate vor avea un spatiu
de vizibilitate restrans si implicit o siguranta crescuta in executie.
Cu cat memoria este mai fragmentata,cu atat executia va fi mai rapida
si mai sigura.In plus,functionalitatea unui astfel de grup de obiecte va
fi foarte usor de transferat de la un program la altul.
-102-
EXEMPLU:
using System;
using System.Windows.Forms;
using System.Drawing;
public partial class AWindow: System.Windows.Forms.Form{
public AWindow() {
this.Size = new Size(600,400);
Panel panel1 = new Panel();
TextBox textBox1 = new TextBox();
Label label1 = new Label();
RadioButton r1 = new RadioButton();
panel1.Location = new Point(56,72);
panel1.Size = new Size(264,152);
panel1.BorderStyle = BorderStyle.Fixed3D;
label1.Location = new Point(16,16);
label1.Text = "Eticheta pentru TextBox:";
label1.Size = new Size(104,16);
textBox1.Location = new Point(16,32);
textBox1.Text = "...textul implicit";
textBox1.Size = new Size(152,20);
r1.Location = new Point(16,80);
r1.Size = new Size(120,20);
r1.Text = "Butonul radio";
this.Controls.Add(panel1);
panel1.Controls.Add(label1);
panel1.Controls.Add(textBox1);
panel1.Controls.Add(r1);
}
static void Main(){ Application.Run(new AWindow));}
}
Salvati fila cu numele Window12.cs si compilati.Observati ca fiecare
container include obiectele prin metoda Controls.Add().Modulul de mai
sus nu face decat sa grupeze trei obiecte.Pentru a fi complet,cele trei
obiecte trebuie sa fie conectate intre ele prin metode sau evenimente.
Nu este utila nici fragmentarea excesiva a programului.Fie ca se
utilizeaza fire de executie paralele (thread-uri),fie ca se imparte
executia in ferestre si module independente,sau containere,este bine
ca fiecare proces sa execute un calup de memorie proportionat in functie
de memoria de lucru a procesorului.Acest calup este bine sa nu depaseasca
30 % din capacitatea maxima (tamponul intern de memorie) a procesorului.
Concret,fragmentarea nu este utila pentru nici un program mai mic de
1 Mb,dar este indispensabila in cazul aplicatiilor ce lucreaza cu baze
de date,sau cu date preluate si procesate de la adrese de memorie din
retea.In mediu de retea,trebuie avut in vedere si spatiul necesar pentru
protocoalele de comunicatie si obiectele necesare pentru conectare.
Este posibila si o solutie mixta.Proiectati si programati aplicatia
in mediu visual,apoi preluati codurile si compilati programul cu csc.exe,
pentru a obtine un modul unic,portabil,de dimensiuni mici.
Pentru aplicatiile mari,sau comunicatii in retea,este recomandabil sa
utilizati exclusiv solutiile standardizate din mediul Visual C#.
-103-
System.Data
Contine clasele necesare pentru conectarea si preluare de date din
baze de date si tabele.Aceleasi obiecte pot organiza si date create
dinamic,in timpul executiei:
EXEMPLU:
using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
public class Form1 : System.Windows.Forms.Form {
private System.ComponentModel.Container components;
private DataGrid Grila1;
private DataSet Info1;
public static void Main() { Application.Run(new Form1()); }
public Form1() { InitializeComponent();
SetUp(); }
private void InitializeComponent() {
this.components = new System.ComponentModel.Container();
this.Grila1 = new DataGrid();
this.Text = "Exemplu de grila: ";
this.ClientSize = new System.Drawing.Size(350,350);
Grila1.Location = new Point(24,50);
Grila1.Size = new Size(300,200);
Grila1.CaptionText = "Grila pentru afisaj: ";
this.Controls.Add(Grila1); }
private void Setup() {
Info1 = new DataSet("Info1");
DataTable tabel1 = new DataTable("Echipe");
DataColumn pozitie = new DataColumn("Pozitie",typeof(int));
DataColumn nume = new DataColumn("Nume");
DataColumn calificare = new DataColumn("Calificare",typeof(bool));
table1.Columns.Add(pozitie);
tabel1.Columns.Add(nume);
tabel1.Columns.Add(calificare);
Info1.Tables.Add(tabel1);
DataRow newRow1;
for( int i = 1; i<4; i++) {
newRow1 = tabel1.NewRow();
newRow1["Pozitie"] = i;
tabel1.Rows.Add(newRow1); }
tabel1.Rows[0]["Nume"] = "Steaua";
tabel1.Rows[1]["Nume"] = "Dinamo";
tabel1.Rows[2]["Nume"] = "Rapid";
tabel1.Rows[0]["Calificare"] = true;
tabel1.Rows[1]["Calificare"] = true;
tabel1.Rows[2]["Calificare"] = false;
Grila1.SetDataBinding(Info1,"Echipe"); }}
Salvati fila cu numele Window13.cs si compilati.Observati cum sunt
interconectate principalele obiecte din interfata.
-104-
Principalele obiecte sunt: DataSet,DataTable,DataColumn si DataRow.
Afisarea datelor se poate face cu un obiect DataGrid (din Windows.Forms).
Tabelul se poate popula su cu date preluate dintr-o fila de tip text,cum
este cea creata pentru exemplul Window9.cs (vezi Fructe.txt).
EXEMPLU:
using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
public class Form1 : System.Windows.Forms.Form {
private System.ComponentModel.Container components;
private DataGrid Grila1;
private DataSet Info1;
public static void Main() { Application.Run(new Form1()); }
public Form1() { InitializeComponent();
SetUp(); }
private void InitializeComponent() {
this.components = new System.ComponentModel.Container();
this.Grila1 = new DataGrid();
this.Text = "Exemplu de grila: ";
this.ClientSize = new System.Drawing.Size(350,350);
Grila1.Location = new Point(24,50);
Grila1.Size = new Size(300,200);
Grila1.CaptionText = "Grila pentru afisaj: ";
this.Controls.Add(Grila1); }
private void Setup() {
Info1 = new DataSet("Info1");
DataTable tabel1 = new DataTable("Fructe");
DataColumn nume = new DataColumn("Nume",typeof(string));
nume.MaxLength = 80;
tabel1.Columns.Add(nume);
Info1.Tables.Add(tabel1);
DataRow newRow1;
string path = @"c:\Fructe.txt";
string[] readtext = File.ReadAllLines(path);
foreach (string s in readText)
{ newRow1 = tabel1.NewRow();
newRow1["Nume"] = s;
table1.Rows.Add(newRow1); }
Grila1.SetDataBinding(Info1,"Fructe");
DataGridTableStyle ts1 = new DataGridTableStyle();
ts1.MappingName = "Fructe";
ts1.AlternatingBackColor = Color.Yellow;
DataGridColumnStyle coloana = new DataGridTextBoxColumn();
coloana.MappingName = "Nume";
coloana.Width = 400;
ts1.GridColumnStyles.Add(coloana);
Grila1.TableStyles.Add(ts1); }}
Salvati fila cu numele Window14.cs si compilati.
-105-
Obiectul pentru afisarea datelor de tip DataGrid este rudimentar.Pentru
a putea organiza designul vizual,este necesar un set de obiecte speciale
cum sunt: DataGridTableStyle,DataGridColumnStyle si DataGridView (toate
sunt incluse in System.Windows.Forms).
Bibliotecile Data.Odbc si Data.OleDb contin alte clase auxiliare.De
exemplu,clasa OleDbDataAdapter faciliteaza preluarea datelor dintr-un
tabel,cu o comanda SQL si apoi transferul acestor date intr-un obiect de
tip DataTable.
EXEMPLU:
using System;
using System.IO;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.Data.OleDb;
public class Form1 : System.Windows.Forms.Form {
private System.ComponentModel.Container components;
private DataGrid Grila1;
private DataSet Info1;
public static void Main() { Application.Run(new Form1()); }
public Form1(){ InitializeComponent();
SetUp(); }
private void InitializeComponent(){
this.components = new System.ComponentModel.Container();
this.Grila1 = new DataGrid();
this.Text = "Exemplu de grila: ";
this.ClientSize = new Size(650,450);
Grila1.Location = new Point(24,50);
Grila1.Size = new Size(500,300);
Grila1.CaptionText = "Grila pentru afisaj:";
this.Controls.Add(Grila1); }
private void SetUp() {
System.Data.OleDbConnection con;
con = new System.Data.OleDb.OleDbConnection("");
con.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;
DataSource=Biblioteca.mdb";
con.Open();
Info1 = new DataSet("Info1");
DataTable tabel1 = new DataTable("Carti");
OleDbDataAdapter sda = new OleDbDataAdapter("SELECT * FROM Carti,con);
sda.Fill(tabel1);
DataColumn nume = new DataColumn("Nume",typeof(string));
tabel1.Columns.Add(nume);
Info1.Tables.Add(tabel1);
Grila1.SetDataBinding(Info1,"Carti");
con.Close();
}}
Salvati fila cu numele Window15.cs si compilati.In exemplul de mai
sus,datele sunt preluate din baza de date denumita Biblioteca.mdb ce
contine un tabel denumit Carti (din directorul curent).
-106-
Pentru a putea lucra cu tabele si baze de date,trebuie sa existe un
driver inregistrat.Pentru bazele de date tip Microsoft,sistemul XP
contine dirver-ul implicit "Microsoft.Jet.OLEDB.4.0".Puteti insa sa
utilizati orice alt driver daca este inregistrat in sistemul de operare.
EXEMPLE:
"Provider=MSDAORA; Data Source=ORACLE8i7;"
"Provider=SQLOLEDB; Data Source=(local);"
Driver-ul impreuna cu locatia bazei de date formeaza string-ul de
conectare necesar pentru a deschide o conexiune intre aplicatia si baza
de date locala.Dupa ce conexiunea este stabilita corect,se poate crea un
obiect de tip OleDbDataAdapter ce preia toate datele din tabel in functe
de comanda SQL din constructor.Pentru a putea transfera aceste date in
DataTable,cu ajutorul metodei Fill(),este necesar ca tabelul ca contina
cel putin o coloana predefinita (prima coloana sa nu fie nula).Acest
mecanism este foarte operativ si permite filtrarea datelor prin comanda
SQL.Obiectul OleDBDataAdapter nu poate transfera insa decat un singur
tabel per operatie si nu permite operatii de intersectare sau reuniune a
doua tabele.
Atunci cand baza de date este localizata intr-un server,string-ul de
conectare trebuie sa contina in plus si numele serverului,adresa de
acces si parola utilizatorului.Operatiile cu baze de date din serverul
local,sau din retea sunt insa recomandate doar programatorilor avansati.
Tabelele si bazele de date contin de cele mai multe ori volume mari
de informatie,ce necesita operatii cu volume mari de memorie.Cea mai mica
gresala de conceptie,poate avea efecte dezastroase asupra executiei.Din
acest motiv,este recomandabil sa utilizati formule de lucru standardizate,
sau sa preluati si sa adaptati exemple pre-existente.Principalele operatii
de selectare si filtrare a datelor se pot organiza cu ajutorul comenzilor
SQL,fara sa mai fie necesar sa programati algoritmi speciali.
Exista numeroase obiecte de tip colectie,ce pot prelua si prelucra
seturi sau subseturi de date din tabele.Exemplu: coloanele unui tabel
se pot utiliza pentru a completa optiunile unor casete de tip ComboBox,
sau ListBox.Uneori,se selecteaza din tabel,o singura inregistrare ce
poate fi transformata in string si afisata cu un obiect TextBox sau Label.
De cele mai multe ori,este nepractic sa prezentati intregul tabel sub
forma de grila.Nu numai ca se consuma volume inutile de memorie,dar se
prezinta si date ce nu sunt relevante pentru utilizator (sau sunt chiar
secrete).Din acest motiv,solutia de prezentare a datelor procesate va fi
personalizata in functie de aplicatie si utilizator.
Acelasi mecanism functioneaza si in sens invers.Datele din unul sau
mai multe obiecte vizuale din interfata grafica,pot fi arhivate in tabele
si baze de date.Nu se justifica insa crearea de tabele,decat atunci
cand se vor executa si operatii de sortare,selectare sau filtrare a lor.
Pentru arhivare simpla,se vor prefera intotdeauna fisierele de tip text,
deoarece ocupa mult mai putin spatiu de memorie si nu necesita operatii
de formatare,conversie,criptare...etc.
Bazele de date si tabelele,sunt un instrument de lucru foarte practic,
dar reduc viteza de executie si intoduc un numar foarte mare de operatii
suplimentare.In plus,coruperea accidentala a unei baze de date este
mult mai greu de corectat si depanat decat o fila de tip text.Solutia
optima este sa pastrati intotdeauna copii de siguranta.
-107-
System.Timers
Contine un set restrans de clase destinate pentru a putea cronometra
operatiile,sau pentru a putea declansa evenimente la anumite intervale de
timp.Dintre acestea,cea mai importanta este clasa Timer (cronometru).Cu
ajutorul aceste clase se construiesc obiecte ce cronometreaza anumite
grupuri de operatii din program.
EXEMPLU:
using System;
using System.Timers;
using System.Windows.Forms;
public class AWindow : Form {
public AWindow(){
System.Timers.Timer Timer1 = new System.Timers.Timer();
Timer1.Enabled = true;
Timer1.Interval = 2000;
Timer1.Elapsed += new System.Timers.EventHandler(Timer1_Elapsed);
}
private void Timer1_Elapsed(object sender,
System.Timers.ElapsedEventArgs e)
{ MessageBox.Show("2 secunde!","Eveniment nou !"); }
static void Main(){ Application.Run(new AWindow()); }
}
Salvati fila cu numele Window16.cs si compilati.In acest exemplu este
necesar sa fie utilizata expresia completa: System.Timers.Timer atunci
cand se construieste obiectul pentru a face distinctia de clasa Timer din
Windows.Forms.Se observa ca la fiecare doua secunde,cronometrul emite un
nou mesaj.Cronometrul este creat pe baza cronometrului intern din procesor
si poate functiona 24 de ore din 24.Pentru a declansa un eveniment se
utilizeza metoda Elapsed conectata la functia de raspuns (delegat).Pentru
ca evenimentul sa poata fi repetat,trebuie ca proprietatea AutoReset sa
fie setata True.Daca este setata False,evenimentul nu se va mai repeta la
urmatorul interval setat.Intervalul se seteaza prin proprietatea Interval.
Cronometrul poate fi controlat prin metodele Start() si Stop(), apoi
poate fi sters din memorie cu Dispose().Alta proprietate este Enabled,
prin care se specifica daca cronometrul poate sa declanseze un eveniment
sau evolueaza doar in background (este inactivat).
Cronometrele sunt concepute pentru a putea evolua in mediu de multi-
procesare cu thread-uri multiple.Fiecare fir de executie (thread) va putea
avea unul sau mai multe cronometre proprii,ce guverneaza toate operatiile
din stream.Prin combinarea unui numar oarecare de thread-uri,cu unul sau
mai multe cronometre, se pot obtine rutine de automatizare complexe,usor
de programat si usor de depanat. Pentru controlul cronometrelor se pot
conecta si cateva obiecte vizuale prin care utilizatorul poate seta
proprietatile,sau poate comanda una dintre metode.In aceste situatii este
utila si proprietatea SynchronizingObject.Pentru a bloca complet executia
unui cronometru cu Stop() si Dispose(),se va seta si SynchronizingObject
la valoarea "null".In caz contrar,evenimentul conectat la cronometru va
putea fi declansat si dupa oprirea cronometrului (daca mesajul de executie
a fost trimis inainte de Stop() si asteapta trecerea intervalului setat).
-108-
System.Runtime
Contine clase esentiale pentru managementul automat al memoriei.Astfel,
CGSettings permite setarea operatiei de "garbage collection" pentru
procesul aflat in executie,iar MemoryFailPoint verifica daca exista
suficienta memorie pentru executia procesului curent.
EXEMPLU:
using System;
using System.Runtime;
using System.Collections;
using System.Windows.Forms;
class Test {
static void Main(){
Queue workQueue = new Queue(50);
for (int x=1; x<30; x++){
try { MemoryFailPoint memFailPoint = new MemoryFailPoint(1000);
for (int n=1; n < 2500000; n++)
workQueue.Enqueue(n);
}
catch (InsufficientMemoryException e)
{ MessageBox.Show("Memorie insuficienta","mesaj");
Console.WriteLine(e);
workQueue = null;
Dostları ilə paylaş: |