Autor Beitrag
Fienix
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109

Win 2K, Win XP Pro, Win 7
D 5 Pro., D 7 Ent., D 2010 Pro.
BeitragVerfasst: Di 19.11.19 11:13 
Hallo,

ich hab eine kleines Problem, dass anscheinend eher ein Delphi-Bug zu sein scheint.

Ich hab ein Dataset-Field mit einer OnValidate Prüfung.

wenn ich den Button direkt anklicke, kommt die Exception und ich komme auch nicht weiter.

wenn ich Button.OnClick über TAction über einen ShortCut auslöse, kommt die Exception aber der Dialog schließt sich auch.

Hab ich einen Denkfehler oder ein Bug?

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, Grids, DBGrids, StdCtrls, DBClient, Mask, DBCtrls, ActnList;

type
  TForm3 = class(TForm)
    dataset: TClientDataSet;
    dbgrd: TDBGrid;
    ds: TDataSource;
    dbedtDate: TDBEdit;
    actlst: TActionList;
    actFertig: TAction;
    btnEinfuege: TButton;
    btnok: TButton;
    procedure FormCreate(Sender: TObject);
    procedure actFertigExecute(Sender: TObject);
    procedure btnEinfuegeClick(Sender: TObject);
    procedure btnokClick(Sender: TObject);
  private
    procedure DoValidate(Sender: TField);
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form3: TForm3;

implementation

uses DateUtils;

{$R *.dfm}

procedure TForm3.actFertigExecute(Sender: TObject);
begin
  if (self.btnok.enabled) and (self.btnok.visible) then
  begin
    btnOK.setfocus;
    btnOKClick(nil);
  end;
end;

procedure TForm3.btnEinfuegeClick(Sender: TObject);
begin
  dataset.Append;

  dataset.FieldByName('Field1').Value := 'Artikel ' + IntToStr(dataset.Recordcount + 1);
  dataset.FieldByName('Field2').Value := date;
  dataset.FieldByName('Field3').Value := FormatDatetime('dd.mm.yyyy hh-mm-ss-zzz', now);
  dataset.Post;
end;

procedure TForm3.btnokClick(Sender: TObject);
begin
  Modalresult := mrOk;
end;

procedure TForm3.DoValidate(Sender: TField);
begin
  if DaysBetween(date, sender.asDatetime) > 7
    then raise Exception.Create('Zu alt');
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
  dataset.CreateDataSet;
  dataset.FieldByName('Field2').OnValidate := DoValidate;
end;

end.



Im Anhang eine keines Beispiel, damit es leichter nachzuvollziehen ist.



Danke im voraus.
Einloggen, um Attachments anzusehen!
_________________
Wer sichert ist feige!!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 19.11.19 12:22 
Das liegt daran, dass du in der Action mit dem Setzen des Fokus die Prüfung auslöst, die OnValidate-Exception dabei abgefangen und dann danach der btnOKClick durchgeführt wird. Deshalb wird dabei das ModalResult wirklich gesetzt und das Fenster geschlossen.

Drückst du auf den Knopf, tritt das Problem auch beim Fokuswechsel auf, aber durch den Fehler wird der Klick, sprich die Methode btnokClick, gar nicht mehr ausgeführt.
Fienix Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109

Win 2K, Win XP Pro, Win 7
D 5 Pro., D 7 Ent., D 2010 Pro.
BeitragVerfasst: Di 19.11.19 12:33 
Die Exception wird doch nicht abgefangen!

Es wird eine Exception ausgelöst und das Programm läuft trotzdem normal weiter?

_________________
Wer sichert ist feige!!
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6386
Erhaltene Danke: 146

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Di 19.11.19 12:38 
Sebastian hat ja schon was zu dem Problem geschrieben.
OnValidate wird ausgelöst, wenn das Feld aktualisiert wird. Das passiert beim Speichern des Datensatzes oder wenn das Eingabefeld den Focus verlieren soll (nicht verliert). Das OnValidate sorgt dafür, dass der Fokus bleibt. Du setzt ihn aber manuell um und bekommst dein Problem.

user profile iconFienix hat folgendes geschrieben Zum zitierten Posting springen:

Hab ich einen Denkfehler oder ein Bug?

Es liegt ein konzeptioneller Fehler vor.
Wenn du TAction nutzt, dann weise die Action auch dem Button zu (im Objektinspektor). Das OnClick des Button dann bitte löschen und den entsprechenden Source ins OnExecute der Action verschieben. Ansonsten weißt du irgendwann nicht mehr, was du wo machst.
Außerdem hat TAction auch ein OnUpdate. Damit kannst du z.B. steuern, ob der Button enabled ist.

Da das OnValidate nur in den oben genannten Situationen reagiert, habe ich mich schon lange davon verabschiedet, bzw. eigentlich nich genutzt. Den Aufwand den man dafür treiben muss, damit es an den richtigen Stellen auch reagiert, war mir zu umständlich.
Die Prüfung muss sowieso gemacht werden. In deinem Beispiel kann man die Prüfung einfach auf die Action für den Button verlagern. Wenn das Datum ungültig ist, setzt du den Fokus wieder auf das Eingabefeld, machst ein ShowMessage und setzt keinen ModalResult.
Vorteil: Du hast die volle Kontrolle an der gewünschten Stelle.
Nachteil: Bei vielen Feldern, die geprüft werden müssen, wird der Anwender erst gewarnt, wenn schon viele Felder ausgefüllt sind. Das ist aber durchaus eine übliche Vorgehensweise.
Fienix Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109

Win 2K, Win XP Pro, Win 7
D 5 Pro., D 7 Ent., D 2010 Pro.
BeitragVerfasst: Di 19.11.19 12:58 
Das funktioniert aber noch weniger.

Wenn die Action dem Button zugewiesen wird, wird ja überhaupt nix mehr geprüft,
deswegen wird ja der Focus explizit auf den Button gesetzt, um die Exception auszulösen.

bei dem SetFocus wird die Exception ausgelöst, ist auch richtig, aber warum läuft das Programm weiter?

_________________
Wer sichert ist feige!!
Fienix Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109

Win 2K, Win XP Pro, Win 7
D 5 Pro., D 7 Ent., D 2010 Pro.
BeitragVerfasst: Di 19.11.19 13:57 
grundsätzlich ist das Problem nicht bei der TAction.
sondern beim SetFocus , anscheinend wird hier die Exception abgefangen :(

hier tritt das gleiche Problem auf:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure TForm3.btnCloseClick(Sender: TObject);
begin
  if (self.btnok.enabled) and (self.btnok.visible) then
  begin
    btnOK.setfocus;
    btnOKClick(nil);
  end;
end;

_________________
Wer sichert ist feige!!
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6386
Erhaltene Danke: 146

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Di 19.11.19 14:20 
user profile iconFienix hat folgendes geschrieben Zum zitierten Posting springen:
Das funktioniert aber noch weniger.

Weil du konzeptionell falsch damit arbeitest. Das hatte ich versucht oben zu erläutern. Man muss sich entscheiden, ob man TAction verwendet oder nicht. Aber wenn man es nutzt, muss man konsequent sein.
user profile iconFienix hat folgendes geschrieben Zum zitierten Posting springen:
Wenn die Action dem Button zugewiesen wird, wird ja überhaupt nix mehr geprüft,

Richtig, aber wie schon geschrieben, ist dein Konzept nicht in Ordnung.
user profile iconFienix hat folgendes geschrieben Zum zitierten Posting springen:
deswegen wird ja der Focus explizit auf den Button gesetzt, um die Exception auszulösen.

OnValidate prüft den Wert, wenn man das DataSet-Feld (nicht das Eingabefeld) verlässt oder ein Post macht. Das hat zu dem Zeitpunkt nichts mit der fokussierten Eingabe-Komponente zu tun. Daher macht dein SetFocus im Source einen Wechsel zum Button und dir geht die Kontrolle darüber verloren. Der Fokus-Wechsel durch Auswahl mit der Maus läuft etwas anders.
user profile iconFienix hat folgendes geschrieben Zum zitierten Posting springen:
bei dem SetFocus wird die Exception ausgelöst, ist auch richtig, aber warum läuft das Programm weiter?

Weil der Fokus durch deinen Source verändert wird und nicht durch das Event.

Mit OnValidate hat man immer diese Probleme. Deswegen nutze ich es nicht und kontrolliere die Daten z.B. vor einem DataSet.Post.
Es gibt da so eine nettes Ereignis (BeforePost) beim DataSet. Das eignet sich in den meisten Fällen ganz gut. Alternativ kann man das auch in einer Action machen, bevor man das Post auslöst.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 20.11.19 07:18 
user profile iconFienix hat folgendes geschrieben Zum zitierten Posting springen:
grundsätzlich ist das Problem nicht bei der TAction.
sondern beim SetFocus , anscheinend wird hier die Exception abgefangen :(
Da liegt daran, dass die Nachricht WM_SETFOCUS vom System kommt und daher die Exception auch in diese Richtung geschickt wird und nicht "zu dir".
Fienix Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109

Win 2K, Win XP Pro, Win 7
D 5 Pro., D 7 Ent., D 2010 Pro.
BeitragVerfasst: Mi 20.11.19 10:12 
Ich habs jetzt soweit verstanden, denk ich.
Und das passende Event hab ich auch gefunden:

ds.dataset.UpdateRecord;

damit hab ich genau das richtige um den Ablauf nicht komplett überarbeiten zu müssen:


ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure TForm3.actFertigExecute(Sender: TObject);
begin
  if (self.btnok.enabled) and (self.btnok.visible) then
  begin
    ds.dataset.UpdateRecord;
    btnOK.setfocus;
    btnOKClick(nil);
  end;
end;


:beer:
Danke euch für die Hilfe!

_________________
Wer sichert ist feige!!
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6386
Erhaltene Danke: 146

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Mi 20.11.19 13:28 
Gern geschehen.
Dennoch solltest du dein Konzept überdenken, wie du mit TAction arbeitest.