Datenaustausch zwischen PropertyPage
-
Jetzt versuche ich es bei euch noch mal mit Code:
Ich sehe da einfach den Fehler nicht!!!!!!!!!!!!!!!!!!!!!!!Also die PropertySheet Klasse
#pragma once #include "AppSettings.h" #include "afxwin.h" #include "afxcmn.h" #include "OptSprachmaterial.h" #include "OptTestablauf.h" #include "OptLogatome.h" // CPropOptionen class CPropOptionen : public CPropertySheet { DECLARE_DYNAMIC(CPropOptionen) public: CPropOptionen(UINT nIDCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0); CPropOptionen(LPCTSTR pszCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0); virtual ~CPropOptionen(); protected: DECLARE_MESSAGE_MAP() public: virtual BOOL OnInitDialog(); COptTestablauf prog; //das sind die PropertyPages!!! COptSprachmaterial sprach; COptLogatome logatom; AppSettings set; CHilfsfunktionen pfadHolen; CString pfad; afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); struct opt { 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; }option; };Und nun eine der Pages:
#pragma once #include "AppSettings.h" #include "WavListe.h" #include "afxwin.h" #include "afxcmn.h" #include "Optionen.h" //Der Header der PropertySheet // COptSprachmaterial-Dialogfeld class COptSprachmaterial : public CPropertyPage { DECLARE_DYNAMIC(COptSprachmaterial) public: COptSprachmaterial(); virtual ~COptSprachmaterial(); // Dialogfelddaten enum { IDD = IDD_SPRACHMATERIAL }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-Unterstützung WavListe wavlist; DECLARE_MESSAGE_MAP() public: CPropOptionen* optionen; // der Zeiger für die Page public: virtual BOOL OnInitDialog(); virtual BOOL OnSetActive(); virtual BOOL OnKillActive(); BOOL opt_bArtLogatome; CString opt_strNameLogatomListe; CString opt_strAnzahlLogatomeListe; CString opt_strWavOrdner; CString opt_strAnzahlWav; CHilfsfunktionen pfadHolen; CString pfad; AppSettings set; CString opt_strLogatomDatei; afx_msg void OnBnClickedListeLaden(); afx_msg void OnBnClickedWavliste(); afx_msg void OnBnClickedArtlogatome(); afx_msg void OnBnClickedWavlogatome(); afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); afx_msg void OnBnClickedExe(); CString opt_strPfad; CString opt_strKommando1; CString opt_strKommando2; CString opt_strNameExe; };Und da kommt halt dieser Syntaxfehler. Aber ich muß doch das irgendwie incluieren!!!! Und da ist wahrscheinlich der Fehler!!!
Aber wie mache ich das den jetzt.BITTE BITTE HILFE!!!!!!!!!!!!!!!!!!!!!
-
Das es mit der Incluierung zu tun hat habe ich mir halt auch schon gedacht. Aber irgendwie mache ich da was falsch. Aber damit ich die Pages in die PropertySheet-Klasse bekomme, muß ich die doch da auch incluieren??! Damit ich sie dann mit AddPage(..) im Konstruktor von PropertySheet anzeigen lassen kann!!! Und da ist halt irgendwo der Wurm drin. Aber ich sehe das einfach nicht!!
-
Danke, jetzt ist alles klar ^^
Du inkludierst gegenseitig.
// A.h #include "B.h" // B.h #include "A.h"Ergibt diesen Fehler.
Am besten machst du einen Vorwärtsdeklaration.
In "OptSprachmaterial.h" und all den anderen Pages machst du folgendes oben unterhalb der Includes rein:
class CPropOptionen;Mit dieser Vorwärtsdeklaration kannst du Zeiger definieren. Aber keine Methoden aufrufen oder Objekte davon erzeugen!
In der "OptSprachmaterial.cpp" und all den anderen Pages macht du dann das#include "Optionen.h"In der *.cpp kannst du nun Methoden dieses Zeigers aufrufen.
Dann sollte es funktionieren :p
Grüssli
PS: Der Code hat geholfen ... siehst du

-
Danke erstmal für die Hilfe. werde ich gleich mal probieren!!
-
Ich kann jetzt zwar ohne Fehler den Zeiger definieren, aber beim ausführen sind die Daten nicht mehr aktuell. Da muß noch irgendetwas falsch sein!

-
Dumme Frage, aber übergibst du dem Zeiger auch einen Wert? Bzw. halt die richtige Adresse? Man muss dem Zeiger nämlich noch sagen, wohin der zeigen soll. Ansonsten weiss ich eigentlich nicht, was du meinst, mit nicht aktuell.
Grüssli
-
Im OnInit des PropertySheet mache z.B. folgendes
option.strPfad = set.in_strPfad;damit wird ein String aus meiner XML Datei in die Struktur geladen.
mein Zeiger lautet:
CPropOptionen* sprachmaterial;und dann mache ich bei OnSetActive oder im OnInit der Page:
opt_strPfad = sprachmaterial->option.strPfad;ja und da ist dann halt nichts mehr drin!
Da sehe ich bestimmt irgendwas grundsetzliches nicht?!
-
Tjo der Zeiger braucht doch noch eine Initialisierung. Du musst dem sagen wohin er zeigt, sonst zeigt er ins Nirvana.
int* p; // Der Zeiger weiss nicht wohin, bzw. auf welches Objekt er zeigen muss. int a = 5; // Ein Int-Objekt mit dem Wert 5; p = &a; // p zeigt nun auf das Objekt, a mit dem Wert 5Ziemlich logisch nicht?
Daher habe ich so langsam das Gefühl, dass wir uns irgendwie nebendurch reden ^^
Grüssli
-
Ich hoffe ich bekomme das jetzt hin. Da habe ich wohl was mit Zeigern nicht ganz verstanden.
Danke für die Geduld von dir.Beste Grüße
-
Da muß ich dann doch nochmal fragen!
Ich habe hier doch jetzt einen Zeiger auf die Klasse:CPropOptionen* sprachmaterial;mit was soll ich den diese nun zuweisen. Das ist doch keine Variable im Sinne von int oder CString oder so??
Also das Beispiel von dir kann ich doch garnicht so anwenden.sprchmaterial ist nun ein Zeiger auf die Klasse. Nun habe ich in der Klasse eine Struktur mit Variablen. Diese Variablen werden in der SELBEN Klasse Daten zugewiesen:
option.strPfad = "BlahBlah";Ja und jetzt will ich über den Zeiger auf die Klasse in einer ANDEREN Klasse auf diese Daten zugreifen:
CString str = sprachmaterial->option.strPfad;Wo ist da jetzt der fehler?? Ich habe auch schon etliche Bücher durchgewälst und da kommt das so einfach nicht vor!!!
Normalerweise mache ich das ja immer so:
CPropOptionen sprachmaterial; //im Header der anderen Klasse definiert CString str = sprachmaterial.option.strPfad;Aber das geht hier ja nicht so.
Hast du das Problem erkannt??
-
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!!