->Modified direkt setzen / mit Zeiger setzen
-
Hallo,
das Thema OnChange und Modified hatten wir zwar schon, es ist jedoch eine (IMHO wesentliche) Frage offen geblieben:
Man nehme ein Edit auf ein Form. Ist es zur Laufzeit aktiv und der Benutzer macht eine Eingabe, tritt unter normalen Umständen ein Change-Ereignis ein. Bei entsprechender Benennung und Einbindung der Methoden wird dann eine OnChange-Eventmethode angesprungen, in der das Programm auf die Eingabe reagieren kann.
In dieser OnChange-Eventmethode kann man die Modified-Eigenschaft des Edit abfragen. Damit wird sichergestellt, dass nur auf wirkliche Änderungen des Edit-Text reagiert wird:void __fastcall TForm1::Edit1Change(TObject *Sender) { if(Edit1->Modified) { //...Verarbeitung der Eingabe etc. } }Soweit, so gut... Jetzt nehmen wir folgenden Fall: Man nehme 3 Edits auf einem Form und nutze für alle 3 dieselbe OnChange Eventmethode. (Dieses Beispiel steht stellvertretend für ein Form mit 28 Edits. Wird zur Laufzeit in ein Edit eine Eingabe gemacht, soll diese auf einige andere Edits übertragen werden.) Jedes Edit hat zur Entwurfszeit einen spezifischen Wert in seiner Eigenschaft Tag bekommen, um die Edits zu identifizieren. Nehmen wir an die 3 Edits haben die Tags 1, 2 und 3. Wird etwas in Edit1 eingetragen, soll es auch in Edit2 und Edit3 erscheinen. Wird etwas in Edit2 eingetragen, soll es auch in Edit3 erscheinen. Wieder soll die Modified-Eigenschaft zur Sicherheit abgefragt werden:
void __fastcall TForm1::AllEditChange(TObject *Sender) { TEdit *VirtualEdit= static_cast<TEdit*>(Sender); bool bBreak= false; unsigned short VETag= VirtualEdit->Tag; AnsiString VEEingabe= VirtualEdit->Text; if(VirtualEdit->Modified) { for(k=0; k<ComponentCount; k++) { if(Components[k]->ClassNameIs("TEdit")) { TEdit *VirtualEditTemp= static_cast<TEdit*>(Components[k]); unsigned short VETmpTag= VirtualEditTemp->Tag; // hier steht bei 28 Edits eine lange switch-Anweisung: if(((VETag==1) || (VETag==2)) && (VETmpTag==VETag+1)) { VirtualEditTemp->Text= VEEingabe; // ... bBreak= true; } } if(bBreak) break; } } }So sieht das Ganze dann aus und es funktioniert auch - fast. Das Bespiel lässt vermuten, dass wenn Edit1 einen Eintrag erhält und dieser in Edit2 geschrieben wird, danach auch Edit3 automatisch den Text erhält - Pustekuchen. Die Anweisung VirtualEditTemp->Text= VEEingabe; löst zwar ein Change-Ereignis aus, es wird auch direkt nach dieser Anweisung die AllEditChange-Eventmethode aus sich selbst heraus neu angesprungen, jedoch ist die Modified-Eigenschaft des zweiten veränderten Edits nicht true. Und da sind wir dicht am Problem!
Als logische Konsequenz füge ich jetzt in die innersten if-Bedingung ein Setzen der Modified-Eigenschaft ein. Dadurch sollen bei einer Eingabe in Edit1, die Edits 2 und 3 mit verändert werden:// Variante 1: if(((VETag==1) || (VETag==2)) && (VETmpTag==VETag+1)) { VirtualEditTemp->Modified= true; VirtualEditTemp->Text= VEEingabe; // <= Change-Event & sofort Sprung zu EditAllChange // ... bBreak= true; }Leider ist Modified des gecasteten Sender-Edits dann beim automatischen zweiten Durchlauf der AllEditChange-Methode immer false, was ich nicht verstehe! Liegt es am erneuten casten des Edits nach dem 2. Sprung in AllEditChange?
Folgendes funktioniert geprüftermaßen:// Variante 2: if((VETag==1) && (VETmpTag==VETag+1)) { Edit2->Modified= true; Edit2->Text= VEEingabe; // <= Change-Event & sofort Sprung zu EditAllChange // ... bBreak= true; } if((VETag==2) && (VETmpTag==VETag+1)) { Edit3->Modified= true; Edit3->Text= VEEingabe; // <= Change-Event & sofort Sprung zu EditAllChange // ... bBreak= true; }Mit Variante 2 werden nach einer Eingabe in Edit1 auch Edit2 und 3 automatisch mit derselben Eingabe versehen. Nach einer Eingabe in Edit2, wird nur Edit3 automatisch mit der Eingabe versehen. Das Problem: Variante 2 ist wesentlich länger (gerade bei 28 Edits) als Variante 1. Warum funktioniert Variante 1 nicht wunschgemäß? Warum wird das Modified über den Zeiger in Variante 1 nicht gesetzt?
Danke schonmal, wer sich bis hierhin durchgekämpft hat! Ich hoffe es kann jemand eine Aussage dazu machen..
-
Modified wird durchaus über den Zeiger gesetzt. Aber offenbar wird es auf false gesetzt, wenn man Text von Anwendungsseite setzt. Dadurch ist die Zuweisung nutzlos. Das widerspricht natürlich dem Hinweis in der BCB-Hilfe.
Allerdings ist etwas unverständlich, wieso du überhaupt Modified abfragst.
-
Hallo
Nein das widerspricht nicht der Builder-Hilfe zu TEdit::Modified
Die Eigenschaft Modified sollte auf true gesetzt werden, falls eine Anwendung die Eigenschaft Text in einem Eingabefeld direkt ändert.
Sagt doch genau aus : Wenn das Programm (und nicht der User) den Edit-Inhalt selber setzt, wird Modified auf false gesetzt.
Und ich empfehle auch dringend statt dem ständigen Edit-Suchen und -Casten besser gleich alle betreffenden (und nur die) Edits in ein entsprechendes dynamisches Array zu packen. Genaue Beschreibung siehe FAQ.
Und dann würde ich auch mit Schleifen arbeiten anstelle von mehrfachen Events.bis bald
akari
-
Morris Szyslak schrieb:
Modified wird durchaus über den Zeiger gesetzt. Aber offenbar wird es auf false gesetzt, wenn man Text von Anwendungsseite setzt. Dadurch ist die Zuweisung nutzlos. Das widerspricht natürlich dem Hinweis in der BCB-Hilfe.
akari schrieb:
Nein das widerspricht nicht der Builder-Hilfe zu TEdit::Modified
Die Eigenschaft Modified sollte auf true gesetzt werden, falls eine Anwendung die Eigenschaft Text in einem Eingabefeld direkt ändert.
Sagt doch genau aus : Wenn das Programm (und nicht der User) den Edit-Inhalt selber setzt, wird Modified auf false gesetzt.
Genau das steht da eben nicht explizit geschrieben. Da steht nur: Modified wird nicht true gesetzt, wenn das Prog die Eigenschaft Text ändert. Der Rest ist erstmal der freien Interpretation des Programmierers überlassen, bzw. den Göttern des Probierens. Und IMHO wäre die logische Konsequenz, dass Modified nicht verändert wird, wenn die Text-Eigenschaft programmseitig verändert wird. Das Funktionieren von Variante 2 stützt diese These eigentlich unumstößlich. Die Frage ist: Was läuft da anders, wenn Modified über den Zeiger gesetzt wird?
--------------------------------------------------------------------------------
Morris Szyslak schrieb:
[...] Allerdings ist etwas unverständlich, wieso du überhaupt Modified abfragst.
Das wurde so empfohlen und wird in Beispielen wird es auch so gemacht. Ich habe nicht den Durchblick und weiß nicht, wann Change noch OnChange erzeugt... aus der Hilfe wird das (für mich) auch nicht wirklich ersichtlich:
Die Methode Change erzeugt das Ereignis OnChange.
*DYNAMIC void __fastcall Change(void);
*
BeschreibungAnwendungen rufen die Methode Change nicht direkt auf. Sie wird automatisch von Windows-Ereignissen ausgelöst. Change ist als Methode vom Typ protected deklariert. Damit können abgeleitete Klassen zusätzliche Reaktionen definieren, die über den Aufruf der Ereignisbehandlungsroutine für OnChange hinausgehen. Wenn abgeleitete Klassen, die die Methode Change überschreiben, die geerbte Methode nicht aufrufen, wird die Ereignisbehandlungsroutine OnChange nicht aufgerufen.

--------------------------------------------------------------------------------akari schrieb:
Und ich empfehle auch dringend statt dem ständigen Edit-Suchen und -Casten besser gleich alle betreffenden (und nur die) Edits in ein entsprechendes dynamisches Array zu packen. Genaue Beschreibung siehe FAQ.
Und dann würde ich auch mit Schleifen arbeiten anstelle von mehrfachen Events.Damit werde ich mich befassen (sagte ich ja schonmal). Jetzt möchte ich aber dieses Mysterium lösen!
-
@akari: ich habe gerade in den VCL-FAQ's "Dynamische Arrays von Komponenten oder Objekten" gelesen. Das ist ja einfach.... Danke für deinen beharrlichen Hinweis!

Das heißt aber jetzt nicht, das mich das Edit->Modified-Mysterium nicht mehr interessiert!
