tutorials.de Buch-Aktion 05/2012
ERLEDIGT
JA
ANTWORTEN
14
ZUGRIFFE
6912
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    langer1801 langer1801 ist offline Mitglied Platin
    Registriert seit
    Jun 2005
    Ort
    Bad Arolsen (Hessen)
    Beiträge
    556
    Hallo, ich habe ein Projekt im Explorer-Stil, links von CTreeView und rechts eine von CFormView abgeleitete Klasse. In dieser FormView habe ich ein CTabCtrl. Das Einfügen von Seiten mittels InsertItem ist auch kein Problem. Nur - danach habe ich erstmal leere Seiten zur Verfügung. Wie bringe ich meine Steuerelemente auf die Seiten? Kann man einfach Dialoge vom Typ CPropertyPage an die Seiten übergeben? Und wenn ja, wie?

    Danke

    langer
     

  2. #2
    MCoder MCoder ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jul 2005
    Ort
    München
    Beiträge
    2.448
    CPropertyPage ist für die Verwendung in CPropertySheet gedacht. Für CTabControl reicht eine normale CDialog basierte Klasse. Das Dialog-Template sollte keinen Titel und keinen Rand haben und den Style WS_CHILD (untergeordnet) besitzen.

    Der Code zum Einbinden des Dialogs schaut so aus:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    
    // m_dlgTab ist ein Objekt der Klasse CMyDialog (als Beispiel)
    // m_TabCtrl ist das CTabCtrl-Objekt
     
    // Dialog erzeugen
    m_dlgTab.Create(CMyDialog::IDD, m_TabCtrl);
     
    CString strTitle = _T("Tab Überschrift");   // Titel des Dialogs
    int     iIndex   = 0                        // Tab-Index
     
    // Dialog  als Tab hinzufügen
    TCITEM item;
    item.mask    = TCIF_TEXT | TCIF_PARAM;
    item.lParam  = (LPARAM)&m_dlgTab;
    item.pszText = (LPTSTR)(LPCTSTR)strText;
    m_TabCtrl.InsertItem(iIndex, &item);
     
    // Dialog positionieren
    CRect rcItem;
    m_TabCtrl.GetItemRect(0, &rcItem);
     
    m_dlgTab.SetWindowPos( NULL,
                           rcItem.left,
                           rcItem.bottom + 1,
                           0,
                           0,
                           SWP_NOSIZE | SWP_NOZORDER );
     
    // Anzeigen (nur den ersten Tab)
    m_dlgTab.ShowWindow(iIndex ? SW_HIDE : SW_SHOW);

    Bei Verwendung von CTabCtrl musst du dich allerdings auch noch selber um die Umschaltung der Tabs kümmern
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    
    // benötigte Member-Variable: m_uiSelectedTab (mit 0 vorbelegen)
     
    // Message-Handler für TCN_SELCHANG
    void CMyFormView::OnSelchangeTabcontrol(NMHDR* pNMHDR, LRESULT* pResult) 
    {
        TCITEM  item;
        CWnd*   pWnd;
        int     iNewTab = m_TabCtrl.GetCurSel();
     
        item.mask = TCIF_PARAM;
     
        // aktuellen Tab ausblenden
        m_TabCtrl.GetItem(m_uiSelectedTab, &item);
        if( item.lParam )
        {
            pWnd = reinterpret_cast<CWnd*> (item.lParam);
            pWnd->ShowWindow(SW_HIDE);
        }
     
        // neuen Tab anzeigen
        m_TabCtrl.GetItem(iNewTab, &item);
        if(item.lParam)
        {
            pWnd = reinterpret_cast<CWnd*> (item.lParam);
            pWnd->ShowWindow(SW_SHOW);
        }
     
        *pResult = 0;
    }
     
    // Message-Handler für TCN_SELCHANGING
    void CMyFormView::OnSelchangingTabcontrol(NMHDR* pNMHDR, LRESULT* pResult) 
    {
        m_uiSelectedTab = m_TabCtrl.GetCurSel();
        *pResult = 0;
    }
     
    "The three chief virtues of a programmer are: Laziness, Impatience and Hubris."
    --- Larry Wall

  3. #3
    langer1801 langer1801 ist offline Mitglied Platin
    Registriert seit
    Jun 2005
    Ort
    Bad Arolsen (Hessen)
    Beiträge
    556
    Danke für die Antwort. Habe den Code mal ausprobiert in meinem Projekt. Das Einfügen des Items klappt problemlos. Nur wird der Dialog nicht angezeigt.
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    void CAbrVersuchView::OnInitialUpdate()
    {
        TCITEM item;
        int iIndex=0;
        CString strTitel = _T("Patientendaten");
        CVersuchDlg m_versuch;
        m_versuch.Create(CVersuchDlg::IDD,&ctr_Tab1);
        CFormView::OnInitialUpdate();
        GetParentFrame()->RecalcLayout();
        ResizeParentToFit();
        item.mask=TCIF_TEXT|TCIF_PARAM;
        item.lParam=(LPARAM)&m_versuch;
        item.pszText=(LPTSTR)(LPCTSTR)strTitel;
        ctr_Tab1.InsertItem(iIndex,&item);
        CRect rcItem;
        ctr_Tab1.GetItemRect(0,&rcItem);
        ctr_Tab1.SetWindowPos(NULL,rcItem.left,rcItem.bottom+1,0,0,SWP_NOSIZE|SWP_NOZORDER);
        ctr_Tab1.ShowWindow(/*iIndex?SW_HIDE:*/SW_SHOW);
    //  ctr_Tab1.InsertItem(2,"Leistungen SGB V");
    //  ctr_Tab1.InsertItem(3,"Einsätze SGB V");
    //  ctr_Tab1.InsertItem(4,"Leistungen SGB XI");
    //  ctr_Tab1.InsertItem(5,"Einsätze SGB XI");
    }
    Das TabCtr habe ich in der .h deklariert.
    Code :
    1
    2
    
    public:
        CTabCtrl ctr_Tab1;
    Ich habe alles, was nicht unbedingt nötig ist, auskommentiert. Aber ich kann machen, was ich will, ich kriege nur das Item angezeigt, aber nie den dazugehörigen Dialog.
    Wo liegt der Fehler?

    langer
     

  4. #4
    MCoder MCoder ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jul 2005
    Ort
    München
    Beiträge
    2.448
    Den Dialog musst du ebenfalls als Member in der .h deklarieren. Ansonsten ist er am Ende von OnInitialUpdate() wieder weg.
     
    "The three chief virtues of a programmer are: Laziness, Impatience and Hubris."
    --- Larry Wall

  5. #5
    langer1801 langer1801 ist offline Mitglied Platin
    Registriert seit
    Jun 2005
    Ort
    Bad Arolsen (Hessen)
    Beiträge
    556
    Wow, jetzt klappts. Hätte ich auch selbst drauf kommen können.

    Danke

    langer
     

  6. #6
    Elayas Elayas ist offline Grünschnabel
    Registriert seit
    Jul 2004
    Beiträge
    1
    Hi, ich habe Deinen Lösungsvorschlag wie folgt umgesetzt:
    Code cpp:
    1
    2
    3
    4
    5
    
    // Header-Datei des Hauptdialogs
    ...
    CDlg_Tab_Suche mDlg_Tab;      // Objekt auf den ersten Tab-Dialog
    CTabCtrl mCtrl_Tab;           // Objekt auf CTabCtrl, ist Control-Var vom TabControl
    unsigned int mUI_SelectedTab;

    Code cpp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    
    // CPP-Datei des Hauptdialogs
     
    BOOL CHauptDlg::OnInitDialog()
    {
        CDialog::OnInitDialog();
        ...
     
        // Initialisierung des TabControl
        // Dialog erzeugen
        mDlg_Tab.Create(CDlg_Tab_Suche::IDD, &this->mCtrl_Tab);
     
        CString strTitle = _T("Tab Überschrift");   // Titel des Dialogs
        int     iIndex   = 0;                        // Tab-Index
     
        // Dialog  als Tab hinzufügen
        CString strText = "Hallo Welt!";
        TCITEM item;
        item.mask    = TCIF_TEXT | TCIF_PARAM;
        item.lParam  = (LPARAM)&mDlg_Tab;
        item.pszText = (LPTSTR)(LPCTSTR)strText;
        mCtrl_Tab.InsertItem(iIndex, &item);
     
        // Dialog positionieren
        CRect rcItem;
        mCtrl_Tab.GetItemRect(0, &rcItem);
     
        mDlg_Tab.SetWindowPos(NULL, rcItem.left, rcItem.bottom + 1, 0, 0, SWP_NOSIZE | SWP_NOZORDER );
     
        mDlg_Tab.ShowWindow(iIndex ? SW_HIDE : SW_SHOW);
     
        return TRUE;
    }

    Jedoch erscheint bei mir das TabControl nicht. Woran kann das liegen?

    Danke!

    Gruß,

    Elayas
     

  7. #7
    MCoder MCoder ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jul 2005
    Ort
    München
    Beiträge
    2.448
    Wo erzeugst du das TabControl ?
     
    "The three chief virtues of a programmer are: Laziness, Impatience and Hubris."
    --- Larry Wall

  8. #8
    chefsalat- chefsalat- ist offline Mitglied Bronze
    Registriert seit
    Mar 2007
    Beiträge
    40
    Hallo,
    ich versuche mich momentan auch an einem CTabCtrl.
    Folgendes habe ich ausprobiert:
    In der .h meines Dialoges, in dem das CTabCtrl erscheinen soll, habe ich die untergeordneten Dialoge ohne Rand erzeugt.
    Code cpp:
    1
    2
    
    CmeinTab1Dlg mDlg_Tab1;
    CmeinTab2Dlg mDlg_Tab2;

    In der .cpp (OnInitDialog) des Dialoges, sieht es so aus
    Code cpp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    CTabCtrl* pTabCtrl = (CTabCtrl*)GetDlgItem(IDC_TAB_USERVERWALTUNG); //Zugriff auf das CTabCtrl
     
    mDlg_Tab1.Create(IDD_DLG_MEIN_TAB1, pTabCtrl->GetParent());
    mDlg_Tab2.Create(IDD_DLG_MEIN_TAB2, pTabCtrl->GetParent());
     
    CString sUeberschrift = "Passwort ändern";
    TCITEM item1;
    item1.mask    = TCIF_TEXT | TCIF_PARAM;
    item1.lParam  = (LPARAM)&mDlg_Tab1;
    item1.pszText = (LPTSTR)(LPCTSTR)sUeberschrift;
    pTabCtrl->InsertItem(0, &item1);
     
    sUeberschrift = "Neuen User anlegen";
    TCITEM item2;
    item2.mask    = TCIF_TEXT | TCIF_PARAM;
    item2.lParam  = (LPARAM)&mDlg_Tab2;
    item2.pszText = (LPTSTR)(LPCTSTR)sUeberschrift;
    pTabCtrl->InsertItem(1, &item2);
     
    pTabCtrl->ShowWindow(SW_SHOW);

    Normalerweise müsste das doch dann so funktionieren, dass wenigstens der untergeordnete Dialog für das erste Tab angezeigt wird, oder?

    Beim Debuggen läuft es ohne Probleme durch, aber der untergeordnete Dialog wird im CTabCtrl nicht angezeigt.

    Kann mir jemand weiterhelfen?

    Gruß chefsalat-
     

  9. #9
    chefsalat- chefsalat- ist offline Mitglied Bronze
    Registriert seit
    Mar 2007
    Beiträge
    40
    Ok, ich hab selber nochmal n bischen dran rumgespielt.
    Warum funktioniert es immer erst dann, wenn man sich schon Mühe gemacht hat, sein Problem zu posten?

    So sieht meine Lösung aus:
    .h
    Code cpp:
    1
    2
    
    CmeinTab1Dlg mDlg_Tab1;
    CmeinTab2Dlg mDlg_Tab2;

    .cpp
    Code cpp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    CTabCtrl* pTabCtrl = (CTabCtrl*)GetDlgItem(IDC_TAB_USERVERWALTUNG);
     
    mDlg_Tab1.Create(IDD_DLG_MEIN_TAB1, pTabCtrl);
    mDlg_Tab2.Create(IDD_DLG_MEIN_TAB2, pTabCtrl);
     
    CString sUeberschrift = "Passwort ändern";
    TCITEM item1;
    item1.mask    = TCIF_TEXT | TCIF_PARAM;
    item1.lParam  = (LPARAM)&mDlg_Tab1;
    item1.pszText = (LPTSTR)(LPCTSTR)sUeberschrift;
    pTabCtrl->InsertItem(0, &item1);
     
    sUeberschrift = "Neuen User anlegen";
    TCITEM item2;
    item2.mask    = TCIF_TEXT | TCIF_PARAM;
    item2.lParam  = (LPARAM)&mDlg_Tab2;
    item2.pszText = (LPTSTR)(LPCTSTR)sUeberschrift;
    pTabCtrl->InsertItem(1, &item2);
     
    // Dialog positionieren
    CRect rcItem;   
    pTabCtrl->GetItemRect(0, &rcItem);
    mDlg_Tab1.SetWindowPos(NULL, rcItem.left, rcItem.bottom + 1, 0, 0, SWP_NOSIZE | SWP_NOZORDER );
     
    int iCount = pTabCtrl->GetCurSel();
    pTabCtrl->ShowWindow(iCount ? SW_HIDE : SW_SHOW);
    mDlg_Tab1.ShowWindow(SW_SHOW);

    Ist schon praktisch, wenn man den untergeordneten Dialog auch noch anzeigt und an die richtige Position setzt...

    Gruß chefsalat-
     

  10. #10
    bw1faeh0 bw1faeh0 ist offline Grünschnabel
    Registriert seit
    Oct 2007
    Beiträge
    2
    Hallo!

    auch wenn der Thread schon etwas älter ist, würde ich mich an dieser Stelle gerne einmal einklinken.
    Ich möchte in meiner Anwendung auch gerne die erwähnten Tabs nutzen. Dazu habe ich den Code aus chefsalat's letztem Posting wie folgt übernommen:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    
    BOOL CSourceDlg::OnInitDialog()
    {
        /*
        ...
        */
     
        // TODO: Hier zusätzliche Initialisierung einfügen
     
        CTabCtrl* pTabCtrl = (CTabCtrl*)GetDlgItem(IDC_TAB);    
     
     
        CString sUeberschrift = "Register 1";
        TCITEM pTabCtrlItem_01;
        pTabCtrlItem_01.mask    = TCIF_TEXT | TCIF_PARAM;
        pTabCtrlItem_01.lParam  = (LPARAM)&m_register_01;
        pTabCtrlItem_01.pszText = (LPTSTR)(LPCTSTR)sUeberschrift;
        pTabCtrl->InsertItem(0, &pTabCtrlItem_01);
     
        sUeberschrift = "Register 2";
        TCITEM pTabCtrlItem_02;
        pTabCtrlItem_02.mask    = TCIF_TEXT | TCIF_PARAM;
        pTabCtrlItem_02.lParam  = (LPARAM)&m_register_02;
        pTabCtrlItem_02.pszText = (LPTSTR)(LPCTSTR)sUeberschrift;
        pTabCtrl->InsertItem(1, &pTabCtrlItem_02);
     
        // Dialog positionieren
        CRect rcItem;
        pTabCtrl->GetItemRect(0, &rcItem);
        m_register_01.SetWindowPos(NULL, rcItem.left, rcItem.bottom + 1, 0, 0, SWP_NOSIZE | SWP_NOZORDER );
     
        pTabCtrl->SetCurSel(0);
        int iCount = mctl_Tab.GetCurSel();
        mctl_Tab.ShowWindow(iCount ? SW_HIDE : SW_SHOW);
        m_register_01.ShowWindow(SW_SHOW); 
    }

    m_register_01 und m_register_02 wurden wie folgt definiert:

    Code :
    1
    2
    
        CRegister_01 m_register_01;
        CRegister_02 m_register_02;

    Das Problem ist nun, dass das Programm beim Ausführen der Zeile
    Code :
    1
    
        pTabCtrl->GetItemRect(0, &rcItem);
    gnadenlos abstürtzt.

    Hat jemand spontan eine Idee, woran das liegen könnte?

    mfg

    Christian Flämig
     

  11. #11
    bw1faeh0 bw1faeh0 ist offline Grünschnabel
    Registriert seit
    Oct 2007
    Beiträge
    2
    Ok, sorry. Das Problem konnte an einer anderen Stelle gelöst werden...

    man sollte auch ein m_register_01.Create() durchführen....

    mfg

    Christian Flämig
     

  12. #12
    chefsalat- chefsalat- ist offline Mitglied Bronze
    Registriert seit
    Mar 2007
    Beiträge
    40
    Ist meistens ganz praktisch, ja

    Falls noch jemand diesen Thread benötigt, hier ist noch der Teil, zum Umschalten der Tabs (es gibt sicher auch andere Möglichkeiten):

    Code cpp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    
    void OnSelchangeTabParameter(NMHDR* pNMHDR, LRESULT* pResult) {
        CTabCtrl* pTabCtrl = (CTabCtrl*)GetDlgItem(IDC_TAB_PARAMETER);
        int iCount = pTabCtrl->GetCurSel();
     
        //Alle Tabs verstecken
        mDlg_Tab1.ShowWindow(SW_HIDE);
        mDlg_Tab2.ShowWindow(SW_HIDE);
        mDlg_Tab3.ShowWindow(SW_HIDE);
        mDlg_Tab4.ShowWindow(SW_HIDE);
        
        //Nur das gewünschte Tab initialisieren und anzeigen.
        switch(iCount) {
            case 0:
                mDlg_Tab1.init();
                mDlg_Tab1.ShowWindow(SW_SHOW);
                break;
            case 1:
                mDlg_Tab2.init();
                mDlg_Tab2.ShowWindow(SW_SHOW);
                break;
            case 2:
                mDlg_Tab3.init();
                mDlg_Tab3.ShowWindow(SW_SHOW);
                break;
            case 3:
                mDlg_Tab4.init();
                mDlg_Tab4.ShowWindow(SW_SHOW);
                break;
            default:
                break;
        }
     
        *pResult = 0;
    }

    Gruß chefsalat-
     

  13. #13
    sun-fire sun-fire ist offline Rookie
    Registriert seit
    Dec 2008
    Ort
    Gilching (Bayern)
    Beiträge
    9
    Hallo Leute,

    dieser Thread ist zwar schon mega-alt, das Thema dafür umso aktueller...
    Ich habe versucht, die Lösung von MCoder umzusetzen. Dabei tauchen leider ein paar Schwierigkeiten auf:

    Wenn ich das Erzeugen des Dialoges so schreibe wie MCoder
    Code :
    1
    
    m_TabDlg1.Create(CTabDlg1::IDD, m_FormTab);
    dann gibt mir der Compiler folgenden Fehler:
    error C2664: 'BOOL CDialog::Create(LPCTSTR,CWnd *)': Konvertierung des Parameters 1 von '' in 'LPCTSTR' nicht möglich
    1> Die Konvertierung eines ganzzahligen Typs in einen Zeigertyp erfordert ein reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat
    Ich verstehe an diesem Fehler eins nicht: warum nimmt er plötzlich eine andere Implementierung von CDialog::Create, obwohl der zweite Parameter in beiden Formen der Funktion gleich ist?

    Schreibe ich die gleiche Zeile so:
    Code :
    1
    
    m_TabDlg1.Create(CTabDlg1::IDD, &m_FormTab);
    gibt es zwar keinen Compilerfehler, aber später beim Umschalten der Tabs gibt es eine Assertion, weil hier:
    Code :
    1
    
    pWnd = reinterpret_cast<CWnd*> (item.lParam);
    zwar ein CWnd-Pointer zurückkommt, bei dem m_hWnd aber 0 ist.
    Das wiederum führt dazu, dass in der nächsten Zeile
    Code :
    1
    
    pWnd->ShowWindow(SW_HIDE);
    die Funktion ShowWindow eine Assertion schmeißt.

    Ich hoffe, das war jetzt verständlich und jemand kann mit helfen. Wie gesagt: Grundlage ist der Code von MCoder am Anfang des Threads.

    Viele Grüße mit der Hoffnung auf Hilfe
    Tanja
     

  14. #14
    MCoder MCoder ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jul 2005
    Ort
    München
    Beiträge
    2.448
    Hallo Tanja,

    mit einem aktuellen Visual Studio gibt's da wohl eine Änderung hinsichtlich des zweiten Parameters.
    So sollte es funktionieren:
    Code cpp:
    1
    
    m_TabDlg1.Create(CTabDlg1::IDD, CWnd::FromHandle(m_FormTab.m_hWnd));
    Gruß
    MCoder
     
    "The three chief virtues of a programmer are: Laziness, Impatience and Hubris."
    --- Larry Wall

  15. #15
    sun-fire sun-fire ist offline Rookie
    Registriert seit
    Dec 2008
    Ort
    Gilching (Bayern)
    Beiträge
    9
    Hallo MCoder,

    vielen Dank für Deine Antwort, das hat geholfen. Jetzt muss ich mich nur noch ein wenig mit der Positionierung herumschlagen...

    Viele Grüße
    Tanja
     

Ähnliche Themen

  1. Dialoge in CTabCtrl in CFormView
    Von sun-fire im Forum VisualStudio & MFC
    Antworten: 0
    Letzter Beitrag: 02.12.08, 09:43
  2. CTabCtrl und PropertySheet
    Von Hulewulle im Forum C/C++
    Antworten: 0
    Letzter Beitrag: 07.11.07, 15:06
  3. CView an CTabCtrl
    Von chuqa im Forum VisualStudio & MFC
    Antworten: 4
    Letzter Beitrag: 28.07.07, 20:43
  4. CTabCtrl & msflexGrid mit MFC
    Von Drei im Forum VisualStudio & MFC
    Antworten: 9
    Letzter Beitrag: 11.01.06, 21:41
  5. CTabCtrl
    Von Indian im Forum C/C++
    Antworten: 1
    Letzter Beitrag: 22.01.05, 08:43