Radiobuttons (de)aktivieren
-
Hallo!
Ich würde gerne zur Laufzeit einige Radiobuttons die der selben Gruppe zugehörig sind deaktivieren bzw. aktivieren.Dies habe ich versucht durch folgenden Code zu realisieren:
void Spielart::SetEnabled (int Spielart,bool Enabled) { CWnd* ctlSpielart; switch(Spielart){ //Anhand des Indexes das gewünschte Optionsfeld ermitteln case 0: ctlSpielart = GetDlgItem(IDC_NORMAL); break; case 1: ctlSpielart = GetDlgItem(IDC_HOCHZEIT); break; case 2: ctlSpielart = GetDlgItem(IDC_KREUZDAMENSOLO); break; case 3: ctlSpielart = GetDlgItem(IDC_KAROSOLO); break; case 4: ctlSpielart = GetDlgItem(IDC_HERZSOLO); break; case 5: ctlSpielart = GetDlgItem(IDC_PIKSOLO); break; case 6: ctlSpielart = GetDlgItem(IDC_KREUZSOLO); break; case 7: ctlSpielart = GetDlgItem(IDC_BUBENSOLO); break; case 8: ctlSpielart = GetDlgItem(IDC_DAMENSOLO); break; case 9: ctlSpielart = GetDlgItem(IDC_FLEISCHLOS); break; default: ctlSpielart = NULL; } if (Enabled) ctlSpielart->EnableWindow (TRUE); else ctlSpielart->EnableWindow (FALSE); delete ctlSpielart; }
Aber bei jeder Zuweisung der Variable "ctlSpielart" kommt es während der Laufzeit zu einem Fehler: "Debug Assertion failed".
Auch ist mir aufgefallen, dass wenn ich versuche den Radiobutton direkt über...
GetDlgItem(IDC_NORMAL)->EnableWindow (FALSE);
...anzusprechen, es zu genau dem selben Fehler kommt. Auch wenn ich für das erste Element der "Radiobuttongruppe" eine ControlVariable anlege, und die Eigenschaft wie folgt aufrufe:
m_ctlSpielart.EnableWindow(FALSE);
bekomme ich diesen Fehler.
Weiß jemand wie man Radiobuttons anders kontrollieren und programmieren kann?
Danke im Voraus,
Flux
-
Hi!
Also erstmal: Du legst die CWnd*-variable auf dem Stack an, d.h. du darfst nicht delete aufrufen! Vielleicht ist das ja schon die Fehlerursache.
Ausserdem: den default-Zweig solltest du per return beenden, sonst wendest du im weiteren Verlauf auf den NULL-pointer eine Funktion an, was ebenfalls zum Absturz führt.
Was auch sein kann, dass du diese Funktion zu einem Zeitpunkt aufrufst, wo der Dialog noch nicht bzw. nicht mehr existiert. Du darfst GetDlgItem erst aufrufen, nachdem dein Dialog erzeugt wurde (i.d.R. nach OnInitDialog)
Schreib doch mal, in welchem Zusammenhang du diese Funktion aufrufst.Gruß,
Ravel[ Dieser Beitrag wurde am 13.04.2003 um 21:16 Uhr von Ravel2000 editiert. ]
-
Ok, also die Sache mit dem Return ist klar, hab ich auch schon eingebaut.
Hmm, wegen dem Stack, das versteh ich nicht ganz... Bisher habe ich immer Zeiger, egal wo deklariert, wieder mit delete entfernt. Zumindestens tritt der Fehler aber schon bei der Zuweisung der CWnd*-Variable mit GetDlgItem auf.Hier der Code über den die Funktion (der Dialog) aufgerufen wird:
Spielart Dlg; Dlg.SetEnabled (1,false); Dlg.DoModal ();
Hoffe dass das etwas hilft.
Gruß,
Flux
-
Ha, da haben wir doch schon das Problem: Du rufst SetEnabled und damit auch GetDlgItem auf, BEVOR der Dialog per DoModal angezeigt wird.
Am besten du setzt in SetEnabled einfach nur 2 Membervariablen der Klasse Spielart. Das eigentliche Enablen/Disablen erfolgt dann einfach in OnInitDialog des Dialogs.Noch was:
delete gibt einen per new reservierten (Haupt-)Speicher wieder frei. Ein delete ohne new macht keinen Sinn.
Alle Variablen, die du innerhalb von Funktionen OHNE new definierst, werden auf dem sog. Stack angelegt, welcher beim Verlassen der Funktion automatisch geleert wird. Dein CWnd*-Zeiger existiert also nur im Stack und wird beim Verlassen der Funktion automatisch entfernt.Gruß,
Ravel
-
Alle Variablen, die du innerhalb von Funktionen OHNE new definierst, werden auf dem sog. Stack angelegt, welcher beim Verlassen der Funktion automatisch geleert wird. Dein CWnd*-Zeiger existiert also nur im Stack und wird beim Verlassen der Funktion automatisch entfernt.
Diese Erklärung ist hier falsch und nicht angebracht. Siehe dazu Beitrag: Fortschrittsanzeige
[ Dieser Beitrag wurde am 14.04.2003 um 11:40 Uhr von RenéG editiert. ]
-
@Ravel
Alle Variablen, die du innerhalb von Funktionen OHNE new definierst, werden auf dem sog. Stack angelegt, welcher beim Verlassen der Funktion automatisch geleert wird. Dein CWnd*-Zeiger existiert also nur im Stack und wird beim Verlassen der Funktion automatisch entfernt.Diese Erklärung ist hier falsch und nicht angebracht.
Hä, das verstehe ich jetzt nicht. Was ist daran falsch? Ich ging bisher immer davon aus, daß alle in Funktionen deklarierten Variablen ohne new ganz einfach im Stack landen. Dein Link hat mir auch nicht die Erleuchtung gebracht.
Könntest du mich kurz aufklären, wo mein Denkfehler ist?
-
Sicherlich liegt der CWnd*-Zeiger auf dem Stack. ABER:
delete ctlSpielArt löscht doch nicht die 4 Byte des Zeigers, welcher auf dem Stack liegt, sondern den Speicher, auf den innerhalb der 4 Byte verwiesen wird. Und dieser Zeiger kommt von GetDlgItem, also der MFC. Somit sollte auch (und ist) die MFC auch für diesen Zeiger verantwortlich.
-
Sicherlich liegt der CWnd*-Zeiger auf dem Stack. ABER:
delete ctlSpielArt löscht doch nicht die 4 Byte des Zeigers, welcher auf dem Stack liegt, sondern den Speicher, auf den innerhalb der 4 Byte verwiesen wird. Und dieser Zeiger kommt von GetDlgItem, also der MFC. Somit sollte auch (und ist) die MFC auch für diesen Zeiger verantwortlich.Hmm, also wenn ich das jetzt richtig verstanden habe, so erzeugt die Funktion GetDlgItem intern ein temporäres CWnd und gibt dessen Zeiger zurück.
Diesen zurückgegebenen Zeiger weise ich meinem lokalen CWnd* -Pointer zu und kann diesen nun lokal benutzen.
In der MSDN steht ja auchThe returned pointer may be temporary and should not be stored for later use.
Delete darf ich nicht auf den CWnd*-pointer anwenden, da dieser nicht von mir stammt, sondern eben von den MFC temporär erzeugt wurde.
Also verlasse ich die Funktion einfach und die MFC kümmert sich darum, in einer "Ruhepause" den Speicher des CWnd-Objekts zu bereinigen. Die 4 Byte des lokalen Pointers auf dem Stack werden jedoch automatisch ungültig beim Verlassen der Funktion.
Habe ich das jetzt alles richtig verstanden?Gruß,
Ravel
-
korrekt
-
Ok, also vielen Dank erstmal, ich werde versuchen so eine Lösung zu finden.
Und ja, auch danke wegen der Pointer Diskussion, weil nun ist mir auch eher klar was eigentlich passiert. Das delete war aber sowieso fehl am Platz, das stimmt *g*.Grüße,
Flux