RicH and FamouS

       Home         Glosar IT                                                                                                                                                                                                              SUBSCRIBE NOW!
        

30.04.2009

MFC Tips - Common Dialogs

Cum "controlez" un control dintr-un common dialog?

Problema:
Am un dialog comun, sa zicem "File Open" si vreau (doar un exemplu), sa schimb textul unui control tip static.
Pare simplu, nu trebuie decat sa derivez din CFileDialog, sa suprascriu functia OnInitDialog iar acolo apelez GetDlgItem si SetWindowText sau direct SetDlgItemText (ID-ul controlului l-am gasit cu Spy++).
Nu merge. GetDlgItem intoarce NULL iar SetDlgItemText nu schimba absolut nimic.

Rezolvare:
De fapt, clasele derivate din CComonDialog (CFileDialog, CFontDialog, CColorDialog, etc) incapsuleaza un child al dialogului comun ce contine controalele. Deci trebuie sa-i gasim mai intai parent-ul.

Exemplu:

Cod:
class CMyFileDialog : public CFileDialog
{
// ...
// Overrides
public:
virtual BOOL OnInitDialog();
// ...
};

#include <DLGS.H>
// ...
BOOL CMyFileDialog::OnInitDialog()
{
CFileDialog::OnInitDialog();
// ...
GetParent()->SetDlgItemText(stc3, _T("Ala bala portocala"));
// ...
return TRUE;
}

NOTA: In exemplul de mai sus am folosit ID-ul 'stc3' definit in <DLGS.H>.

29.04.2009

Ubuntu Party Chișinău, Moldova — 2 Mai

În Chișinău va fi primul Ubuntu Release Party!

În data de 2 Mai 2009, va avea loc în cadrul Universității Tehnice a Moldovei, Blocul de studii nr 2, str 31 August 1989 nr 78, începând cu orele 12.00, evenimentul de lansare Ubuntu 9.04.

Mulțumim linux.md pentru suportul acordat!

Pentru mai multe detalii consultați pagina oficială: party.ubuntumd.org

Glosar IT (Traceroute, SSL, Spam)

Traceroute

Conceput initial drept aplicatie Unix, Traceroute este in mod curent accesibil pe majoritatea platformelor de operare. Traceroute este un utilitar ce permite modul in care informatiile circula in mediul Internet, prin urmarirea unui pachet de date trimis de pe computerul personal catre un destinatar oarecare. La intampinarea unui server Web cu viteza de transfer redusa, aplicatia Traceroute va poate ajuta in determinarea serverlor ce cauzeaza intarziere in livrarea mesajelor dumneavoastra.

SSL

Secure Sockets Layer SSL este un standard de securitate a tranzactiilor online dezvoltat de Netscape Communications pentru a contribui la realizarea de tranzactii comerciale intr-un mediu Internet confidential.


Spam

Spamming (sau spam) este procesul de expediere a mesajelor electronice nesolicitate, de cele mai multe ori cu caracter comercial, de publicitate pentru produse şi servicii dubioase, practicată în industria e-marketingului şi de proprietarii de situri pornografice. Spam-ul se distinge prin caracterul agresiv, repetat şi prin privarea de dreptul la opţiune.

Spamming-ul este o metodă foarte ieftină de a face reclamă pentru ceva în Internet; succesul campaniei este de obicei proporţional cu numărul de destinatari; de aceea mesajul respectiv este transmis la mii, chiar milioane de adrese simultan.

28.04.2009

Blochează porturile USB

Dacă fratele tău mai mic îţi fură documentele cu stick-ul lui USB, sau nu vrei să o laşi pe sora ta să-ţi copieze MP3-urile pe player-ul ei, ori pur şi simplu eşti paranoic şi vrei să te asiguri că nimeni nu va putea să-ţi utilizeze informaţiile esenţiale pentru umanitate pe care le ţii pe PC-ul tău, ai o singură soluţie. Nu, nu trebuie să dormi cu laptopul sub pernă. E suficient să blochezi porturile USB.

Poţi face acest lucru folosind un program mic şi extrem de uşor de folosit. Se numeşte chiar USB Blocker.

Blocarea porturilor USB, la mintea cocoşului

Utilizarea programului este cât se poate de simplă. Ai trei butoane: Normal, ReadOnly şi Disable. Normal înseamnă că accesul la USB-uri este permis, ReadOnly acceptă doar citirea şi copierea fişierelor (nu şi modificare acestora) de pe dispozitivul conectat, iar Disable blochează porturile.

În modul ReadOnly dispozitivele conectate prin USB la calculator vor funcţiona normal, cu excepţia situaţiilor în care trebuie să modifice diverse informaţii. În acest caz, scrierea pe dispozitivul conectat este împiedicată. Când optezi pentru Disable şi conectezi un stick USB la calculator, acesta nu va fi recunoscut de sistem. Nu vor apărea mesaje care să atenţioneze utilizatorul de blocarea porturilor. Aşa că, aplicaţia USB Blocker poate fi foarte simplu lăsată să ruleze în background. În tot acest timp, dispozitivele conectate pe USB nu vor fi recunoscute de PC-ul respectiv.

Ca un neajuns, am observat că blocarea porturilor USB cu acest program nu funcţionează uneori în cazul dispozitivelor conectate pentru prima oară la un sistem. De la a doua conectare, nu pare să mai existe probleme.

Din păcate, USB Blocker este un program comercial. Poate fi folosit însă, fără nicio obligaţie, timp de 7 zile. Ca alternativă gratuită, poate fi încercat NetWrix USB Blocker. Acesta este însă ceva mai complicat deoarece necesită instalarea unor fişiere auxiliare. Pe de altă parte, NetWrix USB Blocker poate fi folosită şi în cadrul reţelelor de calculatoare, fără a fi instalat pe fiecare calculator în parte.

27.04.2009

Cuvinte de nedespartit (Word)

Modul in care Word-ul imparte un text in rinduri este dat de distanta implicita sau stabilita dintre caractere. Dar, dincolo de acestea, de multe ori se impune ca anumite cuvinte/sintaxe sa nu fie despartite pe rinduri. Si atunci ce e de facut?! In acest caz, veti utiliza un caracter special, asa-numit "nonbreaking space". Acesta are rolul de a lega cuvintele intre care este plasat, pentru ca acestea sa nu fie dispuse pe rinduri separate.
Iata cum puteti utiliza acest simbol in Word 2003.
  1. Plasati cursorul intre cele doua cuvinte pe care le aveti in vedere (insa fara a pune spatiu intre ele).
  2. Din meniul Insert, selectati optiunea Symbol.
  3. Aici activati registrul Special Character.
  4. Din lista caracterelor speciale, selectati optiunea Nonbreaking Space. De aici aflati si combinatia de taste pe care o veti folosi pe viitor cind vreti sa utilizati simbolul.
  5. Clic pe INSERT.

26.04.2009

MFC Tips - Application

Cum gasim folder-ul aplicatiei?
Problema:
Se intampla ca o aplicatie sa failizeze atunci cand cauta un fisier in folder-ul ei sau intr-un sub-folder desi acel fisier este bine-mersi acolo. Cele mai posibile cauze sunt doua: sau programatorul a folosit numai numele fisierului, sau a folosit un full-path-and-file-name batut in cod (ex: "c:\Program Files\MyCoolApp\MyLog.txt").

In primul caz se va folosi directorul curent al aplicatiei dar acesta nu este neaparat acelasi cu folderul aplicatiei (directorul curent poate fi diferit inca de la lansarea aplicatiei sau poate fi schimbat la run-time).

In al doilea caz, aplicatia insasi poate fi instalata in alt folder (in exemplul nostru "c:\Program Files\..." sau chiar foldere speciale cum sunt "Program Files" pot avea denumiri diferite in functie de versiunea de OS, limba, etc).

Rezolvare (1):
Una dintre solutii ar fi sa "extragem" folderul applicatiei din membrul public m_pszHelpFilePath al clasei aplicatiei (derivata din CWinApp):

Cod:
bool CFoo::GetAppPath(CString& strAppPath)
{
bool bFound = false;
strAppPath.Empty();
CWinApp* pApp = AfxGetApp();
if(NULL != pApp)
{
strAppPath = pApp->m_pszHelpFilePath;
// extract the application path
const int nPos = strAppPath.ReverseFind(_T('\'));
if(-1 != nPos)
{
bFound = true;
strAppPath = strAppPath.Left(nPos);
}
}
return bFound;
}


Rezolvare (2):
Prima metoda ar fi destul de buna, dar mai sigur si chiar mai simplu este sa folsim functia WinAPI GetModuleFileName careia ii pasam NULL in primul parametru:

Cod:
void GetAppPath(CString& strAppPath)
{
::GetModuleFileName(NULL, strAppPath.GetBuffer(MAX_PATH), MAX_PATH);
strAppPath.ReleaseBuffer();
// extract the application path
const int nPos = strAppPath.ReverseFind(_T('\'));
strAppPath = strAppPath.Left(nPos);
}


Cum customizez AfxMessageBox?
Rezolvare:
AfxMessageBox cheama intern functia virtuala CWinApp::DoMessageBox. Exemplul urmator suprascrie CWinApp::DoMessageBox si schimba textul de pe caption (default, numele aplicatiei sau fisierului executabil)

Exemplu:

Cod:
// MyApp.h

class CMyApp : public CWinApp
{
// ...
// Overrides
public:
virtual int DoMessageBox(LPCTSTR lpszPrompt, UINT nType, UINT nIDPrompt);
// ...
};

// MyApp.cpp

int CMyApp::DoMessageBox(LPCTSTR lpszPrompt, UINT nType, UINT nIDPrompt)
{
// keep in mind m_pszAppName pointer
LPCTSTR pszAppName = m_pszAppName;
// assign the new desired name
m_pszAppName = _T("My Cool Message Box");
// call base class function
int nRet = CWinApp::DoMessageBox(lpszPrompt, nType, nIDPrompt);
// restore initial m_pszAppName pointer then return
m_pszAppName = pszAppName;
return nRet;
}

25.04.2009

Șabloane multiple în PowerPoint

În sfârșit! Caracteristica PowerPoint pe care am așteptat-o cu toții! Dacă sunteți utilizator PowerPoint 2002, puteți acum folosi mai mult de un șablon de cadru într-o singură prezentare. Așadar, dacă combinați mai multe prezentări într-un singur fișier sau doriți o singură prezentare în mai multe secțiuni, această caracteristică este extrem de utilă.

Pentru a aplica opțiunea șabloane multiple, asigurați-vă că prezentarea se face în Normal view și apoi mergeți la meniul Format și alegeți Slide Design. Fereastra Slide Design Task va apărea la dreapta ecranului. În partea stângă a ecranului selectați filmele la care doriți să le schimbați șablonul (utilizați Control și dați clic pentru a selecta filme multiple, ca de obicei) și apoi dați clic pe șablonul necesar în Task Pane.

24.04.2009

Verificarea documentelor utilizând Office XP

Când lucrați în echipă pentru a crea documente și prezentări, puteți fi sigur că membrii echipei iau parte la discuție folosind opțiunea Routing care face parte din caracteristicile Send To/Send for Review din Microsoft Office XP.

Opțiunea Routing vă dă posibilitatea să specificați ordinea în care destinatarii vor primi și verifica un document pe care îl trimiteți pentru verificare prin e-mail. Creați o notiță care afișează ordinea în care fiecare dintre membrii echipei dvs. va primi documentul pe care îl trimiteți pentru verificare. Apoi, în timp ce fiecare membru al echipei sugerează schimbări, răspunde la întrebări sau face corecții, restul echipei primește schimbările împreună cu documentul pentru a-l verifica; ei pot adăuga date suplimentare înainte de a implementa modificările finale.

De exemplu, după ce ați adunat într-o schiță datele introduse de membrii echipei așa cum se arată în The Review Cycle in Office XP: Draft Documents with Your Team, sunteți gata să trimiteți propunerea echipei pentru comentarii. Deoarece specialistul în marketing al echipei trebuie să răspundă la unele întrebări pentru ca verificarea să poată continua, direcționați documentul pentru verificare întâi la el și apoi la ceilalți membri ai echipei care pot adăuga mai multe informații.

Pregătirea unui document pentru verificare
  • Deschideți documentul.
  • În meniul File, indicați Send To și apoi dați clic pe Routing Recipient....
  • Dați clic pe Address pentru a selecta destinatarii.
  • În caseta Type name or select from list, introduceți un nume și apoi dați clic pe To. Repetați acest pas pentru fiecare destinatar și apoi dați clic pe OK.
  • Selectați opțiunile de rutare dorite.
  • Pentru a ruta documentul, dați clic pe Route.

23.04.2009

Sfaturi pentru un Vista de nota 10


1. Intrerupeti Automatic Windows Defender
Windows Defender va protejeaza sistemul importiva pericolelor cauzate de malware si alti virusi aiinternetului. Dar, daca nu beneficiati de o conexiune activa la Internet, puteti renunta la aceastaoptiune, din moment ce ea reduce performantele sistemului vostru. Accesati Control Panel si dati dublu click pe Windows Defender, apoi pe linkul Tools and Settings. Selectati si debifati casuta OptionsAuto Start. Salvati setarile. Atentie! Recomandabil este sa aveti instalat un program antivirus care sa monitorizeze riscurile de infectare din alte surse.

2. Opriti indexul de cautare
Windows are o structura indexata a fisierelor de permit lansarea rapida a aplicatiilor, cunoscuta sub denumirea de Search Index. Acesta tine o evidenta stricta a tuturor fisierelor si a locatiei lor pentru a putea fi accesate rapid la solicitarea utilizatorului. Instrumentul in sine este extrem de util, dar, in egala masura, poate reduce performantele PC-ului, mai ales daca ruleaza cu o configuratie minima. Pentru a dezactiva indexul de cautare, faceti un dublu clic pe pictograma My Computer aflata pe Desktop si apoi clic dreapta pe una dintra partitii. Selectati optiunea Properties din meniul contextual. Din registrul General, debifati casuta Index this drive for searching.

3. Fara System Restore
Acesta optiune permite aducerea Windows-ului la o stare anterioara in cazul unor atacuri cu virusi sau a cedarii sistemului. Desi este un instrument util, puteti sa renuntati la el pentru a creste performantele sistemului, in special daca aveti o configuratie minima pentru Vista. Daca v-ati decis, nu trebuie decit sa accesati Control Panel si sa dati un dublu clic pe iconita System. Mergeti la System Protection, debifati casutele corespunzatoare unitatilor de memorie si apoi dati clic pe OK.

4. Excesul de servicii
Windows Vista incarca automat, la fiecare pornire, o serie de facilitati si servicii care pot fi nefolositoare utilizatorului. Puteti verifica lista de programe care pornesc o data cu sistemul si sa le dezactivam pe cele de care nu aveti nevoie. Mergeti la Control Panel, dati dublu clic pe Administrative Tools si de aici pe System Configuration. Faceti clic pe registrul Services. Debifati aplicatiile pe care le considerati in plus OK.

5. Renuntati la Hibernare
Modul Hibernare este extrem de util mai ales daca lucrati pe un laptop, dar, in acelasi timp, face apel la multe resurse ale Windows-ului. Daca nu este des utilizat, va recomand sa-l dezactivati. Pentru aceasta intrati in Control Panel si faceti dublu clic pe Power Options. Mergeti la Change Plan Settings si apoi la Change Advanced Power Settings. Alegeti setarea Sleep si de aici selectati optiunea Hibernate After Selection. Introduceti valoarea 0 in casuta de text si dati clic pe OK.

Glosar IT (WWW, Whois, Usenet)

World Wide Web

Cunoscut si sub abrevierea WWW, W3 sau Web, si dezvoltat initial de laboratoarele CERN din Geneva, Elvetia. Dezvoltarea continua a mediului Web este supravegheata de World Wide Web Consortium. Mediul Web poate fi descris si sub forma unui sistem de hypertext pentru server si client, utilizat in furnizarea de informatii din reteaua Internet.

Toate elementele componente ale mediului Web au o reprezentare sub forma de/in format HTML si este legat de alte documente prin intermediul adreselor tip URL. Mediul Web incorporeaza protocolul HTTP, FTP, Gopher si Telnet.

Whois

Un serviciu al directorului Internet, similar cu finger si utilizat pentru a gasi informatii despre diferite nume de persoane, stocate pe servere Internet de la distanta.

Majoritatea furnizorilor de servicii de inregistrare a numelor de domenii ofera facilitati Web de interogare tip WHOIS a bazelor de date, cu afisare a detaliilor legate de proprietarul numelui de domeniu si alte referinte de contact in probleme tehnice si administrative.

Usenet

Usenet reprezinta o retea internationala de sisteme Unix cu informatii si administrare descentralizate. Sistemele tip Usenet transmit mesaje catre grupuri de stiri axate pe subiecte specifice, lansate si continuate de catre utilizatori.

22.04.2009

Calendar Vista

Mulţi utilizatori se bazeaza pe calendarul din Windows pentru a-si organiza agenda zilnica. Daca se intimpla ca fisierul calendarului sa fie corupt, se vor pierde toate planificarile si intilnirile ce au fost salvate acolo. Pentru a preveni o asemenea situatie, se poate face o copie de siguranta a calendarului, care sa die utilizata in locul variantei originale. Toate acesta se pot realiza in urmatorul mod:
  1. Clic pe Start si tastati Calendar in cimpul de cautare.
  2. Mergeti in registrul File si selectati Export. Va aparea casuta de dialog in care se va cere sa specificati un dosar pentru a salvarea fisierului .ics.
  3. Specificati locatia si apoi dati clic pe Save.
  4. Pentru a importa fisierul in cazul in care originalul a fost corupt, selectati optiunea Import din registrul File si veti putea accesa copia de siguranta.
  5. Specificati dosarul unde a fost salvata copia de siguranta si apoi dati clic pe Import.

21.04.2009

Gmail - acum şi offline

Una dintre cele mai insistent cerute funcţii pentru Gmail, suportul offline, face începând de astăzi parte din serviciul de e-mail al celor de la Google. Noua funcţie nu este deocamdată accesibilă tuturor. Unii beneficiază deja de suport offline în Gmail, în timp ce alţii o vor vedea la lucru spre sfârşitul săptămânii.

Ce înseamnă suportul offline

Pe scurt, suportul offline îţi permite să foloseşti Gmail, cu limitările de rigoare, chiar şi atunci când nu eşti conectat la Internet. Gmail va detecta automat dacă îţi merge sau nu Internetul şi va trece în consecinţă pe modul online sau offline.

În funcţie de modul apelat, comportamentul serviciului va fi diferit. De exemplu, offline nu vei putea trimite mesaje (le vei putea totuşi compune), iar paginile se vor încărca mult mai repede pentru că vor fi accesate direct de pe calculatorul tău, nu de pe serverele Google.


Cum funcţionează

În mod normal, mesajele din Gmail sunt stocate pe serverele Google. Cu modul offline activ, e-mail-urile vor fi stocate atât pe server, cât şi pe calculatorul tău. Verificându-ţi conexiunea, Gmail va lucra cu mesajele de pe server când eşti online şi cu cele de pe calculatorul tău când eşti offline.

Nu doar citirea şi căutarea mesajelor sunt posibile în modul offline, ci şi compunerea acestora. Deosebirea este că mesajele trimise când eşti offline sunt stocate în Outbox şi trimise automat când se revine online.


Cum îl foloseşti

Primul pas este să descarci Google Gears, programul responsabil de munca ascunsă din spatele acestei funcţii. În Firefox de exemplu, această aplicaţia este instalată ca un addon. Evident, după instalare trebuie să restartezi browser-ul. Apoi, pentru a activa funcţia, intri în Gmail, la Settings, Labs şi să dai Enable la Offline Gmail. După ce vei da Save, Gmail se va reîncărca automat şi va afişa un nou link, "Offline 0.1", în colţul din dreapta sus, lângă numele de utilizator. De aici va merge pe pilot automat.

De la cei care pot deja folosi noua funcţie am aflat că nu sunt sincronizate toate mesajele. Aşa că nu trebuie să-ţi faci griji că vei avea de aşteptat o eternitate până când Gmail îţi va copia pe calculator 7 GB. Se pare că vor fi sincronizate "doar" cele mai recente 10.000 de e-mail-uri. Dacă nu-ţi apare noua funcţie, nu dispera, nu a fost activată deocamdată pentru toate conturile. Pe parcursul zilelor următoare va deveni disponibilă pentru toţi utilizatorii.

Prin introducerea suportului offline, Gmail se apropie mult de clienţii de e-mail software. Rămâne în continuare o aplicaţie online dar prin această funcţie depăşeşte graniţa care desparte programele de calculator de serviciile online. Chiar dacă este doar la început, acest drum va fi cu siguranţă urmat şi de alţii, gen Yahoo! şi Microsoft. Dubla stocare (pe server online şi pe propriul calculator) este cel sănătos principiu pe care se poate baza pe viitor sistemul Cloud Computing.

20.04.2009

MFC Tips - Dialog

Cum schimbam numele clasei unui dialog?
Problema:
Dialoagele fac parte din clasa fereastra predefinita "#32770". Se poate ivi cerinta de a schimba numele clasei unuia sau mai multe dialoage din aplicatie, de exemplu cu scopul de a fi usor diferentiate atunci cand le cautam cu FindWindow, FindWindowEx, etc sau atunci cand folosim o scula de testare automata.

Rezolvare:
VS6.0
  1. In fereastra "ResourceView" dau right-click pe radacina tree-ului si selectez "Properties".
  2. In dialogul "Resource File Properties" decheckuiesc "Enable MFC features".
  3. Dau right-click pe dialog template si aleg "Properties".
  4. In dialogul "Dialog Properties", introduc noul nume al clasei, ex. "Mama Leone"; NOTA: in lipsa primilor doi pasi, campul "Class name" este disabled.
  5. In sfarsit, in functia InitInstance al aplicatiei MFC adaug urmatorul cod:

    Cod:
    WNDCLASS wc;

    // Get the info for this class.
    // #32770 is the default class name for dialogs boxes.
    ::GetClassInfo(AfxGetInstanceHandle(), _T("#32770"), &wc);

    // Change the name of the class.
    wc.lpszClassName = _T("Mama Leone");

    // Register this class so that MFC can use it.
    AfxRegisterClass(&wc);
VS2003, VS2005
  • In fereastra "Resource View" dau right-click pe numele fisierului .rc si selectez "Properties"
  • Schimb "MFC Mode" din True in False.
  • ...Urmeaza pasi similari cu cei de la VS6.0...
NOTA: Numele clasei se poate adauga si manual in fisierul de resurse (.rc) folosind optiunea "CLASS".

Exemplu:

Cod:
IDD_MY_DIALOG DIALOGEX 0, 0, 320, 200
STYLE DS_SHELLFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION
| DS_MODALFRAME
| WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "My Dialog"
CLASS "Mama Leone"

Mozilla Firefox Tips & Tricks ( Mediu )


1. Etichetaţi

Dacă aţi adunat o listă mare de semne de carte, veţi observa că e dificil să vă descurcaţi cu ele. Puteţi organiza semnele de carte etichetându-le: puteţi adăuga imediat etichete cu un clic dublu pe iconiţa în formă de steluţă din dreapta adresei.

Puteţi pune câte etichete doriţi unui sait (separaţi-le cu virgulă); puteţi să găsiţi imediat saiturile care au o etichetă tastând eticheta în bara adresei. De exemplu, dacă tastaţi „călătorii” în bara adresei veţi vedea toate saiturile cărora le-aţi aplicat eticheta „călătorii”.

2. Aflaţi totul despre suplimente

Versiunea standard de Firefox e plină de funcţionalităţi, dar de ce să nu primiţi mai mult? Sunt peste 5000 de suplimente - componente extra care adaugă sau schimbă

funcţionalităţi - pe care le puteţi descărca pentru a face pe placul dumneavoa

stră aproape orice doriţi. Mergeţi în meniul Unelte-> Suplimente pentru a deschide gestionarul de suplimente şi pentru a descoperi cum să faceţi un Firefox al dumneavoastră.

3. Căutaţi mai inteligent

Ştiţi deja bara de căutare din Firefox. Dar ştiaţi că o puteţi personaliza adăugând aproape orice motor de căutare ? Clic pe iconiţa din stânga barei şi vedeţi opţiunile disponibile.

Sau mergeţi mai departe şi faceţi clic pe Gestionează

motoarele de căutare pentru a rearanja lista, pentru a adăuga alte motoare sau chiar pentru a atribui scurtături de taste motoarelor favorite. De exemplu, puteţi atribui scurtătura „G” motorului Google, apoi dacă doriţi să căutaţi o reţetă de prăjituri, tastaţi în bara de adrese „G reţetă papanaşi”.

4. Găsiţi ce căutaţi într-o clipă

Funcţionalitatea „Caută în timp ce tastez” economiseşte timpul dumneavoastră. În loc să folosiţi bara de căutare pentru a căuta un cuvânt în pagină, faceţi clic oriunde în pagină şi începeţi să tastaţi cuvântul căutat. Cursorul va sări imediat la prima apariţie a cuvântului căutat.

Puteţi folosi funcţionalitatea şi pentru legături. De exemplu, în loc să mutaţi mausul pe legătura „Află mai multe”, începeţi să tastaţi cuvântul şi când este găsit, apăsaţi Enter.

5. Ştergeţi orice urmă

Din motive de securitate şi intimitate, nu e bine să laşi urme pe unde ai umblat (mai ales dacă calculatorul e folosit şi de altcineva). Firefox vă permite să ştergeţi istoricul navigării şi al descărcărilor, să goliţi memoria tampon şi să ştergeţi cookie-urile cu un singur clic. Mergeţi în meniul Unelte → Şterge datele private pentru a face asta. Sau pentru a fi mai sigur, mergeţi în meniul Unelte → Opţiuni → Intimitate şi bifaţi opţiunea „Şterge datele private de fiecare dată când închid Firefox”.

19.04.2009

MFC Tips - Common Controls

Cum inlocuim o line intr-un edit multiline?
Cine cauta in (editii mai vechi) de MSDN s-ar putea sa gaseasca aceasta:

Exemplu:

Cod:
// The pointer to my edit.
extern CEdit* pmyEdit;
// The string for replacing.
extern LPCTSTR lpszmyString;

int nBegin, nEnd;

// Replace the second line, if it exists, of the edit control
// with the text lpszmyString.
if ((nBegin=pmyEdit->LineIndex(1)) != -1)
{
nEnd = nBegin + pmyEdit->LineLength(1);
pmyEdit->SetSel(nBegin, nEnd);
pmyEdit->ReplaceSel(lpszmyString);
}

Iata o forma mai usor de citit de programatorii MFC:

Cod:
CString strText = _T("Replaced text");
CEdit* pEdit = (CEdit*)GetDlgItem(IDC_EDIT1);
int nBegin = pEdit->LineIndex(1);
if(-1 != nBegin)
{
int nEnd = nBegin + pEdit->LineLength(1); // gresit!
pEdit->SetSel(nBegin, nEnd);
pEdit->ReplaceSel(strText);
}

Problema:
Exemplul de mai sus nu functioneaza pentru ca functia CEdit::LineLength trebuie sa primeasca un "character index" (cel intors de functia CEdit::LineIndex), adica indexul primului caracter din linie numarat de la inceputul textului si nu indexul liniei.

Rezolvare:
(vezi spre comparatie linia in care se apeleaza LineLength)

Cod:
CString strText = _T("Replaced text");
CEdit* pEdit = (CEdit*)GetDlgItem(IDC_EDIT1);
int nBegin = pEdit->LineIndex(1);
if(-1 != nBegin)
{
int nEnd = nBegin + pEdit->LineLength(nBegin); // OK.
pEdit->SetSel(nBegin, nEnd);
pEdit->ReplaceSel(strText);
}

NOTA: in editiile mai noi de MSDN aceasta greseala a fost corectata.

Cum adaug text la un edit control?
Problema:
O metoda des utilizata este de a scoate textul initial cu GetWindowText pentru a adauga textul, apoi a-l pune inapoi cu SetWindowText.

Exemplu:

Cod:
CString strText;
edit.GetWindowText(strText);
strText += pszNewText;
edit.SetWindowText(strText);

Totusi, mai ales in cazul edit-urilor multiline, daca textul din edit este foarte lung iar adaugarile se fac des, metoda nu este chiar asagrozava.

Rezolvare:
Pentru controlul edit setam selectia la sfarsitul textului existent apoi o inlocuim cu textul de adaugat. E mai rapid si nici nu e nevoie de un string intermediar.

Exemplu:

Cod:
// get the text length
const int nLength = edit.GetWindowTextLength();
// set the selection at the end of text
edit.SetSel(nLength, nLength);
// replace selection (append the text).
edit.ReplaceSel(pszNewText);

Rich Edit control - rule #0

Problema:
Tocmai am pus intr-un dialog un contor tip rich edit. Aplicatia se compileaza bine-mersi, dar cand rulez programul, dialogul "refuza" sa mai apara.

Rezolvare:
S-a uitat sau n-am stiut regula #0: controlul trebuie initializat cu AfxInitRichEdit.

Exemplu:

Cod:
BOOL CMyApp::InitInstance()
{
AfxInitRichEdit();
// ...
}

18.04.2009

MFC Tips - SDI / MDI Framework

Cum schimbam titlul intr-un frame window?
Problema:
Intr-o aplicatie SDI/MDI, de obicei se afiseaza pe bara de titlu un string de forma "nume_document - nume_aplicatie" pentru frame-ul principal sau "nume_document" pentru un frame MDI child.

Exemple
  • Untitled - MyApp
  • Test.txt - MyApp
  • Test.txt

Daca incercam sa schimbam asta pur si simplu apeland SetWindowText din oarece loc, nu merge, pentru ca avem toate sansele ca framework-ul sa foloseasca din nou schema de mai sus si sa inlocuiasca titlul nostru schimbat "cu atata truda".

Rezolvare:
Suprascriem functia virtuala (nedocumentata) CFrameWnd::OnUpdateFrameTitle.

Cod:
// MainFrm.h

class CMainFrame : public CFrameWnd // NOTA: poate fi de asemenea
// CMDIChildWnd
// sau CMDIFrameWnd
{
// ...
virtual void OnUpdateFrameTitle(BOOL bAddToTitle);
// ...
};

// MainFrm.cpp
void CMainFrame::OnUpdateFrameTitle(BOOL bAddToTitle)
{
SetWindowText(_T("My Cool App Title"));
}

17.04.2009

Glosar IT (ARPAnet, FTP anonim)

ARPAnet
Spre sfarsitul anilor '60, cand armata SUA suspecta un atac nuclear din partea Uniunii Sovietice, un grup de oameni de stiinta din cadrul Advanced Research Projects Agency au proiectat si dezvoltat un sistem antinuclear destinat interconectarii bazelor si agentiilor militare, prin intermediul unui nou tip de protocol, denumit TCP/IP. Aceasta retea antinucleara, desi nu a fost testata in realitate, a devenit ARPAnet. La inceputul anilor '80, tehnologia ARPAnet a fost pusa in folosinta si in scopuri non-militare, constituind treptat reteaua Internet. ARPAnet a fost scoasa din folosinta in 1990, in favoarea unei retele cu viteza ridicata, intitulata NSFNET.


FTP anonim

Una dintre caracteristicile retelei Internet consta in numarul vast de fisiere disponibile pentru download. Protocolul de transfer anonim de fisiere ofera tuturor utilizatorilor posibilitatea de a descarca fisiere din cadrul unui server FTP corect configurat. In acest mod, utilizatorii fara conturi FTP pot accesa fisiere prin introducerea numelui de utilizator: anonymous si a adresei personale de e-mail drept parola de acces. Intrucat oricine poate accesa fisierele ce au fost configurate pentru FTP anonim, administratorii Web trebuie sa fie atenti in configurarea fisierelor destinate utilizarii publice.

16.04.2009

MFC Tips - Files and Folders

Cum citesc un fisier text linie cu linie?
Rezolvare:
Simplu. Instantiez un obiect tip CStdioFile si apelez CStdioFile::ReadString pana citesc toate liniile (pana cand ReadString intoarce FALSE).

Exemplu:

Cod:
void CFoo::ReadTextFile(LPCTSTR pszFileName, CStringArray& arrLines)
{
arrLines.RemoveAll();
CString strLine;
TRY
{
CStdioFile file(pszFileName, CFile::modeRead);
while(file.ReadString(strLine))
{
arrLines.Add(strLine);
}
}
CATCH_ALL(e)
{
e->ReportError(); // shows what's going wrong
}
END_CATCH_ALL
}


Cum citesc intreg continutul unui fisier (text) intr-un obiect de tip CString?
Rezolvare:
Instanitiez un obiect de tip CFile, ii aflu lungimea cu CFile::GetLength apoi apelez functia CFile::Read.

Exemplu:

Cod:
void CFoo::ReadTextFile(LPCTSTR pszFileName, CString& strText)
{
strText.Empty();
TRY
{
CFile file(pszFileName, CFile::modeRead);
const DWORD dwLength = file.GetLength();
file.Read(strText.GetBuffer(dwLength), dwLength);
strText.ReleaseBuffer();
}
CATCH_ALL(e)
{
e->ReportError();
}
END_CATCH_ALL
}

15.04.2009

Run-Time Type Checking (C++)

O intrebare frecvent intâlnită este "Cum pot afla/verifica tipul unui obiect la run-time?".

Să luam o problemă simplă:
Să se completeze codul de mai jos în aşa fel încât la primul apel funcţia CFoo::SpuneCevaMaiAnimalule să afişeze "Ham! " iar la al doilea să afişeze "Miau! ". Cu alte cuvinte, să se verifice la run-time dacă am transmis ca parametru un pointer la un obiect de tipul Caine sau la Pisica.

Cod:
class Animal {...};
class Caine : public Animal {...};
class Pisica : public Animal {...};
class CFoo
{
public:
void SpuneCevaMaiAnimalule(Animal*) {...}
};

int main(int argc, char* argv[])
{
Caine grivei;
Pisica mitzi;
CFoo foo;
foo.SpuneCavaMaiAnimalule(&grivei);
foo.SpuneCavaMaiAnimalule(&mitzi);
return 0;
}

O prima incercare:
Prima idee ar fi sa adaugăm un membru care să ţină o informaţie despre tip.

Cod:
#include <iostream>
using namespace std;
class Animal

{
public:
enum TipAnimal {TipCaine, TipPisica};
};

class Caine : public Animal
{
public:
Caine() : m_tipAnimal(TipCaine) {}
const TipAnimal m_tipAnimal;
};

class Pisica : public Animal
{
public:
Pisica() : m_tipAnimal(TipPisica) {}
const TipAnimal m_tipAnimal;
};

class CFoo
{
public:
void SpuneCevaMaiAnimalule(Animal*);
};

int main(int argc, char* argv[])
{
// ... (vezi codul din enuntul problemei)
}

void CFoo::SpuneCevaMaiAnimalule(Animal* pAnimal)
{
if(((Caine*)pAnimal)->m_tipAnimal == Animal::TipCaine)
cout << "Ham! ";
else if(((Pisica*)pAnimal)->m_tipAnimal == Animal::TipPisica)
cout << "Miau! ";
}

Priviti, vă rog, la implementarea lui CFoo::SpuneCevaMaiAnimalule şi gândiţi-vă că am avea nu două ci treizeci si nouă de tipuri (clase derivate din Animal).
Urâta rău! Greu de scris, greu de inţeles, uşor de făcut greseli. Deşi se putea si mai rău...

...se poate si mai bine

Hai sa înbunătăţim puţin soluţia!
Ţin numele clasei într-un membru static privat de tip string şi îl accesez printr-o funcţie virtuală.

Cod:
#include <iostream>
#include <string>
using namespace std;
class Animal

{
public:
virtual bool EsteDeTipul(const string&) = 0;
};

class Caine : public Animal
{
static const string m_nume_clasa;
public:
virtual bool EsteDeTipul(const string&);
};

class Pisica : public Animal
{
static const string m_nume_clasa;
public:
virtual bool EsteDeTipul(const string&);
};

class CFoo
{
public:
void SpuneCevaMaiAnimalule(Animal*);
};

int main(int argc, char* argv[])
{ }

const string Caine::m_nume_clasa = "Caine";
bool Caine::EsteDeTipul(const string& nume_clasa)
{
return (nume_clasa == m_nume_clasa);
}

const string Pisica::m_nume_clasa = "Pisica";
bool Pisica::EsteDeTipul(const string& nume_clasa)
{
return (nume_clasa == m_nume_clasa);
}

void CFoo::DoSomething(Animal* pAnimal)
{
if(pAnimal->EsteDeTipul("Caine"))
cout << "Ham! " << endl;
else if(pAnimal->EsteDeTipul("Pisica"))
cout << "Miau! " << endl;
}

Din nou uitându-ne la CFoo::SpuneCevaMaiAnimalule, pare acum ceva mai clară si mai uşor de scris.
Putem merge mai departe prin definirea urmatoarelor macro-uri:

Cod:
#define DECLARE_RUNTIME_CLASS
private:
static const string m_nume_clasa;
public:
virtual bool EsteDeTipul(const string&);
#define IMPLEMENT_RUNTIME_CLASS(class_name)
const string nume_clasa##::m_nume_clasa = #nume_clasa;
bool nume_clasa##::EsteDeTipul(const string& nume)
{return (nume == m_nume_clasa);}

Ne rămane şi mai puţin cod de scris:

Cod:
#include <iostream>
#include <string>
using namespace std;
class Animal

{
public:
virtual bool EsteDeTipul(const string&) = 0;
};

class Caine : public Animal
{
DECLARE_RUNTIME_CLASS
};

class Pisica : public Animal
{
DECLARE_RUNTIME_CLASS
};

class CFoo
{
public:
void SpuneCevaMaiAnimalule(Animal*);
};

int main(int argc, char* argv[])
{ }

IMPLEMENT_RUNTIME_CLASS(Caine)
IMPLEMENT_RUNTIME_CLASS(Pisica)

void CFoo::SpuneCevaMaiAnimalule(Animal* pAnimal)
{
if(pAnimal->EsteDeTipul("Caine"))
cout << "Ham! ";
else if(pAnimal->EsteDeTipul("Pisica"))
cout << "Miau! ";
}

In felul acesta ne-am apropiat de soluţia din MFC (Microsoft Foundation Classes library).

Daca folosim MFC, atunci e floare la ureche !
Majoritatea claselor din MFC deriva din CObject care printre altele implementează si un mecanism de verificare a tipului la run-time. Este un pic mai complicat decât în exemplul de mai sus dar tebuie să-l iertam pentru ca face mai multe decât ne dea pur şi simplu tipul obiectului. Mai multe despre "minunatele proprietati" ale clasei CObject pot face subiectul unui articol separat.
Oricum, dacă folosim MFC, problema noastră se poate rezolva simplu şi elegant, cam asa:

Cod:
#include <afx.h>
class Animal : public CObject
{
DECLARE_DYNAMIC(Animal)
};
class Caine : public Animal
{
DECLARE_DYNAMIC(Caine)
};

class Pisica : public Animal
{
DECLARE_DYNAMIC(Pisica)
};
class CFoo
{
public:
void SpuneCavaMaiAnimalule(Animal*);
};
int main(int argc, char* argv[])
{ }
IMPLEMENT_DYNAMIC(Animal, CObject)
IMPLEMENT_DYNAMIC(Caine, Animal)
IMPLEMENT_DYNAMIC(Pisica, Animal)

void CFoo::SpuneCavaMaiAnimalule(Animal* pAnimal)
{
if(pAnimal->IsKindOf(RUNTIME_CLASS(Caine)))
printf("Ham! ");
else if(pAnimal->IsKindOf(RUNTIME_CLASS(Pisica)))
printf("Miau! ");
}

O alta abordare: RTTI
O altă abordare este folosirea mecanismul RTTI (Run-Time Type Information) al limbajului C++. Acesta permite folosirea a doi operatori "speciali": typeid si dynamic_cast.
Prima rezolvare cu RTTI a problemei noastre este prin folosirea operatorului typeid. Acesta intoarce o referinţă la un type_info care ţine informaţii despre tipul obiectului pasat ca parametru.

Cod:
#include <iostream>
using namespace std;
class Animal {virtual void Dummy(){};};
class Caine : public Animal{};
class Pisica : public Animal{};
class CFoo

{
public:
void SpuneCavaMaiAnimalule(Animal*);
};

int main(int argc, char* argv[])
{ }

void CFoo::SpuneCavaMaiAnimalule(Animal* pAnimal)
{
const type_info& ti = typeid(*pAnimal);
if(ti == typeid(Caine))
cout << "Ham! ";
else if(ti == typeid(Pisica))
cout << "Miau! ";
}

Frumos!
Poate aţi observat că în clasa Animal am pus, deşi nu-mi trebuie la nimic, o funcţie virtuală. De ce? Simplu: ca sa meargă jucărica cu RTTI-ul, trebuie o clasă de tip "polimorfic", adică sa aibă cel puţin o funcţie virtuală.

Putem de asemenea să ne bazăm pe operatorul dynamic_cast. Acesta întoarce zero daca îi plasăm un pointer la un obiect de tipul care nu trebuie. Deci am putea scrie

Cod:
void CFoo::SpuneCavaMaiAnimalule(Animal* pAnimal)
{
if(dynamic_cast<Caine*>(pAnimal))
cout << "Ham! ";
else if(dynamic_cast<Pisica*>(pAnimal))
cout << "Miau! ";
}

La urma urmei la ce bun? Acestea fiind zise, am şi eu o intrebare: chiar e nevoie să ştim
tipul unui obiect la run-time? Eu zic ca nu. Putem uita toate chestiile de mai sus cu condiţia să ne amintim de polimorfism si să inţelegem pentru ce, de fapt, a băgat mosu' Stroustrup funcţiile virtuale în C++.

Cod:
#include <iostream>
using namespace std;
class Animal


{
public:
virtual void IacaSpun() = 0;
};

class Caine : public Animal
{
public:
virtual void IacaSpun();
};

class Pisica : public Animal
{
public:
virtual void IacaSpun();
};

class CFoo
{
public:
void SpuneCavaMaiAnimalule(Animal*)
};

int main(int argc, char* argv[])
{ }

void Caine::IacaSpun()
{
cout << "Ham! ";
}

void Pisica::IacaSpun()
{
cout << "Miau! ";
}

void CFoo::SpuneCavaMaiAnimalule(Animal* pAnimal)
{
pAnimal->IacaSpun();
}

O ultimă privire la CFoo::SpuneCavaMaiAnimalule. Frumoasă, curată, simplă, nu-i aşa?

Mi-am propus in articolul de faţă doar o introducere în "recunoaşterea tipurilor la run-time" prin rezolvarea unei probleme simple.
Succes !

14.04.2009

Glosar IT (ActiveX, DOM, JPEG)

ActiveX

Acest set de tehnologii dezvoltat de Microsoft ofera instrumente pentru crearea de legaturi intre aplicatiile desktop si mediul Web. Utilizand o varietate de instrumente de programare (inclusiv Java, Visual Basic si C++), dezvoltatorii pot crea continut Web interactiv. Spre exemplu, tehnologia ActiveX permite utilizatorilor vizualizarea de documente Word si Excel direct in programul de navigare Web.


DOM

Modelul de obiect al documentului DOM constituie o specificatie dezvoltata de W3C, ce permite manipularea tuturor elementelor unei pagini Web (grafica, text, stiluri etc.) de catre programe software si limbaje de programare (de tipul: JavaScript si VBScript).

Spre exemplu, DOM face posibila definirea drept obiect a fiecarei litere individuale din cadrul unei pagini Web, alocand ulterior caracteristici separate, de genul: culoare, dimensiune si stil. DOM este una din tehnologiile de baza ale DHTML, impreuna cu CSS, HTML traditional si limbajele de programare.

JPEG

Joint Photographic Experts Group Acest format de fisier pentru imagini bogate in culori a fost dezvoltat de comitetul Joint Photographic Experts Group. JPEG compreseaza elemente grafice de culoare fotografica imbunatatita, in comparatie cu alte metode de compresie a imaginii (GIF) si retine un inalt grad de persistenta a culorii.

Overlapped/popup/child/owned Windows

De mult, tare de mult, pe cand Windows-ul mai purta pampershi (in versiunile 1.x), existau doua tipuri principale de ferestre: tiled si overlapped (astea din urma, mult mai cool, in sensul ca le puteai aranja si pune una peste alta). Intre timp ferestrele tiled au disparut, nici nu se mai stie prea bine cum au fost alea, iar azi putem spune ca toate ferestrele sunt overlapped. Asta-i, cred, un motiv pentru care WS_OVERLAPPED are valoarea 0 (zero).

Cod:
// WINUSER.H
#define WS_OVERLAPPED 0x00000000L

De altfel, desi ferestrele tiled nu mai exista, totusi stilul WS_TILED n-a fost sters cu radiera si are valoarea:

Cod:
// WINUSER.H
#define WS_TILED WS_OVERLAPPED


Clar pina aici.
Acum totusi, se vorbeste intre programmerii Windows, se scrie prin manuale, de ferestre overlapped, popup, si child.

Care-i deosebirea dintre ele?
Cel mai simplu, o luam de la coada la cap:
  • 3. child windows
    - sunt alea care au stilul WS_CHILD; principala lor proprietate e ca nu pot exista decat in zona client al unei ferestre parinte; child sunt de cele mai multe ori controalele (buton, edit, listbox, etc); toate celelalte, deci care nu sunt child, se mai numesc ferestre top-level, pot exista oriunde in ecran si sunt din categoriile de mai jos.
  • 2. popup windows
    - sunt alea care nu au stilul WS_CHILD dar au stilul WS_POPUP; se foloseste de obicei pentru ferestre de mici dimensiuni si care exista pentru scurt timp.
  • 1. overlapped windows
    - sunt alea care nu au nici stilul WS_CHILD nici stilul WS_POPUP; se foloseste de obicei ca fereastra principala a unei aplicatii; deosebirea principala intre ferestrele overlapped si popup este ca cele overlapped au intotdeauna un caption (bara de titlu) pe cand la cele popup caption-ul este optional.

In practica, aceste stiluri principale sunt utilizate in combinatie cu alte stiluri WS_BORDER, WS_CAPTION, WS_SYSMENU, etc si exista chiar definite (in WINUSER.H) stiluri "compuse" cum ar fi de exemplu:

Cod:
#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED |
WS_CAPTION |
WS_SYSMENU |
WS_THICKFRAME |
WS_MINIMIZEBOX |
WS_MAXIMIZEBOX)

#define WS_POPUPWINDOW (WS_POPUP |
WS_BORDER |
WS_SYSMENU)

Acuma, revenind la stilul WS_OVERLAPPED (cel cu valoarea zero). Cum spuneam, si asta-i o ciudatenie care trebuie tinuta minte, o fereastra cu stilul WS_OVERLAPPED "curat", adica fara WS_CAPTION si WS_BORDER are totusi un caption si un border probabil mostenire din mosi stramosi, de pe vremea cand Windows-ul purta pampershi...

A mai ramas termenul owned window.
De cele mai multe ori de foloseste in mod gresit termenul de child window in loc de owned window.
Dupa cum am mai spus, o fereastra child are setat stilul WS_CHILD iar principala sa proprietate este ca nu poate exista decat in zona client al unei ferestre parinte.
O fereastra owned, poate fi orice fereastra care este top-level (deci overlapped sau popup) dar depinde de o alta fereastra numita owner. Poate exista oriunde in ecran dar este distrusa cand este distrus ownerul si este ascunsa atunci cand ownerul este ascuns sau minimizat. De asemenea, este intotdeauna afisata in fata owner-ului.

13.04.2009

C# Data Layer

Exista multe stiluri de a scrie cod care ineractioneaza cu o baza de date. Este recomandata impartirea pe straturi a codului care se ocupa de asta. Un mod de a face asta este cel pe 3 straturi: Data Layer, BussinessLogic si Applicatie. Acest articlo se vrea o descriere a modului cum poate fi creat stratul DataLayer, insa o sa aiba ceva exemple si de cum poate fi folosit acest strat pentu a trimite informatii spre straturile superioare.

Lucrurile arata cam asa:

[Applicatie] <----> [Bussiness Layer] <----> [DataLayer] <----> [DataBase]



DataBase poate fi orice, M$ Sql, Oracle, Acces etc, insa codul o sa fie scris pentru M$ Sql.

Intr-un proiect nou, se creaza o noua clasa, cu numele dal.cs

Pentru a construi o clasa (pe care o voi numi DAL in continuare) trebuie sa importam in proiectul nostru namespace-urile System.Data.SqlClient si System.Data.SqlClient (in plus fatza de ce isi aduce default VisualStudio).

La mine arata cam asa (deocamdata):

Cod:
using System;
using System.Collections;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace TestEMNdb
{
public class DAL
{
}
}

Primul lucru de care avem nevoie este connectionString, unde definim parametrii necesari accesari serverului unde se aftla baza de date pe care o vom folosi.

Pentru acest exemplu vom folosi urmatorul string:
Data Source=EXPEED-L006SQLEXPRESS;
Initial Catalog=Northwind;
Integrated Security=SSPI;


Unde EXPEED-L006SQLEXPRESS este numele serverului care ruleaza pe calculatorul meu, Northwind este numele bazei de date pe care o voi folosi (vine ca exemplu cu sql server) isr ultimul parametru, Integrated Security=SSPI defineste nivelul de securitate pe care il va folosi connexiunea (se vor folosi drepturile userului curent al sistemului de operare).

Locul cel mai bun de pastrare a acestui string nu este in codul clasei, insa pentru moment, o sa il pun in interiorul clasei (hard coded). Pana la sfarsitul articolului o sa ii gasim un loc mai bun.

Deasemeni, avem nevoie de 2 obiecte, SqlConnection si SqlCommand (ambele se gasesc in numele de spatiu System.Data.SqlClient).

Acum ar trebui sa ne gandim si la un constructor pentru aceasta clasa, in interiorul caruia sa initializam ceea ce avem pana acum, SqlConnection si SqlCommand:

conn = new SqlConnection(connString); // definim un obiect de tipul SqlConnection, care sa aiba grija de conexiunea cu baza de date apoi,
command = new SqlCommand(); // un obiect care sa se ocupe de ceea ce vrem sa ii transmitem bazei de date, si la urma
command.Connection = conn; // ii zicem instantei obiectului command sa foloseasca obiectul conn pentru a transmite ce are de transmis bazei de date.

Pana acum clasa noastra arata asa:

Cod:
using System;
using System.Collections;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace TestEMNdb
{
public class DAL
{
string connString = @"Data Source=EXPEED-L006SQLEXPRESS; Initial Catalog=Northwind; Integrated Security=SSPI;";
SqlConnection conn;
SqlCommand command;

public DAL()
{
conn = new SqlConnection(connString);
command = new SqlCommand();
command.Connection = conn;
}
}
}

Deocamdata avem o clasa care nu prea face nimic. Initializeaza niste obiecte, si cam atat. Ca sa faca ceva, sa ii punem niste metode. Ar fi necesare o metoda Open() care sa deschida coneciunea la baza de date, si o alta metoda Close(), evident, sa inchida coneciunea deschisa de metoda Open(). Acestea sunt cele mai simple metode ale acestei clase.

Cod:
public void Open()
{
conn.Open();
}

public void Close()
{
if (conn != null)
conn.Close();
}

In metoda Close() inainte de a inchide connexiunea, verific daca obiectul conn este nenul. Daca obiectul conn este null, si se incearca executarea metodei conn.Close() o exceptie va fi aruncata. Daca acest obiect nu e null, inchid conexiunea. Nu trebuie sa verific altceva, intru-cat inchiderea unei conexiuni care nu este deschisa nu arunca o exceptie. Deci executarea acestei functii este destul de sigura.

Pentru c acum putem deschide o conexiune la baza de date, sa incepem sa creem niste metode care sa ne aduca si ceva date stocate in tabelele bazei noastre de date.

Una dintre cele mai simple interogari pe care le putem face asupra tabelelor, este sa cerem o singura valoare, ca de exemplu: cat costa produsul X? sau cati munitori sunt inregistrati? Sau in ce data am facut X? Cu alte cuvinte, rezultatul pe care il primim este o valoare care reprezinta rezultatul executiei interogarii noastre asupra bazei de date si care este returnata in coloana 1 randul 1. Orice alte rezultate returnate de baza de date, sunt ignorate.

Cum facem sa primim asa ceva? Destul de simplu! Obiectul command are o metoda care face asta petru noi: command.ExecuteScalar(). Avem nevoie numai sa transmitem obiectului command interogarea sql, si el se ocupa de restul.

Cod:
public object GetScalar(string sql)
{
command.CommandText = sql;
command.CommandType = CommandType.Text;
return command.ExecuteScalar();
}

De retinut este ca aceasta functie returneaza un obiect. Pentru afolosi valoarea returnata trebuie facut (in mometul folosiri ei) casting la tipul de data pe care ne asteptam sa il primim.

Doar ca exemplu de folosire a acestei functii (nu este parte a obiectului DAL - intru-cat aici nu trebuie sa avem decat functii generice, nu specifice unei tabele/baze de date/actiuni) aceasta functie se foloseste asa:

Cod:
string sql = "select count(*) from Products";
conn.Open();
int result = (int)GetScalar(sql);
conn.Close();

Urmatoarea functie utila este o functie care sa ne permita sa face actiuni DML asupra bazei de date. Obiectul connect are inca o metoda utila numita ExecuteNonQuery(). Aceasta executa o actiune DML si returneaza numarul de randuri afectate. Aceasta functie este folosita la inserarea de date, la stergerea de date sau modificarea datelor.

Cod:
public void ExecuteNonQuery(string sql)
{
command.CommandType = CommandType.Text;
command.CommandText = sql;
command.ExecuteNonQuery();
}

Ca sa recapitulam, pana in acest moment am avansat destul de mult. Avem o conexiune, pe care o putem controla, si avem posibilitatea sa primim (deocamdata putine) si sa trimitem date. Destul de bine pentru cateva linii de cod.

Insa in marea majoritate a cazurilor, avem nevoie de mai mult decat o singura valoare. Avem nevoie de un rand, cateva randuri sau chiar de un tabel intreg. Una dintre cele mai simple si eficiente metode de a citi randuri returnate de o instructiune select este folosind SqlDataReader. SqlDataReader este o clasa care ne permite sa citim date intr-un mod foarte eficient. SqlDataReader nu se poate folosi pentru scrierea datelor, iar citirea se face numai prin parcurgerea rezultatelor returnate de instructiunea select numai intr-un sens: inainte! Cu alte cuvinte, daca acum citim randu 4, urmatorul rand la care avem acces pentru citire este randul 5. Pentru a ajunge la randul 3 trebuie sa o luam cu cititul de la capat, de la randul 1 (parcurgand 1 si 2 pentru a avea acces la randul 3).
De regula, datele citite cu SqlDataReader sunt salvate in obiecte care permit parcurgerea datelor in ambele sensuri (sau accesarea prin index a unui element dorit).

Clasa SqlDataReader este definita in namespace-ul System.Data.SqlClient.

Pentru a crea o instantza a SqlDataReader se foloseste metoda ExecuteReader() a unui obiect SqlCommand.

Cod:
SqlDataReader reader = command.ExecuteReader();

Pentru a putea citi date folosind SqlDataReader avem nevoie de o conexiune deschisa la baza de date. De mentionat este ca aceasta conexiune va fi "ocupata" pana ce obiectul SqlDataReader o elibereaza.

Revenind la clasa noastra DAL, o sa o completam cu o functie noua, si anume una care sa returneze un obiect de tip SqlDataReader.

Cod:
public SqlDataReader GetReader(string sql)
{
command.CommandType = CommandType.Text;
command.CommandText = sql;
SqlDataReader dataReader = command.ExecuteReader();
return dataReader;
}

Acestei functii i se transmite ca parametru interogarea sql dorita, iar setul de randuri returnate de sql este accesibil prin intermediul obiectului de tip SqlDataReader returnat. Nu uitati ca inainte de a apela aceasta functie sa deschideti o conexiune, iar la final sa inchideti conexiunea deschisa!

Un exemple de folosire al acestei functii este (nu face parte din DAL.cs - ci dintr-o clasa de tip bussinessLogic):

Cod:
string sql = "select name from students";
con.Open();
SqlDataReader reader = GetReader(sql);
while (reader.Read())
{
// aici se salveaza/prelucreaza/etc datele primite
}
con.Close();

O alta metoda de a avea acces la datele returnate de o instructiune select este salvarea rezultatelor returnate in obiecte de tip DataTable sau DataSet. Descrierea acestor obiecte nu face parte din acestu tutorial. Se pot gasi tutoriale. Pe msdn sunt explicate aceste obiecte: DataTable si [url="http://msdn2.microsoft.com/en-us/librar /system.data.dataset.aspx"]DataSet[/url]

Deci, pe scurt, datele returnate dintr-o interogare sql se pot salva in obiecte de tip DataTable si DataSet. Aceste obiecte se trimit prin referintza functiei care face citirea datelor din baza de date. Aceasta functie se ocupa de "salvarea" datelor in obiect.

Cod:
public void Fill(DataTable dt, string sql)
{
SqlDataAdapter adapter = new SqlDataAdapter(sql, conn);
adapter.Fill(dt);
}

public void Fill(DataSet ds, string sql)
{
SqlDataAdapter adapter = new SqlDataAdapter(sql, conn);
adapter.Fill(ds);
}

Avantajele folosiri DataTable sau DataSet sunt ca datele pot fi parcurse apoi fara a necesita o conexiune deschisa la baza de date. Datele pot fi parcurse in ambele sensuri, sau prin intermediul indecsilor. Deasemeni obiectele de acest tip ofera multe moduri de a prelucra datele, de a cauta date specifice etc (documentatia msdn specifica toate metodele obiectelor de acest tip). Unul din dezavantajele folosiri acestui tip de obiect este consumul de resurse. Daca trebuiesc citite date care trebuiesc parcurse in ambele sensuri, date care trebuiesc parcurse de mai multe ori, date care trebuiesc prelucrate incrucisat, etc folositi datatable sau DataSet. Daca nu, folosirea SqlDataReader este indicata (citirea pentru afisare a unui tabel, incarcarea intr-un obiect specific a anumitor valor din tabele, popularea unor obiecte de tip colectie (ArrayList, HashTable etc)).

Cam asta e ceea ce trebuie sa contina (un minim) o clasa de tip DAL. Codul intregi clase este:

Cod:
using System;
using System.Collections;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace TestEMNdb
{
public class DAL
{
string connString = @"Data Source=EXPEED-L006SQLEXPRESS; Initial Catalog=Northwind; Integrated Security=SSPI;";
SqlConnection conn;
SqlCommand command;

public DAL()
{
conn = new SqlConnection(connString);
command = new SqlCommand();
command.Connection = conn;
}

public void Open()
{
conn.Open();
}

public void Close()
{
if (conn != null)
conn.Close();
}

public object GetScalar(string sql)
{
command.CommandText = sql;
command.CommandType = CommandType.Text;
return command.ExecuteScalar();
}

public void ExecuteNonQuery(string sql)
{
command.CommandType = CommandType.Text;
command.CommandText = sql;
command.ExecuteNonQuery();
}

public SqlDataReader GetReader(string sql)
{
command.CommandType = CommandType.Text;
command.CommandText = sql;
SqlDataReader dataReader = command.ExecuteReader();
return dataReader;
}

public void Fill(DataTable dt, string sql)
{
SqlDataAdapter adapter = new SqlDataAdapter(sql, conn);
adapter.Fill(dt);
}

public void Fill(DataSet ds, string sql)
{
SqlDataAdapter adapter = new SqlDataAdapter(sql, conn);
adapter.Fill(ds);
}
}
}

Accesul la functiile acestei clase trebuie sa se fac prin intermediul unei clase BusinessLogic, respectand principiile N-Tier.

Prin intermediul acestei clase putem executa (aproape) toate operatiile de baza asupra unei baze de date. Ea poate fi imbunatatita prin adaugarea altor functii si facilitati, precum suport pentru executarea Stored Procedures, interogarilor parametrizate samd.

    Blog din Moldova    FastCounter 

 
Copyright © 2008-2010 Foster1. All rights reserved.