Problema TabControl

Intrebari legate de programarea cu biblioteci precum MFC, ATL, WTL si GDI+.
Post Reply
carrera
Junior
Junior
Posts: 38
Joined: 23 Aug 2007, 12:06

Problema TabControl

Post by carrera » 30 Jul 2012, 12:17

Salut,

- Am o aplicatie MDI care contine 3 dialog-uri, primul le gazduieste pe celelalte doua printr-un tabControl.Problema e ca la rulare nu-mi apar controalele din cele doua dialog-uri.Paginile apar, dar...goale.Mentionez ca intr-o aplicatie dialog-based merg fara probleme.(In cazul asta dialogul principal gazduia paginile).
Vreo idee?
Thx.

ps: am pus in atasament exemplul.
Attachments
333.rar
(60.67 KiB) Downloaded 165 times



User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Problema TabControl

Post by Ovidiu Cucu » 31 Jul 2012, 09:35

Ce ai facut pana acum e o intreaga brambureala.
Ba ai derivat din CTabCtrl, ba din CDialog, ba din CPropertyPage, ai incurcat parintii si in fine ai dat-o in bara cu calculul dreptunghiurilor in care muti paginile.
Incearca sa pui putina ordine.
Ca sa vezi din ce se compune un property sheet, arunca mai intai un ochi in articolul asta: http://www.codexpert.ro/articole.php?id=11
Conform schemei de acolo ar trebui sa ai urmatoarele:
  1. O fereastra parinte (uzual un dialog, deci o clasa derivata din CDialog) ca suport pentru celelalte elemente.
  2. Un control tab (intr-o clasa derivata CTabCtrl) care il folosesti pentru comutarea paginilor
  3. N ferestre (uzual dialoguri, clase derivate din CDialog) care reprezinta paginile. De obicei astea au ca parinte controlul tab.
  4. Optional, alte controale comune tuturor paginilor, de obicei butoane "OK", "Cancel", "Apply", etc.

Paginile le tii intr-un array, asa cum ai facut si tu.
Ca sa comuti intre pagini tratezi notificarea TCN_SELCHANGE in clasa derivata din CTabCtrl.
Aici e suficient sa iei itemul curent (vezi CTabCtrl::GetCurSel) si sa arati numai pagina corespunzatoare, ascunzandu-le pe celelalte.
Ma e ceva: de obicei pagina se creaza nu atunci cand o adaugi ci atunci cand este prima data selectata. Deci, te uiti mai intai "este creata?" nu, o creezi, da, doar o faci vizibila.
Pentru mutarea paginilor iei mai intai dreptunghiul fereastra a controlului tab si calculezi zona lui de afisare (care exclude tab-urile si zona non-client) cu CTabCtrl::AdjustRect. Ai aici un exemplu:

Code: Select all

void CMyTabCtrl::AdjustPage(CDialog* pDlgPage)
{
   ASSERT(pDlgPage->GetSafeHwnd());   

   // get tab control rectangle
   CRect rcTabCtrl;
   this->GetWindowRect(rcTabCtrl);

   // get tab control display area
   CRect rcTabDisplay = rcTabCtrl;
   this->AdjustRect(FALSE, rcTabDisplay);
   this->ScreenToClient(rcTabDisplay);

   // move page window in tab control display area
   pDlgPage->MoveWindow(rcTabDisplay);
}

Ajustarea asta o faci o singura data si anume dupa ce ai creat pagina si nu de fiecare data cand se schimba selectia la tab.
Cam atat.

Cateva observatii colaterale:
  1. Nu ignora warning-urile! Vezi ca unul iti spune ca ai undeva un apel recursiv (in TabControl::OnShowWindow) care ar putea sa-ti dea stack overflow.
  2. Nu lasa memory leaks in program. In MFC, poti detecta usor sursa lor adaugand la inceputul fiecaruii CPP, urmatoarele:

    Code: Select all

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif
  3. Cand programezi in MFC, foloseste conventia de notatie din MFC. Exemple: CPage2Dialog nu dialog2, m_arrPages nu m_oPages, CTabControl nu TabControl, SetDefaultPage si nu setDefaultPage, etc. Daca vrei ca un alt programator MFC sa inteleaga mai usor ce vrei sa spui, "vorbeste" in limba MFC si lasa Java notation pentru javameni.
  4. Cand programezi in MFC, foloseste calea cea mai usoara pe care ti-o ofera MFC-ul (vezi mai jos).
Am zis astea pentru cazul in care vrei intradevar sa folosesti direct controlul tab (CTabCtrl) + dialoguri (CDialog).
Mult mai simplu si mai fara dureri de cap este sa folosesti un property sheet (CPropertySheet) + property pages (CPropertyPage).
Acestea dn urma au deja implementat in spate chestii (creare/ajustare/comutare pagini, etc) care in prima optiune trebuie sa le scrii la mana.

neagu_laurentiu
Membru++
Membru++
Posts: 919
Joined: 23 Jul 2007, 11:32

Re: Problema TabControl

Post by neagu_laurentiu » 31 Jul 2012, 17:30

Dincolo de brambureala autorului avem o mare brambureala in implementarea MFC-ului pentru tab-uri. Da-l dracului de "visual" daca nu au vrut sa incapsuleze povestea in ceva de nivel mai inalt. Ca puteau sa faca asta mult mai bine si sa pastreze parfumul de WinAPI fara sa supere nici o tabara.

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Problema TabControl

Post by Ovidiu Cucu » 31 Jul 2012, 18:48

Of, Laurentiu, iar incepem cu RAD si IDE-uri de la Borland sau pe unde-or mai fi acuma? :)
Ca sa faci un property sheet in MFC nu-i greu, trebuie doar:
  1. sa dai dracului (scuze ca raspund cu aceleasi cuvinte) "programarea" cu drag'n drop + proprietati din liste si sa intelegi macar ce-i ala un tab control.
  2. sa dai dracului folosirea directa a CTabCtrl si sa folosesti CPropertySheet + CPropertyPage.
Mai departe-i floare la ureche.
Cat despre raw-WinAPI, no problem, te apuci voiniceste de umplut structuri PROPSHEETHEADER si PROPSHEETPAGE, si sa vezi atunci... "parfum". ;)

neagu_laurentiu
Membru++
Membru++
Posts: 919
Joined: 23 Jul 2007, 11:32

Re: Problema TabControl

Post by neagu_laurentiu » 31 Jul 2012, 20:02

Ovidiu Cucu wrote:Ca sa faci un property sheet in MFC nu-i greu
Eu nu am zis ca-i greu. Da' putea fi mai usor. :)

In plus nu pe mine ma sperie povestile din MFC, lucrez demult cu ele. Da' e bine sa te mai uiti imprejur la evolutie.

carrera
Junior
Junior
Posts: 38
Joined: 23 Aug 2007, 12:06

Re: Problema TabControl

Post by carrera » 01 Aug 2012, 13:53

am rezolvat, pin' la urma am creat o clasa derivata din CPropertySheet in care am adaugat citeva obiecte CPropertyPage care reprezinta paginile.Intr-adevar e mult mai simplu.

thx Ovidiu.

Post Reply