Im Dialog Daten aus Hauptfenster ändern



  • Hi,

    ich habe mit dem Gui-Editor einen neuen Dialog erstellt. In diesem Dialog möchte ich Einstellungen am Hauptfenster vornehmen.

    Ich habe eine neue Dialog-Klasse mit dem Assistent erstellt.

    Normalerweise muss ich der Dialog-Klasse eine Referenz auf das Hauptfenster übergeben, wo ich die Daten ändern möchte.
    Der Assistent hat bereits folgenden Konstruktor für mich erstellt:

    CConfigdialog( CWnd* pParent = NULL );

    Jetzt könnte ich doch eine Membervariable erstellen z. B. m_pParent, in der ich die Referenz speichere und dann auf
    die Memers des Hauptfenster zugreifen kann:

    pParent->m_nData1 = 5;
     pParent->m_nData2 = 460;
    

    Dadurch ergeben sich zwei Probleme:

    1. Muss ich die Referenz auf meine neu erstellte Dialog-Klasse casten und wenn dann eine Referenz einer anderen Klasse
    übergeben wird kommt es zu einem Programmabsturz.

    2. Erhalte ich komischer Weiße falsche Werte

    ((CConfigdialog)pParent)->m_nData1;
    ((CConfigdialog)pParent)->m_nData2;
    

    liefert falsche Werte

    Danke und LG
    Kerberos


  • Mod

    Ich halte es für vernünftiger die relevanten Daten in den Dialog als Kopie zu übernehmen und bei IDOK wieder heraus zu kopieren.

    Ansonsten bekommst Du einfach Probleme im Dialog Design wenn zwischendrin mal UpdateData aufgerufen wurde und anschließend der User Escape drückt. Die Daten wären dann schon geändert....

    Ansonsten solltest Du Casts vermeiden. Schon ganz und gar solche Holzhammer casts!

    ((CConfigdialog)pParent)->m_nData1;
    ((CConfigdialog)pParent)->m_nData2;
    

    Wie besorgst Du dir dnen pParent? Dir ist klar, dass GetParent() ein anderer Wert sein kann, als das Fenster, dass Du dem Dialog mitgegeben hast? WS_CHILD Windows können nämlich keine Parents von Popup Windows sein!



  • Hi Martin,

    danke für Deine Antwort!

    Sorry, ist quatsch was ich da geschrieben habe (sollte lieber direkt aus dem Code kopieren), müsste wie folgt heissen:

    ((CMyFormView)pParent)->m_nData1;
    ((CMyFormView)pParent)->m_nData2;
    

    Die Referenz übergebe ich in der Aufrufenden Klasse (CMyFormView)

    CConfigdialog myDlg(this);
    

    Konstrutkor der Klasse:

    CConfigdialog( CWnd* pParent = NULL );
    

    Somit habe ich eine Referenz auf das Hauptfenster übergeben und kann dort Daten ändern.

    Ich dachte mir schon dass das nicht gerade die nobelste Art ist, vorallem mit diesen Casts.

    Ich halte es für vernünftiger die relevanten Daten in den Dialog als Kopie zu übernehmen und bei IDOK wieder heraus zu kopieren.

    Sorry, ich bin ganz neu in C++ und hab von IDOK noch nie was gehört, kannst du mir evtl. ein Beispiel geben oder kurz erklären wie das funktioniert?

    DANKE UND LG
    Kerberos


  • Mod

    1. Ändere lieber den Konstruktor und führe eine eigene Referenz ein.

    class CConfigdialog : ...
    {
    CConfigdialog(CDataClass &ref, CWnd* pParent = NULL );
    
    CDataClass &m_refData;
    };
    

    2. Besser als das direkte ändern ist das hier: Normalerweise wird einfach für jede Datenvariable eine Kopie durch den Dialog-Wizard erzeugt. Diese befüllst Dumit den Daten und, führst DoModal aus und lädst diese zurück.

    CConfigdialog dlg;
    // Copy data to change
    dlg.m_strData = m_someDatatoEdit;
    
    // Allow user to modify copy of data
    if (dlg.DoModal()==IDOK)
        // On success copy data back
        m_someDatatoEdit = dlg.m_strData;
    

    Die zweite Methode ist auch deswegen besser weil die Dialog Klasse nichts von Deiner Datenklasse/View/Dokuemnt wissen muss!



  • Hi,

    vielen Dank!! Ein sehr guter Tipp!! Habe es so realisiert, jetzt bekomme ich (wie fast immer wenn ich was neues mit der MFC probiere) einen seltsamen Fehler.

    Ich habe eine Set-Methode umd die Edit-Boxen mit Werten initialisieren zu können:

    BOOL CConfigurationDlg::SetValues(int a_iPathesPerPage, int a_iPathSpace)
    {
    	int iRet = FALSE;
    	try
    	{
    		CString strPathesPerPage;
    		CString strPathSpace;
    
    		strPathesPerPage.Format("%d", a_iPathesPerPage				 );
    		strPathSpace.Format("%d", a_iPathSpace							 );
    
    		m_txtPathesPerPage.SetWindowTextA( _T(strPathesPerPage	));
    		m_txtPathSpace.SetWindowTextA( _T(strPathSpace			));
    	}
    	catch(...)
    	{
    		iRet = TRUE;
    	}
    	return iRet;
    }
    

    Das ganze Rufe ich jetzt so auf:

    m_pConfigurationDialog = new CConfigurationDlg;
    m_pConfigurationDialog->SetValues(m_iPathesPerPage, m_iComponentSpace);
    if( m_pConfigurationDialog->DoModal() == IDOK)
    {
    	m_pConfigurationDialog->GetValues(m_iPathesPerPage, m_iComponentSpace);
    }
    delete m_pConfigurationDialog;
    

    Wenn ich das ausführe bekomme ich eine Fehlermeldung. Bei genauerem Betrachten bzw. Debuggen fällt auf das

    m_txtPathesPerPage
    m_txtPathSpace
    

    nicht zugewiesen, also NULL sind. Wie kann das sein, die werden doch im Konstruktor erzeugt?

    DANKE UND LG
    Kerberos


  • Mod

    SetValues kann nicht gehen, da Dein Controls ja nicht existieren. Die MFC arbeitet mit Kopien, der Werte!

    Erst nach em Ausführen von DoModal sind die Fenster vorhanden!



  • Ok, das wusste ich nicht!

    Wie soll ich dann die Werte in Textboxen bringen, wenn ich nicht darauf zugreifen kann bevor sie angezeigt werden?

    Danke und Lg
    Kerberos



  • Überschreibe OnInitDialog() und packe dort die Werte in die Controls.


  • Mod

    Lege eine Wert-Variable in dem Dialog an und binde diese an ein Control.

    Mach Dich mit dem Mechanismus von UpdateData/DoDataExchange vertraut.


Anmelden zum Antworten