Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Windows Message bei Änderung? (https://www.delphipraxis.net/185088-windows-message-bei-aenderung.html)

idefix2 14. Mai 2015 08:54

Windows Message bei Änderung?
 
Gibt es eigentlich eine Windows Message, die immer dann geschickt wird, wenn irgendwo im Formular der Inhalt eines WinControl verändert wurde?
Ich habe jetzt eine Weile gesucht, aber nichts gefunden.

Bernhard Geyer 14. Mai 2015 10:39

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von idefix2 (Beitrag 1301484)
Gibt es eigentlich eine Windows Message, die immer dann geschickt wird, wenn irgendwo im Formular der Inhalt eines WinControl verändert wurde?
Ich habe jetzt eine Weile gesucht, aber nichts gefunden.

Definiere Inhalte eine WinControls?
Es wird viele Windows-Message geben die Gefeuert werden wenn was geändert wurde. Es gibt aber nicht die Broadcast-Windows-Message die immer gefeuert wird.

himitsu 14. Mai 2015 11:35

AW: Windows Message bei Änderung?
 
Eine CheckBox feuert was anders, wenn sie an-/abgehackt wird und ob sie was auslöst, wenn man ihren Text ändert, weiß ich jetzt nicht.

Dagegen feuert ein Label, Edit, Panel und TForm die selbe Message, wenn man ihren Text (Caption, Text, Caption, Caption/Überschrifft) ändert.

Wann soll eine ListView welche einheitliche Message senden? (Änderung der Selection, Änderung der Items, ...)

idefix2 17. Mai 2015 21:47

AW: Windows Message bei Änderung?
 
Ich habe auf jedem Formular zwei Buttons für "abbrechen" und "speichern".
Solange am Formular keine Änderungen gemacht worden sind, ist nur der "speichern"-button enabled und hat als Caption "schliessen" statt "speichern".
Sobald irgend welche Daten geändert worden sind (Text in einem Edit, Radiobutton-Status, checkbox-Status, egal was) werden beide Button aktiviert, und der User kann die Änderungen speichern oder mit "abbrechen" das Formular verlassen, ohne die Änderungen zu speichern.
Ich verwende jetzt einen Timer, der alle 200 Millisekunden alle Komponenten durchgeht und schaut, ob etwas geändert worden ist. Es gibt eine globale Message focuschanged, an die hatte ich die Prüfung vorher gehängt, aber das hat den Nachteil, dass der Button "Speichern" erst aktiviert wird, wenn der User die erste veränderte Komponente verlassen hat.
Sobald ich dazukomme, leite ich mir eigene Komponenten ab, die jede Änderung melden, aber dazu fehlt mir jetzt die Zeit. Wenn es leicht ginge, hätte ich gerne den Timer rausgeschmissen, aber wenn ich mich dafür in ein Dutzend verschiedene Windows Messages hängen müsste, dann lasse ich es fürs erste so, wie es ist.

Perlsau 17. Mai 2015 21:52

AW: Windows Message bei Änderung?
 
Das würde ich mir nochmal überlegen ... Du hast doch irgendwelche Methoden, in denen die Eingaben des Anwenders verarbeitet werden. Werden diese Methoden aufgerufen, ist das ein sicheres Zeichen dafür, daß Änderungen stattfinden. Wieso nimmst du nicht einfach eine Boolsche Variable z.B. mit Namen Gesichert, die beim Programmstart und beim Speichern auf True gesetzt wird, bei Änderungen dagegen auf False? Wenn der Anwender nun das Programm zu beenden wünscht, fragst du im OnCloseQuery ab, ob Gesichert False ist, und wenn ja, dann fragst du den Anwender, ob die geänderten Daten gesichert werden sollen. In den Methoden, mit denen Daten verändert werden, setzt du dann Gesichert immer auf False.

Popov 17. Mai 2015 23:39

AW: Windows Message bei Änderung?
 
@idefix2

Schon mal überlegt, dass du selbst eigene Messages definieren und verschicken kannst?

idefix2 18. Mai 2015 07:40

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von Perlsau (Beitrag 1301862)
Das würde ich mir nochmal überlegen ... Du hast doch irgendwelche Methoden, in denen die Eingaben des Anwenders verarbeitet werden.

Für die meisten der Komponenten nicht. Die Daten werden über unterschiedliche Komponenten (Edit, Combobobox, Radiobutton etc.) erfasst und beim Drücken des Buttons "speichern" ohne weitere spezielle Verarbeitung abgespeichert. Nur wenige Eingabefelder haben eigene Ereignisbehandlungsroutinen.

Zitat:

Zitat von Popov (Beitrag 1301869)
@idefix2
Schon mal überlegt, dass du selbst eigene Messages definieren und verschicken kannst?

Dazu müsste ich mir eben eigene Komponenten ableiten und statt der normalen Komponenten meine abgeleiteten verwenden. Das ist dann doch etwas mehr Arbeit.

Perlsau 18. Mai 2015 07:54

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von idefix2 (Beitrag 1301884)
Zitat:

Zitat von Perlsau (Beitrag 1301862)
Das würde ich mir nochmal überlegen ... Du hast doch irgendwelche Methoden, in denen die Eingaben des Anwenders verarbeitet werden.

Für die meisten der Komponenten nicht. Die Daten werden über unterschiedliche Komponenten (Edit, Combobobox, Radiobutton etc.) erfasst und beim Drücken des Buttons "speichern" ohne weitere spezielle Verarbeitung abgespeichert. Nur wenige Eingabefelder haben eigene Ereignisbehandlungsroutinen.

:wiejetzt: Du speicherst Editfelder, ComboBoxen und RadioButtons direkt, verfügst also nicht über irgend eine Datenstruktur, die von deinen Edit-Komponenten bearbeitet werden kann? Das würde ja bedeuten, du speicherst deine Daten in visuellen Komponenten. Das halte ich für keine gute Idee ... Aber egal, mußt du letztendlich selber wissen, da möchte ich jetzt nicht länger drauf rumreiten.

Änderungen eines Editfeldes, einer ComboBox, eines Radio-Buttons etc. lösen OnChange aus: Du legst für all deine Edit-Komponenten dieselbe OnChange-Ereignisbehandlung fest. In dieser legst du dann die Information, daß etwas geändert wurde, fest. Du mußt auch keine Boolsche Variable neu deklarieren, denn du hast ja bereits eine in deinen Speichern-Button zur Verfügung, den du hier auf Enabled := True setzen kannst. Und schon hast du die Information, daß etwas geändert wurde oder daß alle Änderungen gespeichert sind, im Programm verfügbar. Nach dem Speichern führst du einfach Speicherbutten.Enabled := False aus.

idefix2 18. Mai 2015 08:01

AW: Windows Message bei Änderung?
 
Natürlich speichere ich den Inhalt der diversen Felder und nicht die visuellen Komponenten.

Die Verwendung des Onchange ist von der Programmierung her recht fehleranfällig: wenn ich ein neues Feld einführe und auf die Zuweisung des Onchange vergesse, oder wenn ich ein spezielles Onchange brauche und dort auf das inherited vergesse, dann merke ich den Fehler nicht leicht.
Mit der Methode, die ich verwende, brauche ich mich um nichts zu kümmern. Das Programm merkt auch bei neu eingeführten Komponenten ohne irgend eine Zusatzprogrammierung, wann sie geändert worden sind.

himitsu 18. Mai 2015 08:11

AW: Windows Message bei Änderung?
 
Andersrum ist es auch fehleranfällig.

Windows/Delphi ändert was oder du verwendest eine neue/andere Komponente, deren Message noch nicht behandelt wird, dann geht es ebenfalls nicht.

Andere Lösung:
Du leitest alle nötigen Komponenten ab, welche die nötigen Erweiterungen für die "Änderungsbehandlung" beinhalten. (z.B. TMyOptionsEdit, TMyOptionsCheckBox, ... -> IsChanged-Property und Notification an die Vorfahren-TMyOptionsForm oder eine TMyOptionsNotifier-Komponente auf der Form)

Und der Code ist später vielleicht auch mal plattformunabhängig, denn Android, iOS, Linux und Max haben irgendwie ihre Problemchen, mit den komischen Windows-Messages. :stupid:

Perlsau 18. Mai 2015 08:19

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von idefix2 (Beitrag 1301886)
Natürlich speichere ich den Inhalt der diversen Felder und nicht die visuellen Komponenten.

Da hab ich mich wohl unklar ausgedrückt. Was ich wissen wollte: Gibt es eine Datenstruktur, z.B. einen Record, der die Inhalte der doch sehr unterschiedlichen Eingabe-Komponenten (EKs) aufnimmt? Wenn ja: wo wird der Inhalt der EKs in diesen übertragen? Wenn nicht: Wie speicherst du derart unterschiedliche Inhalte dieser EKs?

Zitat:

Zitat von idefix2 (Beitrag 1301886)
Die Verwendung des Onchange ist von der Programmierung her recht fehleranfällig: wenn ich ein neues Feld einführe und auf die Zuweisung des Onchange vergesse, oder wenn ich ein spezielles Onchange brauche und dort auf das inherited vergesse, dann merke ich den Fehler nicht leicht.

Klar, wenn man Fehler macht, indem man gegen das eigene Programmierkonzept verstößt ...

Zitat:

Zitat von idefix2 (Beitrag 1301886)
Mit der Methode, die ich verwende, brauche ich mich um nichts zu kümmern. Das Programm merkt auch bei neu eingeführten Komponenten ohne irgend eine Zusatzprogrammierung, wann sie geändert worden sind.

Welche Methode verwendest du denn? Ich hatte bislang den Eindruck, ein von dir gesuchtes Ereignis gäbe es nicht. Aber eigentlich suchst du ja tatsächlich OnChange, denn das ist genau das Ereignis, das augelöst wird, wenn der Inhalt bzw. Status einer EK verändert wird.

Weiter oben schreibst du noch etwas, was in mir den Eindruck verstärkt, dein Konzept sei zumindest noch mal zu überdenken:

Zitat:

Zitat von idefix2 (Beitrag 1301861)
Ich habe auf jedem Formular zwei Buttons für "abbrechen" und "speichern".
Solange am Formular keine Änderungen gemacht worden sind, ist nur der "speichern"-button enabled und hat als Caption "schliessen" statt "speichern".

Das verstehe ich jetzt nicht: Wieso ist der Button Speichern enabled, solange keine Änderungen gemacht wurden? Was gibt es davor denn zu speichern?

Zitat:

Zitat von idefix2 (Beitrag 1301861)
Sobald irgend welche Daten geändert worden sind (Text in einem Edit, Radiobutton-Status, checkbox-Status, egal was) werden beide Button aktiviert, und der User kann die Änderungen speichern oder mit "abbrechen" das Formular verlassen, ohne die Änderungen zu speichern.

Noch mehr Verwirrung: Was versteht du unter "Buttons werden aktiviert"? Etwa Enbled := True? Der Speicherbutton ist doch bereits enabled ...

Zitat:

Zitat von idefix2 (Beitrag 1301861)
Ich verwende jetzt einen Timer, der alle 200 Millisekunden alle Komponenten durchgeht und schaut, ob etwas geändert worden ist. Es gibt eine globale Message focuschanged, an die hatte ich die Prüfung vorher gehängt, aber das hat den Nachteil, dass der Button "Speichern" erst aktiviert wird, wenn der User die erste veränderte Komponente verlassen hat.

Das Verlassen einer Komponente ist doch kein Garant für eine Änderung ihres Inhaltes oder ihres Status. Außer deiner Befürchtung, daß du den Fehler nicht finden würdest, gibt es keinen Grund, nicht genau das dafür vorgesehene Ereignis zu verwenden. Und keine Sorge: Den Fehler findest du schon, spätestens nach diesem Thread hier hat sich das in deinem Langzeitgedächtnis eingegraben :lol:

Zitat:

Zitat von idefix2 (Beitrag 1301861)
Sobald ich dazukomme, leite ich mir eigene Komponenten ab, die jede Änderung melden, aber dazu fehlt mir jetzt die Zeit. Wenn es leicht ginge, hätte ich gerne den Timer rausgeschmissen, aber wenn ich mich dafür in ein Dutzend verschiedene Windows Messages hängen müsste, dann lasse ich es fürs erste so, wie es ist.

Alle Eingabe-Komponenten melden doch bereits, wenn ihre Inhalt bzw. ihr Status geändert wurde. Das Ereignis heißt OnChange. Du zäumst ein totes Pferd von hinten auf und ziehst damit die Kirche durch's Dorf, um's mal etwas überspitzt auszudrücken. Aber wie gesagt, du mußt selbst wissen, was du tust ...

Popov 18. Mai 2015 08:42

AW: Windows Message bei Änderung?
 
Ich glaube du wirst nicht drumherum kommen alles selbst zu machen. Edit-Komponenten kennen zwar die Eigenschaft Modifed, aber das kennen nur die Edit-Komponenten.

Auch kennt die TForm die Eigenschaft KeyPreview. Das bedeutet, dass das Formular alle Tastaturanschläge vor dem Steuerelement erhält. Somit könnte man mit einem OnKeyDown des Formulars ein Dutzend Editfelder "überwachen". Aber es funktioniert nur bei Tastauranschlägen.

idefix2 18. Mai 2015 08:57

AW: Windows Message bei Änderung?
 
@himitsu
Das Ableiten von eigenen Komponenten steht auf meiner to-do List.

Wenn es eine Windowsmessage 'somethinghaschanged' geben würde, die bei jeder Änderung des Inhalts eines beliebigen Wincontrol gefeuert würde, dann würde ich mich schon darauf verlassen wollen, dass die bei jeder Art von Wincontrol und bei jeder Änderung des Inhalts uch in zukünftigen Windows-Versionen gefeuert wird. Nachdem es die nicht gibt, sind weitere Überlegungen in der Richtung ohnedies hinfällig.

Die Verwendung eines neuen/anderen Komponententyps kommt ungleich seltener vor als die Einführung eines neuen z.B. Editfelds. Wenn ich in meiner Form einen neuen Komponententyp verwende, den ich bisher in der Überprüfung von Änderungen noch nicht berücksichtigt habe, dann muss ich mich um den natürlich kümmern, aber das ist doch eher eine seltene Ausnahme.

@perlsau
Zitat:

Wenn ja: wo wird der Inhalt der EKs in diesen übertragen?
Delphi-Quellcode:
for i:=0 to componentcount-1 do
  if form.component[i] is Tedit then ...
  else
  if form.component[i] is Tradiogroup then ...
  else
  ...
Die Namen der visuellen Komponenten der Form entsprechen den Namen der Datenfelder in der Datenbank (mit einem Prefix), sodass ich mich dabei um nichts weiter kümmern muss. Nur wenn das in seltenen Ausnahmefällen nicht möglich ist, muss ich extra Code schreiben, aber in den Fällen weiss ich dann auch, dass ich besonders aufpassen muss.


Zitat:

Klar, wenn man Fehler macht, indem man gegen das eigene Programmierkonzept verstößt ...
Je mehr Dinge man manuell tun muss, desto leichter vergisst man irgendwo auf irgendwas.

Zitat:

Aber eigentlich suchst du ja tatsächlich OnChange, denn das ist genau das Ereignis, das augelöst wird, wenn der Inhalt bzw. Status einer EK verändert wird.
Eben nicht, weil ich auf das Ereignis auf der Ebene jeder einzelnen Komponente reagieren müsste. Schön wäre ein onchange der Form, aber das gibt es nicht.

Zitat:

Welche Methode verwendest du denn?
Ich verwende jetzt einen Timer, wie ich eingangs geschrieben habe.

Zitat:

Das verstehe ich jetzt nicht: Wieso ist der Button Speichern enabled, solange keine Änderungen gemacht wurden? Was gibt es davor denn zu speichern?
...
Noch mehr Verwirrung: Was versteht du unter "Buttons werden aktiviert"? Etwa Enbled := True? Der Speicherbutton ist doch bereits enabled ...
Für den User sieht es so aus:
Solange es keine Änderung gibt, gibt es einen Button "Schliessen" und der Button "abbrechen" ist disabled. Wenn etwas geändert wurde, dann wird aus dem Button "Schliessen" ein Button "Speichern" (es ist der gleiche Button mit einer anderen Caption) und der Button "Abbrechen" wird enabled. Werden alle Änderungen der Form rückgängig gemacht, sodass in der Form genau das angezeigt wird, was in der DB gespeichert ist, dann wird aus "Speichern" wieder "schliessen" und "abbrechen" wird wieder disabled.

Zitat:

Alle Eingabe-Komponenten melden doch bereits, wenn ihre Inhalt bzw. ihr Status geändert wurde. Das Ereignis heißt OnChange
Sie reagieren aber eben nicht automatisch auf die "Meldung". Dazu müsste ich neue Komponenten ableiten, die von selbst wissen, wie sie reagieren müssen, wenn onchange eintritt.

@Popov
Ja, ich fürchte, du hast Recht. :-D

Perlsau 18. Mai 2015 09:33

AW: Windows Message bei Änderung?
 
Alle Ereignisse werden automatisch ausgelöst, wenn ihre Bedingung zutrifft. OnChange reagiert auf alle Benutzer-Eingaben automatisch - zumindest in meinem Delphi 2009. Vielleicht ist das ja bei dir anders ...

Wieso verwendest du nicht einfach DB-sensitive Komponenten, wenn bereits deine Eingabe-Felder direkt mit Datenbank-Feldern korrespondieren?

Aber egal, du mußt nicht antworten, ich geb's hier sowieso auf und überlasse dich deinen – aus meiner Sicht – merkwürdigen Programmierkonzepten :cry:

idefix2 18. Mai 2015 10:41

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von Perlsau (Beitrag 1301898)
OnChange reagiert auf alle Benutzer-Eingaben automatisch - zumindest in meinem Delphi 2009. Vielleicht ist das ja bei dir anders ...

OnChange tut erst einmal gar nichts, solange du nicht explizit ein OnChange-Ereignis programmierst und das im OI (oder sonstwie) der Komponente zuweist.
Ich glaube nicht, dass das bei dir anders ist.

Zitat:

Zitat von Perlsau (Beitrag 1301898)
Aber egal, du mußt nicht antworten, ich geb's hier sowieso auf und überlasse dich deinen – aus meiner Sicht – merkwürdigen Programmierkonzepten :cry:

Stimmt, man muss nicht immer alles verstehen :wink:

Dalai 18. Mai 2015 11:01

AW: Windows Message bei Änderung?
 
Wieso weist du nicht beim Erstellen/Anzeigen des Formulars oder beim Befüllen der Komponenten das OnChange zu? So mache ich das jedenfalls. Klar kann man da die eine oder andere Komponente vergessen, aber das fällt doch sofort auf, wenn sich der Speichern-Button nicht ändert beim Ändern eben dieser Komponente.

[EDIT]
Ich benutze sowas in der Art:
Delphi-Quellcode:
procedure TForm1.ToggleChangeEventHandlers(Enable: Boolean);
var tne: TNotifyEvent;
begin
    if Enable then
       tne:= SetPropertiesChanged
    else
       tne:= nil;

    //--- Set all OnChange/OnClick event handlers
    editName.OnChange:= tne;
    editCommandLine.OnChange:= tne;
    checkEnabled.OnClick:= tne;
    editComments.OnChange:= tne;
    comboShowWindow.OnChange:= tne;
    comboLocation.OnChange:= tne;
end;
Alles ist zentral in dieser Methode. Das hat sogar den Vorteil, dass man temporär alle Behandlungsroutinen abschalten kann, wenn man es braucht (z.B. Speichervorgang).

MfG Dalai

Popov 18. Mai 2015 11:02

AW: Windows Message bei Änderung?
 
@idefix2

Hast du von dem Flugzeugunglück über dem Pazifik gehört, bei dem sich drei erfahrene Piloten mit einem unwichtigem Lämpchen beschäftigt haben und deshalb keiner von ihnen mitbekommen haben, dass sich das Passagierflugzeug gerade im Sturzflug befindet? Da gab es auch ein Flugzeugunglück über den USA, wo sich auch drei Piloten mit einem defekten Lämpchen für das Fahrwerk beschäftigt haben und keiner mitbekommen hat, dass der Sprit alle wurde? Manchmal ist es so, dass sich Menschen auf etwas verbeißen, was evtl. nicht so wichtig ist, und nicht auf das eigentliche konzentrieren.

Sich mit WinControl zu beschäftigen ist nicht falsch, aber warum beschäftigst du dich damit? Du scheinst jede Komponente auf WinControl zu reduzieren.

Übrigens, wie soll WinControl wissen ob es eine Änderung in ihr gab? Ist eine Texteingabe in TEdit eine Änderung? Klar. Ist das Setzen der CheckBox eine Änderung? Klar. Ist das Bewegen des Mauszeigers von rechts nach links über ein Panel eine Änderung? In Smartphones ist das eine Funktion.

Woher soll also WinControl wissen was eine Änderung ist. Das eine Texteingabe eine Änderung ist, das weiß TEdit, aber nicht WinControl. Denn wie gesagt, woher soll es wissen was du unter einer Änderung verstehst. Auch das Bewegen des Mauszeigers kann eine Änderung sein.

Perlsau 18. Mai 2015 11:30

AW: Windows Message bei Änderung?
 
Irgendwie hab ich den Eindruck, dir ist die Arbeitsweise eines Delphi-Programms nicht so recht klar ... mein ganz persönlicher subjektiver Eindruck, den mußt du ja nicht teilen und solltest dich auch nicht darüber ärgern, daß ich das so sehe, wie auch ich mich nicht darüber ärgere, daß du dir Umstände machst, wo das nicht wirklich notwendig wäre.

Zitat:

Zitat von idefix2 (Beitrag 1301905)
Zitat:

Zitat von Perlsau (Beitrag 1301898)
OnChange reagiert auf alle Benutzer-Eingaben automatisch - zumindest in meinem Delphi 2009. Vielleicht ist das ja bei dir anders ...

OnChange tut erst einmal gar nichts, solange du nicht explizit ein OnChange-Ereignis programmierst und das im OI (oder sonstwie) der Komponente zuweist.
Ich glaube nicht, dass das bei dir anders ist.

Eigentlich wollte ich hier ja nichts mehr posten, aber du provozierst das, indem du den Sinn meiner Aussage so verdrehst, als hätte ich behauptet, die Zuweisung eines Ereignisses würde auch gleich die Ereignisbehandlung erstellen oder beinhalten. Tatsächlich habe ich geschrieben, daß Ereignisse immer automatisch ausgelöst werden – ausgelöst und nicht behandelt –, und zwar auf deine falsche Behauptung hin, daß Ereignisse nicht automatisch ausgelöst würden.

Letztendlich mußt du auch bei deiner "Lösung" eine Ereignisbehandlung schreiben, denn das Timer-Ereignis tut auch erstmal gar nichts außer eben auszulösen. Oder mit anderen Worten: Der Kampf gegen Windmühlen war schon immer ein aussichtsloser :lol:

Ich denke, du solltest das so machen, wie du denkst, und auf keinen Fall dumme Ratschläge von erfahrenen Programmieren annehmen, ja nicht einmal darüber nachdenken, warum die überhaupt was vorschlagen ... um vielleicht zu einem späteren Zeitpunkt den Holzweg, auf den du dich – meiner bescheidenen subjektiven Ansicht nach – begeben hast, erkennen zu können. Macht ja nix, ich muß ja deinen Code weder warten noch erweitern und auch nicht mit deiner Anwendung arbeiten :)
Aber ich kann mich noch gut daran erinnern, daß ich früher – heute etwas weniger – zahlreiche umständliche Klimmzüge veranstaltet habe, weil mir so manche Funktion von Delphi einfach noch nicht bekannt oder ich falsch darüber informiert war, wie sie funktioniert. Wenn man dann gleichzeitig an den eigenen Mythos vom gewieften Programmierer glauben will oder muß, hat man da ein echtes Problem am (oder im) Hals :vernupft:

Achso, bevor ich's vergesse: Mich würde noch immer interessieren, wieso du keine datensensitiven Komponenten verwendest, wenn du schon mit einer Datenbank arbeitest und die Komponenten doch, wie du schriebst, direkt mit diversen DB-Feldern assoziiert sind. Da würden nämlich alle Änderungen sofort ohne Timer oder OnChange-Ereignisbehandlung gespeichert werden. Ob ich das noch erfahren werde in diesem Leben? Ach was soll's, das Leben geht weiter :-D
Ich habe heute auf jeden Fall eines gelernt: OnChange ist für manche Programmierer ganz ganz böse :dancer:
In Wirklichkeit hab ich natürlich was ganz anderes gelernt ... aber du mußt ja nicht alles wissen :angel:

idefix2 18. Mai 2015 12:06

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von Popov (Beitrag 1301908)
Übrigens, wie soll WinControl wissen ob es eine Änderung in ihr gab? Ist eine Texteingabe in TEdit eine Änderung? Klar. Ist das Setzen der CheckBox eine Änderung? Klar. Ist das Bewegen des Mauszeigers von rechts nach links über ein Panel eine Änderung? In Smartphones ist das eine Funktion.

Nachdem es die Message nicht gibt, sind weitere Überlegungen in die Richtung natürlich sinnlos. Aber wenn es so eine Message geben würde, dann müsste natürlich jede Komponente selbst wissen, wann sie sie verschicken muss, TWinControl kann das nicht. Das könnte mir aber gleichgültig sein.

idefix2 18. Mai 2015 12:26

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von Perlsau (Beitrag 1301914)
Eigentlich wollte ich hier ja nichts mehr posten, aber du provozierst das, indem du den Sinn meiner Aussage so verdrehst, als hätte ich behauptet, die Zuweisung eines Ereignisses würde auch gleich die Ereignisbehandlung erstellen oder beinhalten. Tatsächlich habe ich geschrieben, daß Ereignisse immer automatisch ausgelöst werden – ausgelöst und nicht behandelt –, und zwar auf deine falsche Behauptung hin, daß Ereignisse nicht automatisch ausgelöst würden.

Die falsche Behauptung habe ich nirgends aufgestellt. Das Auslösen des Ereignisses hilft nicht, wenn nicht daruf reagiert wird. Mir geht es darum, dass diese Reaktion immer automatisch abläuft, ohne dass ich dafür in einer Komponente, die ich in der Form platziere, weitere Schritte unternehmen müsste.

Zitat:

Zitat von Perlsau (Beitrag 1301914)
Letztendlich mußt du auch bei deiner "Lösung" eine Ereignisbehandlung schreiben, denn das Timer-Ereignis tut auch erstmal gar nichts außer eben auszulösen. Oder mit anderen Worten: Der Kampf gegen Windmühlen war schon immer ein aussichtsloser :lol:

Bei meiner Lösung muss ich die Ereignisbehandlung ein einziges mal schreiben und brauche mich später, beim Einfügen eines neuen Datenfeldes, nicht mehr darum kümmern. Meine Ereignisbehandlung kümmert sich automatisch um alle Datenfelder des Formulars, egal welche und wie viele es sind. Nur wenn ich irgendwann einen neuen Typ von Datenfeld verwenden sollte, den ich bisher nicht verwendet und berücksichtigt habe, müsste ich die Ereignisbehandlungsroutine erweitern.

Zitat:

Zitat von Perlsau (Beitrag 1301914)
Ich denke, du solltest das so machen, wie du denkst, und auf keinen Fall dumme Ratschläge von erfahrenen Programmieren annehmen, ja nicht einmal darüber nachdenken, warum die überhaupt was vorschlagen ...

Ja, nach über dreissig jahren professioneller Programmiertätigkeit (aber dabei eher wenig mit Delphi und der Windows Oberfläche) bin ich sicher noch zu unerfahren, um eine Ahnung von dem zu haben, was ich tue.

Zitat:

Zitat von Perlsau (Beitrag 1301914)
Achso, bevor ich's vergesse: Mich würde noch immer interessieren, wieso du keine datensensitiven Komponenten verwendest, wenn du schon mit einer Datenbank arbeitest und die Komponenten doch, wie du schriebst, direkt mit diversen DB-Feldern assoziiert sind. Da würden nämlich alle Änderungen sofort ohne Timer oder OnChange-Ereignisbehandlung gespeichert werden.

Dafür habe ich durchaus gute Gründe, aber ich fürchte nach unserem bisherigen Diskussionsverlauf, dir die erläutern zu wollen wäre vergebliche Liebesmüh. Es ist mir lieber so.

TRomano 18. Mai 2015 12:31

AW: Windows Message bei Änderung?
 
Ich habe mir das nun alles durchgelesen und bin ein wenig verwundert ...wenn man in der DP etwas erfragt und von wirklich, langjährig erfolgreichen, Entwicklern Konzepte vorgeschlagen bekommt sollte man wenigstens mal in sich gehen und darüber nachdenken.
In deinem Falle, und so lange Du dir keine Ableitungen von den Komponenten machst, würde ich mir, wenn es schnell gehen soll, einen Dictionary mit den Start- und aktuellen Werten anlegen. In einer zentralen OnChange-Routine kannst Du dann prüfen, ob es überhaupt Änderungen gibt und entsprechend deine Buttons einstellen. Es könnte ja auch sein, dass der User eine Eingabe wieder zurückstellt ...
Oder Du nimmst halt gleich daten-sensitive Controls (da kann man auf xxx.OldValue <> xxx.NewValue prüfen) und checkst in einer zentralen Rotine, ob sich etwas geändert hatte ...

TRomano 18. Mai 2015 12:35

AW: Windows Message bei Änderung?
 
@IdeFix2: ich glaube, dass ich mich jetzt da auch raushalte, denn ich finde es unmöglich, wie Du hier mit den Foren-Usern sprichst, denn man versucht Dir zu helfen und es sind ausgesprochen patzige Antworten. Ich kann auch nicht erkennen, dass Du nach 30 Jahren Berufserfahrung (egal welche Sprache) dein Problem in ein einfaches, aber sicheres, Konzept umsetzt.

idefix2 18. Mai 2015 12:52

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von Dalai (Beitrag 1301907)
Wieso weist du nicht beim Erstellen/Anzeigen des Formulars oder beim Befüllen der Komponenten das OnChange zu? So mache ich das jedenfalls. Klar kann man da die eine oder andere Komponente vergessen, aber das fällt doch sofort auf, wenn sich der Speichern-Button nicht ändert beim Ändern eben dieser Komponente.
...
Alles ist zentral in dieser Methode. Das hat sogar den Vorteil, dass man temporär alle Behandlungsroutinen abschalten kann, wenn man es braucht (z.B. Speichervorgang).

MfG Dalai

Hmm, das wäre auch ein Ansatz, der mir gefallen könnte. Lässt sich noch weiter verbessern, dass man neue Komponenten an der Stelle nicht manuell einfügen muss:
Delphi-Quellcode:
for i:=0 to componentcount-1 do
    if component[i]=Tedit then Tedit(component[i]).onchange:=tne
    else
    if component[i]=Tcheckbox then TCheckbox(component[i]).onchange:=tne
    ...
Ein Problem hätte ich dann nur, wenn es Komponenten gibt, die eine eigene Onchange-Routine brauchen, in der noch irgend etwas anderes passieren soll.

Dalai 18. Mai 2015 13:04

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von idefix2 (Beitrag 1301944)
Ein Problem hätte ich dann nur, wenn es Komponenten gibt, die eine eigene Onchange-Routine brauchen, in der noch irgend etwas anderes passieren soll.

Auch kein Problem, das sich nicht lösen lässt. Beispiel:
Delphi-Quellcode:
procedure TForm1.SetPropertiesChanged(Sender: TObject);
begin
    btnApply.Enabled:= True;
    if Sender = comboLocation then
        checkCopyStartup.Enabled:= True;
end;
Für diese eine Komponente (ComboBox) gibt's in der Ereignisbehandlung zusätzlich eine Besonderheit.

MfG Dalai

Captnemo 18. Mai 2015 13:14

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von idefix2 (Beitrag 1301944)
Delphi-Quellcode:
for i:=0 to componentcount-1 do
    if component[i]=Tedit then Tedit(component[i]).onchange:=tne
    else
    if component[i]=Tcheckbox then TCheckbox(component[i]).onchange:=tne
    ...
Ein Problem hätte ich dann nur, wenn es Komponenten gibt, die eine eigene Onchange-Routine brauchen, in der noch irgend etwas anderes passieren soll.

Deswegen würde ich so was auch nicht machen. Wenn man später eigene OnChange-Ereignisse für bestimmte controls braucht muss man wieder alles umstricken, und dann wird's unübersichtlich.

Hängt natürlich immer davon ab, wie man so arbeitet. Ich persönlich arbeite bei Formularen, denen ich einen solche Logik spendieren möchte, im Formular mit einer Kopie der Originaldaten. Bei Änderungen vergleiche ich dann die Kopie komplett mit dem Original und erkenne so Änderungen, aber auch wenn Änderungen wieder zurückgenommen wurde, und setze meine Buttons entsprechend.

idefix2 18. Mai 2015 13:20

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von TRomano (Beitrag 1301931)
@IdeFix2: ich glaube, dass ich mich jetzt da auch raushalte, denn ich finde es unmöglich, wie Du hier mit den Foren-Usern sprichst, denn man versucht Dir zu helfen und es sind ausgesprochen patzige Antworten.

"mit den Foren-Usern" ist wohl sicher nicht zutreffend. Ich bin für jeden konstruktiven Vorschlag dankbar.

Zitat:

Ich kann auch nicht erkennen, dass Du nach 30 Jahren Berufserfahrung (egal welche Sprache) dein Problem in ein einfaches, aber sicheres, Konzept umsetzt.
Dazu spare ich mir einen weiteren Kommentar.

Zitat:

Zitat von TRomano (Beitrag 1301929)
In deinem Falle, und so lange Du dir keine Ableitungen von den Komponenten machst, würde ich mir, wenn es schnell gehen soll, einen Dictionary mit den Start- und aktuellen Werten anlegen. In einer zentralen OnChange-Routine kannst Du dann prüfen, ob es überhaupt Änderungen gibt und entsprechend deine Buttons einstellen. Es könnte ja auch sein, dass der User eine Eingabe wieder zurückstellt ...

Genau das mache ich ja. Es geht ja nur darum, sicherzustellen, dass diese "zentrale On-Change Routine" auch wirklich allen Komponenten zugeordnet ist. Deshalb hatte ich nach so einer globalen Windows-Message gefragt, an die ich den Event hängen wollte. Aus Erfahrung weiss ich, dass jeder Eintrag, den man jedesmal erneut von Hand machen muss, irgendwann bei einer Programmänderung vergessen wird. Der Ansatz von Dalai wäre allerdings eine gute Alternative zu meinem Timer. Der Vorteil wäre, dass er nur aufgerufen wird, wenn wirklich irgendwo eine Änderung stattgefunden hat, und nicht ständig alle 200ms, der Nachteil, dass er sich mit spezifischen On-Change Events nicht vertragen würde, sollte man solche irgendwo brauchen (was bei mir derzeit nicht der Fall ist, aber im Prinzip könnte das irgendwann sein).

idefix2 18. Mai 2015 13:30

AW: Windows Message bei Änderung?
 
@Dalai
Das würde heissen, dass man individuelle Onchange-Behandlungen auch in der zentralen Routine erledigen muss, wenn man wirklich einmal ausnahmsweise solche braucht, und den einzelnen Kompos eben keine Onchange Ereignisse zuordnen darf - Ja, das scheint mir ganz praktikabel zu sein, die Lösung gefällt mir immer besser :-D .

Und wenn irgendwer, der zwei Jahre später am Formular eine Änderung macht, auf diese Einschränkung vergisst, dann könnte man im OnCreate des Forms eine passende Warnmeldung ausgeben, wenn OnChange bei einer Komponente schon zugeordnet ist. Und hoffen, dass er das Programm nach der Änderung zumindest einmal startet, bevor es an die Kunden ausgeliefert wird :)


Zitat:

Zitat von Captnemo (Beitrag 1301950)
Deswegen würde ich so was auch nicht machen. Wenn man später eigene OnChange-Ereignisse für bestimmte controls braucht muss man wieder alles umstricken, und dann wird's unübersichtlich.

Siehe Lösungsansatz von Dalai. Da braucht man dann nichts umzustricken.

Captnemo 18. Mai 2015 13:37

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von idefix2 (Beitrag 1301952)
Aus Erfahrung weiss ich, dass jeder Eintrag, den man jedesmal erneut von Hand machen muss, irgendwann bei einer Programmänderung vergessen wird.

Ich gehe mal davon aus, dass du deine Eingabecontrols auf der Form selbst setzt. Dann musst du doch sowieso "Hand" anlegen, um z.B. das Control auszurichten, bestimmte Eigenschaften zu setzen, usw. Was spricht dagegen, im dann auch im OnClick oder im OnChange auf Veränderung zu prüfen.

Noch eine Idee: Du könntest das Tag jedes Controls nutzen. In einer zentralen Routine addierst du die Tag's aller Komponenten. Wenn das Ergebnis größer 0 ist, dass speichern. Dann musst du zwar immer noch für alle Controls ein Ereignis haben, was den Tag verändert und dann die zentrale Routine aufruft, aber du brauchst in der Zentralen Routine nix ändern.

Captnemo 18. Mai 2015 13:43

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von idefix2 (Beitrag 1301953)
Zitat:

Zitat von Captnemo (Beitrag 1301950)
Deswegen würde ich so was auch nicht machen. Wenn man später eigene OnChange-Ereignisse für bestimmte controls braucht muss man wieder alles umstricken, und dann wird's unübersichtlich.

Siehe Lösungsansatz von Dalai. Da braucht man dann nichts umzustricken.

Wieso nicht?

Zitat:

Zitat von Dalai (Beitrag 1301907)
Delphi-Quellcode:
procedure TForm1.ToggleChangeEventHandlers(Enable: Boolean);
var tne: TNotifyEvent;
begin
    if Enable then
       tne:= SetPropertiesChanged
    else
       tne:= nil;

    //--- Set all OnChange/OnClick event handlers
    editName.OnChange:= tne;
    editCommandLine.OnChange:= tne;
    checkEnabled.OnClick:= tne;
    editComments.OnChange:= tne;
    comboShowWindow.OnChange:= tne;
    comboLocation.OnChange:= tne;
end;

Und wenn du jetzt z.B. für editName noch prüfen willst, ob .text<>'' ist, dann brauchst du doch auch einen eigene Behandlungsroutine.

idefix2 18. Mai 2015 13:59

AW: Windows Message bei Änderung?
 
Die Prüfung mache ich eben für das eine Feld auch in der zentralen Routine:

Zitat:

Zitat von Dalai (Beitrag 1301948)
Delphi-Quellcode:
procedure TForm1.SetPropertiesChanged(Sender: TObject);
begin
    btnApply.Enabled:= True;
    if Sender = comboLocation then
        checkCopyStartup.Enabled:= True;
end;
Für diese eine Komponente (ComboBox) gibt's in der Ereignisbehandlung zusätzlich eine Besonderheit.

Nachdem spezielle OnChange-Behandlungen eher selten nötig sein werden, ist die Einschränkung nicht wirklich wichtig. Gültigkeitsprüfungen gehören ja zum Beispiel meiner Meinung nach ins OnExit und nicht ins OnChange.

Dalai 18. Mai 2015 13:59

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von Captnemo (Beitrag 1301956)
Und wenn du jetzt z.B. für editName noch prüfen willst, ob .text<>'' ist, dann brauchst du doch auch einen eigene Behandlungsroutine.

Das erledigt die eigentliche Speicher-Routine, die beim Klick auf den Apply- oder OK-Button ausgelöst wird. Klar, könnte man auch im OnChange-Ereignis machen. Ich hab lieber alles zentral, so dass vor dem Speichern die Eingaben geprüft werden.

MfG Dalai

PS: Die Prüfung auf leeren String hab ich ganz vergessen in meiner Anwendung. Danke für den Hinweis :).

idefix2 18. Mai 2015 14:09

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von Captnemo (Beitrag 1301955)
Zitat:

Zitat von idefix2 (Beitrag 1301952)
Aus Erfahrung weiss ich, dass jeder Eintrag, den man jedesmal erneut von Hand machen muss, irgendwann bei einer Programmänderung vergessen wird.

Ich gehe mal davon aus, dass du deine Eingabecontrols auf der Form selbst setzt. Dann musst du doch sowieso "Hand" anlegen, um z.B. das Control auszurichten, bestimmte Eigenschaften zu setzen, usw. Was spricht dagegen, im dann auch im OnClick oder im OnChange auf Veränderung zu prüfen.

Genau der Satz, den du von mir zitiert hast, spricht dagegen. Ein falsche Ausrichtung des Controls sehe ich auf den ersten Blick, wenn ich die Form öffne. Schon eine falsche Tab-Reihenfolge eines irgendwo in der Mitte eingefügten Eingabefelds ist für den User mühsam und passiert immer wieder, wenn der Programmierer beim Testen des Programms vorwiegend mit der Maus arbeitet. Und dass die Zuordnung von onchange vergessen worden ist, kann beim Testen des Programms noch leichter übersehen werden als eine falsche Tab-Reihenfolge.

Jumpy 18. Mai 2015 14:29

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von idefix2 (Beitrag 1301957)
Die Prüfung mache ich eben für das eine Feld auch in der zentralen Routine:

Zitat:

Zitat von Dalai (Beitrag 1301948)
Delphi-Quellcode:
procedure TForm1.SetPropertiesChanged(Sender: TObject);
begin
    btnApply.Enabled:= True;
    if Sender = comboLocation then
        checkCopyStartup.Enabled:= True;
end;
Für diese eine Komponente (ComboBox) gibt's in der Ereignisbehandlung zusätzlich eine Besonderheit.

Nachdem spezielle OnChange-Behandlungen eher selten nötig sein werden, ist die Einschränkung nicht wirklich wichtig. Gültigkeitsprüfungen gehören ja zum Beispiel meiner Meinung nach ins OnExit und nicht ins OnChange.

Eine Alternative könnte natürlich auch sein, dass beim Zuweisen der OnChange-Routine zur Laufzeit erstmal geprüft wird, ob EditXYZ schon eine eigene OnChange-Routine hat. Dann wird diesem Edit die globale OnChange halt nicht zugewiesen.
Dann muss man natürlich bedenken, in der speziellen OnChange-Routine der Edits auch das zu machen, was auch die globale Routine macht. Am einfachtsen in dem in beiden Fällen eine "normale" (nicht Event bezogene) Prozedur aufgerufen wird, die den eigentlichen Code enthält.


Eventuell kann man sich das Leben aber auch evtl. einfacher machen, wenn man mit Actions arbeitet, da das OnUpdate(?)-Ereignis der Actions doch alle Nase lang gefeuert wird.

idefix2 18. Mai 2015 15:07

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von Jumpy (Beitrag 1301966)
Eine Alternative könnte natürlich auch sein, dass beim Zuweisen der OnChange-Routine zur Laufzeit erstmal geprüft wird, ob EditXYZ schon eine eigene OnChange-Routine hat. Dann wird diesem Edit die globale OnChange halt nicht zugewiesen.
Dann muss man natürlich bedenken, in der speziellen OnChange-Routine der Edits auch das zu machen, was auch die globale Routine macht. Am einfachtsen in dem in beiden Fällen eine "normale" (nicht Event bezogene) Prozedur aufgerufen wird, die den eigentlichen Code enthält.

Ja, so ginge es auch - aber:
Die Programme sind wesentlich länger im Einsatz, als ich mich an den Code, den ich "damals" verbrochen habe, erinnern würde - und gar erst, wenn irgendwann ein anderer Programmierer Änderungen in dem Code machen muss. Der baut dann in ein Feld eine OnChange Behandlung ein und wundert sich, warum plötzlich der "Speichern"-Button nicht mehr aktiviert wird, obwohl das Feld geändert worden ist (oder noch schlechter, der Kunde wundert sich, nachdem das Update eingespielt worden ist). Wenn ich separate OnChange Routinen einfach verbiete, verlange, dass OnChange Behandlungen nur in der zentralen Routine erfolgen dürfen (wenn "sender" den entsprechenden Wert hat) und eine verständliche Warnung/Fehlermeldung ausgebe, wenn die Form beim Programmstart auf eine Komponente stösst, bei der schon im OI eine OnChangeBehandlung eingegeben wurde, dann entschärft das das Problem.

Zitat:

Zitat von Jumpy (Beitrag 1301966)
Eventuell kann man sich das Leben aber auch evtl. einfacher machen, wenn man mit Actions arbeitet, da das OnUpdate(?)-Ereignis der Actions doch alle Nase lang gefeuert wird.

Ja, so könnte ich mir auch meinen Timer sparen. Statt an die Timer Routine könnte ich die Überprüfung an die OnUpdate Routine der entsprechenden Actions hängen. Aber der Ansatz von Dalai gefällt mir noch besser.

Captnemo 18. Mai 2015 15:16

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von idefix2 (Beitrag 1301959)
Zitat:

Zitat von Captnemo (Beitrag 1301955)
Zitat:

Zitat von idefix2 (Beitrag 1301952)
Aus Erfahrung weiss ich, dass jeder Eintrag, den man jedesmal erneut von Hand machen muss, irgendwann bei einer Programmänderung vergessen wird.

Ich gehe mal davon aus, dass du deine Eingabecontrols auf der Form selbst setzt. Dann musst du doch sowieso "Hand" anlegen, um z.B. das Control auszurichten, bestimmte Eigenschaften zu setzen, usw. Was spricht dagegen, im dann auch im OnClick oder im OnChange auf Veränderung zu prüfen.

Genau der Satz, den du von mir zitiert hast, spricht dagegen.

Aha. Dann verneige ich mich ehrfürchtig und bin raus.

Popov 18. Mai 2015 15:56

AW: Windows Message bei Änderung?
 
Ich habe mich gerade an meine Routine für Faule erinnert. Damals habe ich just4fun eine Funktion geschrieben mit der es möglich war alle Einstellungen auf dem Formular in eine Ini zu speichern/daraus zu laden, ohne die einzelnen Komponenten in eine Speiche- oder Ladeliste eintragen zu müssen. Ich hab einfach alles gespeichert und geladen.

Die Routine finde ich jetzt nicht mehr, aber das Prinzip ist einfach und evtl. auf dein Problem anwendbar. In einer Durchgang wird aus allen Inhalten aller Komponenten auf dem Formular eine Checksumme gebildet. Unterscheidet sie sich zu der vorherigen, gibt es eine Änderung.

Das spezielle an der Routine ist, dass in die Routine nur einmal der Komponententyp aufgenommen werden muss, z. B. TEdit. Danach werden automatisch alle TEdits erfasst, auch solche die neu dazukommen.

Ich hab das hier mit einer Checksumme gemacht, man kann es auch anders machen. Wichtig ist nur, dass so alle Komponenten überprüft werden.

Delphi-Quellcode:
function ChecksumStr(s: string): Integer;
begin
  Result := -1; //Hier aus einem String eine Checksumme bilden
end;

function ChecksumInt(i: Integer): Integer;
begin
  Result := -1; //Hier aus einem Integer eine Checksumme bilden
end;

function ChecksumBool(b: Boolean): Integer;
begin
  Result := -1; //Hier aus einem Boolean eine Checksumme bilden
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  i, ChkSum: Integer;
begin
  ChkSum := 0;

  for i := 0 to ComponentCount - 1 do
  begin
    if Components[i].ClassType = TEdit then
      ChkSum := ChkSum + ChecksumStr(TEdit(Components[i]).Text);

    if Components[i].ClassType = TComboBox then
      ChkSum := ChkSum + ChecksumInt(TComboBox(Components[i]).ItemIndex);

    if Components[i].ClassType = TCheckBox then
      ChkSum := ChkSum + ChecksumBool(TCheckBox(Components[i]).Checked);

    if Components[i].ClassType = TRadioButton then
      ChkSum := ChkSum + ChecksumBool(TRadioButton(Components[i]).Checked);
  end;

  //Hier dann die CheckSumme auf Änderung prüfen
  ShowMessage(IntToStr(ChkSum));
end;
Achso, die Funktionen für Checksummen müssten selbst programmiert werden.

idefix2 18. Mai 2015 16:25

AW: Windows Message bei Änderung?
 
Genau nach diesem Prinzip arbeitet meine Routine zum Erkennen einer Änderung.
Wenn die Daten in das Formular geladen werden, werden die Werte aller Komponenten des Formulars in so einer Schleife durchlaufen und in einer Stringlist abgelegt.
Die Routine, die auf Änderungen prüft, vergleicht die aktuellen Werte der Controls mit denen in der Liste.

Popov 18. Mai 2015 16:56

AW: Windows Message bei Änderung?
 
Wie gesagt, hier werden nicht alle Komponenten in eine Liste eingetragen, nur die Klassen-Typen.

Aber um auf dein Problem nochmal einzugehen, wenn man kompliziert genug denkt und noch komplizierter programmiert, könnte man vielleicht etwas fabrizieren. Das Ergebnis wäre eine komplexe Routine. Am Ende würde man sich aber fragen wieso man nicht einfach bei jeder Komponente in der OnChange Prozedur ein globales Modifed auf True gesetzt hat.

Aber ich möchte noch mal zu meiner Geschichte mit den Flugzeugen zurück kommen. Bist du sicher sie verstanden zu haben? Da geht es drum sich in einer Idee zu verlieren ohne den Blick für andere Lösungen zu haben.

In deinem Fall stellt sich die Frage ob es wirklich nötig ist, dass der Speichern Button erst bei einer Änderung aktiv wird. Wäre es schlimm wenn der Button immer Aktiv wäre? Und wenn es wichtig ist, ist die Anzahl der Komponenten so groß, dass es zu aufwändig ist bei jeder Komponente zu reagieren und ein Modifed-Wert zu setzten?

Ansonsten empfehle ich dir das Demo Programm (Delphi-Ordner) ReichEdit anzugucken. Da wird auch viel auf Änderungen reagiert. Guckt mir mal an wie die mit Modifed umgehen.

idefix2 18. Mai 2015 17:17

AW: Windows Message bei Änderung?
 
Zitat:

Zitat von Popov (Beitrag 1301984)
In deinem Fall stellt sich die Frage ob es wirklich nötig ist, dass der Speichern Button erst bei einer Änderung aktiv wird. Wäre es schlimm wenn der Button immer Aktiv wäre? Und wenn es wichtig ist, ist die Anzahl der Komponenten so groß, dass es zu aufwändig ist bei jeder Komponente zu reagieren und ein Modifed-Wert zu setzten?

Was ist schon NÖTIG, und was ist WICHTIG?
Das User-Interface gewinnt durch diese Feature sicher ein wenig an Attraktivität, unbedingt nötig wäre es natürlich nicht.
Es geht nicht darum, ob es zu aufwändig wäre, bei jeder Komponente zu reagieren, sondern darum, dass alles, was man routinemässig manuell irgendwo eintragen muss, eine potentielle zukünftige Fehlerquelle ist. Und besonders lästig sind Fehlerquellen dann, wenn sie beim Testen des Programms nicht zwangsläufig sofort auffallen, sondern wenn dann erst nach Auslieferung an den Kunden eine Reklamation kommt. Dann erweist sich der ursprüngliche Gewinn für das User-Interface nämlich als Eigentor.
Deshalb würde ich auf die Feature (die ich durchaus als Gewinn ansehe) eher verzichten und den Speichern Knopf immer aktiv lassen, wenn es nicht Möglichkeiten geben würde, sicherzustellen, dass auch bei zukünftigen Programmänderungen in dem Bereich keine (unnötigen) Fehler entstehen können, weil der Programmierer, der die Änderungen macht (ich selbst oder ein Mitarbeiter) übersieht, dass bei jedem neuen Control die OnChange Routine zugeordnet werden muss, weil sonst die Aktivierung des Speichern-Buttons nicht mehr richtig funktioniert. Wenn ich nach drei Jahren an dem Programm eine kleine Änderung machen soll, denke ich unter Umständen selbst auch nicht mehr daran, und schon gar nicht, wenn ich einen Mitarbeiter mit der Trivialaufgabe betraue, er soll in ein Formular der Anwendung zwei neue Datenfelder einbauen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:18 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz