Datenaustausch zwischen PropertyPage


  • Administrator

    Du weisst nicht wie man Zeiger verwendet? Kann das sein oder liegt das an der Uhrzeit? ^^

    Ok, mal schauen.

    Jeder Speicher besteht aus einer Anzahl an Bytes. Jedes Byte in einem Speicher hat eine Adresse. Wenn man nun ein Objekt auf einem Speicher anlegt, werden für dieses Objekt eine Anzahl an Bytes reserviert. Die Adresse zu diesen Bytes kann man in C/C++ rausfinden und mit ihnen direkt arbeiten (Ist einer der grossen Vor/Nachteile). Eine Adresse auf ein Objekt, ist immer das erste reservierte Byte. Durch das Objekt selber wird automatisch klar, wieviele weitere Bytes reserviert sind und wie man auf diese zugreifen muss.

    Die Adresse eines Objektes bekommt man mit dem UND-Operator vor dem Objekt.

    int a;  // Es werden 4 Bytes auf dem Speicher angelegt.
    int* p; // Es wird ein Zeiger (braucht auch 4 Bytes unter Win32) auf dem Speicher angelegt.
    p = &a; // In den Zeiger wird die Adresse des ersten Bytes des Objekts a gespeichert.
    

    Bei einem Objekt geht das ganz genau gleich.

    CObject Object;
    CObject* pObject = &Object;
    

    Also folgendes schlage ich dir nun vor.

    // Allerhand includes und zeugs
    
    // Du nimmst die Struktur aus der Klasse raus.
    struct SOptions
    {
        CString strPfad;
        CString strNameExe;
        CString strKommando1;
        CString strKommando2;
        CString strAnzahl;
        bool bArtLogatome;
        int iZeit;
        CString strWavOrdner;
        CString strMaxAnzahl;
        CString strAnzahlWav;
        CString strNameLogatomListe;
        CString strPathLogatomListe;
        bool bGleicheListe;
        CString strAnzahlPersonen;
        bool bVorstellungSynthese;
        CString strUserPath;
        bool bLernmodus;
        bool bLernphase;
        int iAnzahlLernphase;
    };
    
    class CPropOptionen : public CPropertySheet
    {
        // ...
    private:
        // Du deklarierst einen Zeiger auf die Struktur in deiner Sheet Klasse.
        SOptions* m_pOptions;
    
        // ...
    }
    
    // PropOptionen.cpp
    
    // Konstruktor 1
    CPropOptionen::CPropOptionen(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
        : m_pOptions(NULL) // Initialisierung mit NULL
    {
        m_pOptions = new SOptions; // Du legst Speicher auf dem Heap an und speicherst die Adresse.
    
        sprach.SetOptions(m_pOptions); // Du übergibst dem Objekt sprach per Setter den Zeiger. Siehe dazu etwas weiter unten. Geduld!
    }
    
    // Konstruktor 2
    CPropOptionen::CPropOptionen(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
        : m_pOptions(NULL) // Initialisierung mit NULL
    {
        m_pOptions = new SOptions; // Du legst Speicher auf dem Heap an und speicherst die Adresse.
    
        sprach.SetOptions(m_pOptions); // Du übergibst dem Objekt sprach per Setter den Zeiger. Siehe dazu etwas weiter unten. Geduld!
    }
    
    // Destruktor
    CPropOptionen::~CPropOptionen()
    {
        delete m_pOptions; // Du gibst den Heap Speicher frei.
    }
    

    Normalerweise befindet sich der Speicher auf dem Stack. Dieser wird von alleine aufgeräumt, sobald ein Block beendet wurde.

    {
        int* p = NULL;
    
        {
            int a; // 4 Bytes werden auf dem Stack angelegt.
            p = new int; // 4 Bytes werden auf dem Heap angelegt.
        }
    
        // a ist nicht mehr vorhanden! Speicher wurde aufgeräumt.
        // der Speicher, auf welcher p zeigt ist immer noch gültig.
        // Um den Speicher freizugeben, müssen wir delete aufrufen.
        delete p;
    
        // Heap speicher muss immer manuell freigegeben werden.
        // Das geschiet nicht automatisch!
    }
    

    Nun hast du einen Zeiger auf ein struct SOptionen in deiner CPropertySheet Klasse, welches beim erstellen des Objekts angelegt wird und beim zerstören des Objekts wieder freigegeben wird.

    Du musst nun in jeder PropertyPage Klasse diese Adresse auf dieses Struct übergeben. Das kannst du im Konstruktor machen oder per Setter.

    Ich demonstrier es jetzt mal mit dem Setter bei einer PropertyPage.

    // Allerhand includes und anderes.
    
    // anstatt class CPropOptionen; kommt nun folgendes hin:
    struct SOptions;
    
    class COptSprachmaterial : public CPropertyPage
    {
        // ...
    private:
        SOptions* m_pOptions;
        // ...
    public:
        void SetOptions(SOptions* pOptions) { m_pOptions = pOptions; };
    }
    
    // In der dazugehörigen cpp
    COptSprachmaterial(SOptions* pOptions)
        : m_pOptions(NULL) // Zeiger mit NULL initialisieren, damit er nicht ins Nirvana zeigt.
    {
    }
    
    // Irgendwo in einer Funktion wo du drauf zugreifen willst
    void COptSprachmaterial::Funktion()
    {
        // Prüfen ob m_pOptions ungleich NULL ist. Wenn der Zeiger NULL wäre
        // und einfach drauf zugegriffen würde, dann gäbe es eine
        // Speicherzugriffsverletzung -> Absturz
        if(m_pOptions)
        { m_pOptions->strPfad = _T("Bla bla bla"); }
    }
    

    So nun sollte auch alles mit dem Setter im Konstruktor des CPropOptionen-Objekt klar sein. Gibt es noch was zu sagen?

    Aja ... im Objekt selber, kannst du auf dich selbst mit this zugreifen. this ist immer der Zeiger auf das aktuelle Objekt der Klasse.

    Ansonsten, tjo noch Fragen? *betet, dass es nicht so ist* 😃

    Ich würde noch vorschlagen ein Tutorial zu Zeigern in C++ zu machen. Kenne nur leider keins im Inet.

    Grüssli



  • Ich hatte gestern Abend (Heute früh) deinen Eintrag nicht mehr gesehen. Mußte dann auch mal endlich schlafen. So nun habe ich das gerade gemacht und so funktioniert es wunderbar. Ich muß zugeben, daß ich mit Zeigern noch nicht so viel zu tun hatte und das ganze aber jetzt verstanden habe.

    Danke, Danke das hat mir sehr geholfen!!!!!!!!!!!!!!!!!!!!!!!!!

    Beste Grüße



  • Jetzt habe ich leider doch noch ein Problem!!
    Ich habe das Ganze ja nun mit dieser Struktur gemacht und beim OnSetActive und OnKillActive werden die Daten der Seiten untereinander ausgetauscht. Das funktioniert auch, aber wenn ich jetzt nur die erste Seite öffne und dort etwas ändere wird ja die Funktion OnKillActive nicht aufgerufen und somit findet auch ein Austausch meiner Seitendaten mit der Datenstruktur nicht statt.
    Ich muß dazu sagen, daß ich den übernehmen Button ausblende und das speichern über den Ok Button realisiere, also über die Nachricht, daß der button gedrückt wurde, wird eine Funktion aufgerufen, die das Speichern der Daten übernimmt.

    Wie kann ich das lösen?

    Edit: Jetzt habe ich festgestellt, daß OnKillActive doch aufgerufen wird. Nun dann werde ich das mal darüber probieren!!


Anmelden zum Antworten