Sunteți pe pagina 1din 4

Dialoguri i Controale

Pentru fiecare box de dialog care apare pe ecran exist dou entiti pe care trebuie s le dezvoltm: o resurs box de dialog i o clas box de dialog. Resursa box de dialog este folosit pentru a desena boxa de dialog i controalele pe care le conine. Clasa menine valorile din boxa de dialog i exist o funcie membru a acestei clase care este folosit pentru a activa boxa de dialog. n general se construiete un meniu ce va conine o opiune pentru activarea acestui dialog. Resursa box de dialog se construiete cu editorul de resurse. Pe baza acestei resurse Class Wizard va genera clasa corespunztoare. n general boxele de dialog sunt derivate din CDialog.

Crearea unei resurse de dialog


Controalele uzuale din Windows pot fi folosite ntr-o box de dialog. Enumerm dintre acestea: Static text. Folosit de alte controale pentru descriere. Edit box. Folosit pentru a prelua anumite informaii (iruri de caractere, numere). Poate fi definit ca avnd o singur linie sau mai multe linii. Button. Fiecare box de dialog are implicit butoanele OK i Cancel care pot fi pstrate sau terse. Check box. Permite selectare sau deselectare. Lucreaz independent. Radio button. Permite selectare sau deselectare. Nu lucreaz independent. List box. Conin o list de articole, din care utilizatorul poate selecta un articol la un moment dat. Nu putem tasta text n cadrul acestui control. Combo box. Este o combinaie ntre Edit box i List box.

Definirea boxei de dialod i ID-ul Controlului


Fiecare box de dialog are un ID unic (un identificator), iar controalele din cadrul boxei de dialog au de asemenea ID-uri. Fiecare control din cadrul unei boxei de dialog este vzut ca o fereastr. Deci o parte din funcionalitatea unei ferestre se va reflecta i asupra controlului. Clasa CDialog este derivat din clasa CWnd care descrie funcioanlitatea unei ferestre. Dac avem un pointer la fereastr (GetDlgItem() pentru dialoguri) putem apela metode specifice pentru aceasta. De exemplu putem ascunde o fereastr (ShowWindow()), o putem activa sau dezactiva (EnableWindow()) sau i putem citi/modifica coninutul (GetWindowText(), SetWindowText()), etc. Pentru a ti ce funcii se aplic va trebui s consultm clasa de baz i clasa derivat. Editorul de resurse definete implicit un ID pentru boxa de dialog i ID-uri pentru controalele pe care le atam acesteia. Putem modifica aceste ID-uri (Properties din meniul contextual disponibil pentru controlul selectat sau boxa de dialog) pentru a le da un sens conform aplicaiei noastre. De obicei aceste ID-uri ncep cu IDD_ urmate de un text pentru boxele de dialod i cu IDC_ pentru controalele din boxa de dialog. (Exemple: IDD_DIALOG1, IDC_STATIC1, IDC_EDIT1, IDC_RADIO1, etc.). Pentru controalele dintr-o box de dialog putem defini date membru (variabile) n cadrul clasei pentru a menine starea acestora. Cu ajutorul Class Wizard-ului putem defini aceste variabile i le putem manevra ntr-o anumit msur. De asemenea putem defini i implementa funciile necesare tratrii mesajelor de notificare pe care acestea le suport. Observaie: MFC utilizeaz tabele pentru a gestiona harta de mesaje precum i pentru a menine legtura dintre o variabil i un control. A se vedea clasa CDataExchange i funcia DoDataExchange(). Exerciiu. Se va crea o box de dialog cu mai multe controale i se vor explica aceste lucruri pe codul rezultat. Se vor urmri posibilitile de aliniere a controalelor, redimensionare, ordinea controalelor, stilurile, etc. Tipuri de date pentru fiecare control: Edit box. n mod obinuit un string, dar poate fi i un int, long, float. Check box. int Radio button. int List box. String Combo box. String

Scrollbar. int

Pentru a afia boxa de dialog va trebui s apelm funcia membru DoModal() n cazul boxelor de dialog modale. Boxele de dialog amodale vor fi tratate separat, deoarece nu urmeaz aceeai construcie.

Exemplu de lansare n execuie a unei boxe de dialog


CSdiDialog dlg; // se creaza obiectul pe stiva dlg.m_check = TRUE; // variabila atasata unui control check dlg.m_edit = "hi there"; // variabila atasata unui control Edit CString msg; if (dlg.DoModal() == IDOK) // are loc afisarea dialogului { msg = "You clicked OK. "; } else { msg = "You cancelled. "; } msg += "Edit box is: "; msg += dlg.m_edit; AfxMessageBox (msg);

Tiprirea codului (Autocompletion: Tools->Options->Editor) Cnd tastm codul avem posibilitatea de a vedea numele variabilelor membru i a funciilor din clas. Dac tastm dlg. i apoi pauz, va aprea o fereastr, ce va lista toate variabilel membru i funciile din clas, inclusiv cele motenite din clasa de baz. n continuare vom folosi tastele sgei pentru selecie i apoi apsm tasta Space pentru a trece selecia fcut n cadrul codului.

Ce se ascunde n spatele unei boxe de dialog?


Cel mai important lucru este nelegerea funciei care urmeaz. void CSdiDialog::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CSdiDialog) DDX_Control(pDX, IDC_LIST1, m_listbox); DDX_Check(pDX, IDC_CHECK1, m_check); DDX_Text(pDX, IDC_EDIT1, m_edit); DDV_MaxChars(pDX, m_edit, 10); DDX_Radio(pDX, IDC_RADIO1, m_radio); //}}AFX_DATA_MAP } Trebuie s tim c ntre boxa de dialog afiat pe ecran i variabilele care menin starea anumitor controale este definit un schimb bidirecional de date. Un rol important l joac aici funcia UpdateData() care stabilete practic direcia de schimb ecran->variabile sau variabile->ecran. Funciile care ncep cu DDX_ realizeaz schimbul de date. Exist 34 de funcii care ncep cu DDX, una pentru fiecare tip de dat care poate fi schimbat ntre clas i dialog. Primul parametru arat direcia, al doilea este ID-ul controlului iar al treilea parametru este numele variabilei. Codul este adgat de Class Wizard.

OBSERVAIE: Anumite funcii DDX nu sunt generate de Class Wizard. De exemplu, cnd ne conectm la o valoare din List Box, singura alegere posibil pentru tip este CString. Alegnd acest lucru, Class Wizard va genera un apel la DDX_LBString() care conecteaz stringul selectat la variabila membru de tip CString. Exist situaii cnd un index de tip int este mai bun. Pentru acest lucru exist funcia DDX_LBIndex() care realizez acest schimb de informaii. O parte dintre funciile din List Box folosesc indeci pentru a manevra articolele dintr-un list box. Putem aduga cod n DodataExchange(), dar n afara comentariilor speciale introduse de Class Wizard. n acest caz vom aduga singuri variabila membru la clas.
Funciile care ncep cu DDV realizeaz validarea datelor. Prametrul al doilea este numele variabilei, iar al treilea specific limitele.

Utilizarea controlului List Box


Un control de acest tip nu poate fi iniializat dect atunci cnd boxa de dialog este afiat, deci este pe ecran. Din acest motiv trebuie s fim ateni la momentul iniializrii. Nu putem apela funcii membru din aceast clas atta timp ct dialogul nu este afiat. Acest lucru este valabil pentru orice control pe care l accesm ca un control i nu ca o valoare. O asemenea iniializare are loc n funcia OnInitialDialog() care este apelat de cadrul de lucru (frame work) imediat ce dialogul a fost afiat pe ecran. Aceast funcie este apelat la trimiterea mesajului WM_INITDIALOG. Cade n sarcina noastr s includem acest mesaj n tratare (se face cu Class Wizard). Se va explica n mod concret cum se folosete Class Wizard pentru a aduga noi mesaje tratate de clasa respectiv. De asemenea tot cu Class Wizard se ataeaz variabile pentru controalele dintr-o box de dialog.

Un exemplu pentru OnInitDialog()


BOOL CSdiDialog::OnInitDialog() { CDialog::OnInitDialog(); m_listbox.AddString("First String"); m_listbox.AddString("Second String"); m_listbox.AddString("Yet Another String"); m_listbox.AddString("String Number Four"); m_listbox.SetCurSel(2); return TRUE; } // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE

Aceast funcie apeleaz mai nti OnInitDialog() din clasa de baz, iar n continuare se execut codul din cadrul funciei. Stringurile vor fi afiate n ordinea n care au fost introduse (adugate) cu funcia AddString(). n final se apeleaz funcia SetCurSel(), funcie care are drept parametru un index ce identific articolele din List Box. Indexul pentru primul articol are valoarea 0 (zero).

OBSERVAIE: n mod obinuit, articolele n list box sunt adugate dintr-un vector sau o list. Pentru acest lucru se folosesc clasele colecie din MFC (CStringArray, CList, etc.).

Pentru a menine (memora) articolul (string-ul) selectat n list box, vom aduga o variabil membru de tip CString la aceast clas. Aceast variabil va fi privat, i deci vom aduga funcii membru publice la clas pentru a manevra aceast variabil pentru a pstra stilul de programare impus de POO. Pentru selecie se va trata mesajul de notificare BN_CLICKED, care are semnificaia c utilizatorul a fcut o selecie n list box. Funcia care trateaz acest mesaj se va aduga tot cu Class Wizard. n codul care urmeaz se exemplific preluarea stringului din list box la apsarea butonului OK. void CSdiDialog::OnOK() { int index = m_listbox.GetCurSel(); if (index != LB_ERR) { m_listbox.GetText(index, m_selected); } else { m_selected = ""; } CDialog::OnOK(); } Explicaii. Funcia GetCurSel() ntoarce indexul la articolul selectat. Dac acesta este valid (index != LB_ERR) se obine valoarea acestui articol n variabila m_selected care este de tip CString folosind funcia GetText al crei prim parametru este indexul articolului.. n final se apeleaz funcia OnOK() din clasa de baz pentru a executa alte procesri necesare. n cele ce urmeaz vom observa apeluri la funciile din clasa de baz. Aceste apeluri sunt generate de Class Wizard. Exist i excepii cnd aceste apeluri trebuiesc invalidae (comentate). Ca un exemplu vom vedea la mprtirea zonei client n mai multe ferestre (splitting window) la apelul funciei OnCreateClient().

Folosirea butoanelor radio


La afiarea unei boxe de dialog care conine butoane radio vom vedea c nici un buton nu este selectat. Pentru a realiza o selecie implicit adugm n OnInitDialog() urmtoarele linii de cod. m_radio = 1; UpdateData(FALSE); Variabila m_radio este ataat unui grup de butoane radio i reprezint indexul butonului n acest grup. Primul buton are indexul 0 (zero). Funcia UpdateData(FALSE) stabilete direcia de actualizare, care n acest caz este de la variabil la ecran i n final are loc un refresh al boxei de dialog. Un grup de butoane radio poate fi accesat dup ce boxa de dialog nu mai este pe ecran, deci nu trebuie s tratm OnOK() sau ONCancel().