Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Form Automatsch öffnen, wenn ein User es möchte! (https://www.delphipraxis.net/188-form-automatsch-oeffnen-wenn-ein-user-es-moechte.html)

m-werk 17. Jun 2002 21:11


Form Automatsch öffnen, wenn ein User es möchte!
 
Hi Leute, so nun hab ich ein Problem beseitigt, schon ist das nächste da. Dies ist aber (glaub ich jedenfalls) das letzte, was ich noch habe.

Ich habe folgendes vor.
Ich habe eine Form (ExtraForm) wo ich die Geburtstagskinder sehe, die von heute an bis hin in einer Woche, Geburtstag haben.
Das mit dem Filtern von den Geburtstagskindern funktioniert einwandfrei.

Folgendes. Ich habe in der ExtraForm eine Checkbox eingebaut. Wenn ein User diese Checkbox aktiviert, dann öffnet sich die Form automatisch beim start. Wenn er sie nicht aktiviert, kann er über einen Button auf die form Zugreifen.

Der Wert von der checkbox wird in eine INI-Datei geschrieben

So sieht der code in der Hautpform aus:
Im Puplic Teil meiner Hauptform habe ich folgenden code:

Code:
public
     { Public-Deklarationen }
  procedure save_inifile;
  procedure load_inifile;
  end;
Weiters stehen die save_inifile und die load_inifile auch in der Hauptform:

Code:
procedure TKundendaten.save_inifile;
begin
  try
    Ini:=TIniFile.Create(ExtractFilePath(Application.ExeName)+'settings.ini' );
    Ini.WriteBool('Sektion1','check_box',ExtraForm.CheckBox1.Checked);
  finally
    Ini.Free;
  end;
end;
Code:
procedure TKundendaten.load_inifile;
begin
  try
    Ini:=TIniFile.Create(ExtractFilePath(Application.ExeName)+'settings.ini' );
    ExtraForm.CheckBox1.Checked:=ini.ReadBool('Sektion1','check_box', true)
  finally
    Ini.Free;
  end;
end;
Und
Code:
procedure TKundendaten.FormShow(Sender: TObject);
begin
  load_inifile;
  if ExtraForm.CheckBox1.Checked Then Geburtsdatum.Click;
end;
In der ExtraForm habe ich folgendes in die Procedure von der Checkbox stehen:

Code:
procedure TExtraForm.CheckBox1Click(Sender: TObject);
begin
  Kundendaten.save_inifile;
end;
Soweit sogut. Wenn ich die Checkbox aktiviere, bekomme ich folgende Fehlermeldung:
Zugriffsverletzung bei Adresse 00383638. Lesen von Adresse 00383638

Was kann ich da noch machen?
PS: Ich muß bei der Hautpform beim FormShow auf die Geburtstag.Click gehen, da dieser Button einen code zum filtern beinhaltet.
Ich hab auch schon probiert anstelle von FormShow diese Procedure bei onActivate auszuführen, aber da habe ich eine andere fehlermelung. Diese ist mit onShow weg.

Kann mir jemand helfen?

jbg 17. Jun 2002 21:42

Rufst du load_inifile noch wo anders auf?

Schau mal im Menü Projekt - Optionen... im Register "Formulare" nach, auf welcher Seite sich dein ExtraForm befindet. Wenn es rechts ist, dann schiebe es nach links.

m-werk 17. Jun 2002 21:45

Hi, die procedure load_inifile rufe ich sonst niergenst auf und ExtraForm ist auf der rechten Seite

Daniel B 17. Jun 2002 21:46

Hi,

schreib die Tini.Create, vor das try

Grüsse, Daniel :)

jbg 17. Jun 2002 21:48

Zitat:

Zitat von m-werk
... und ExtraForm ist auf der rechten Seite

Da haben wir das Problem. Da ExtraForm auf der Seite der "verfügbaren Formulare" ist, wird es beim Start nicht erzeugt. Dadurch zeigt die Variable (Zeiger) ExtraForm ins leere und ein Zugriff auf ExtraForm.CheckBox1 erzeugt eine Schutzverletzung. Du musst ExtraForm zu den Formularen hinzufügen, die Automatisch erzeugt werden.

m-werk 17. Jun 2002 21:48

Hab ich gemacht, nützt aber nichts!

Noch was ist mir aufgefallen:

Normalerweise schreibt man das ja so:

Code:
Procedure TKundendaten.load_inifile;
var
Ini: TIniFile;
begin
............
end;
Ich bekomme, wenn ich die Variable TIniFile so schreibe bei beiden Codes folgenden hinweis:

[Warnung] Hauptmenue.pas(431): Variable 'Ini' ist möglicherweise nicht initialisiert worden

Ich hab dann das so gemacht:
Code:
......
var
  Ini: TIniFile;
  Kundendaten: TKundendaten;

implementation
.......
Kann es daran liegen? (Ich glaube nicht)

jbg 17. Jun 2002 21:59

Dazu: Schau dir einmal das Posting von Daniel B an, da steht, was du machen musst, um diesen Hinweis zu "beseitigen".

Zu deinem Problem:
Setze mal den Cursor in die Zeile mit
ExtraForm.CheckBox1.Checked:=ini.ReadBool('Sektion 1','check_box', true)
und drücke dann [F4]. Dein Programm müsste nach dem Starten nun an dieser Stelle anhalten. Sollte die Fehlermeldung aber davor erscheinen, dann liegt der Fehler wo anders.
Gehe nun mit der Mouse über das Wort ExtaForm. Sollte in dem erscheinenden Hint nil stehen, so ist ExtraForm an dieser Stelle noch nicht erzeugt, was zur Schutzverletzung führt.
Sollte ExtraForm <> nil sein, dann drücke die [F8] Taste, um zu sehen, ob in dieser Zeile vielleicht doch eine AV (AccessViolation) auftritt. Mit F8 und F7 (bei Prozeduraufrufen) kannst du dein Programm jetzt Zeile für Zeile durchgehen, bis du den Fehler gefunden hast.

jbg 17. Jun 2002 22:03

Da fällt mir noch ein, dass man auch bei Warnungen und Fehlermeldungen von der OnlineHilfe unterstützt wird. Meist sogar mit Beispielen, die einem den Fehler aufzeigen. Einfach die Fehlermeldung anlicken und F1 drücken.

m-werk 17. Jun 2002 22:07

hab ich gemacht, es kommt zuerst keine Fehlermeldung. Wenn ich mit dem Cursor über das Wort ExtraForm gehe, dann kommt ein gelbes fenster, da steht ein langer code drinn. Wenn ich dann F8 drücke, dann ist die Zeile ini.free; blau. Wenn ich nochmals F8 drücke, dann kommt die Fehlermeldung.

Daniel B 17. Jun 2002 22:12

Hi,

das lässt "vorübergehen" unterdrücken, indem du die Zeile ini.Free; Komentierst. müsste danach auch alles gehen. Ist abe rnicht sinn und zweck der Sache.
Eigentlich kann man es durch das schreiben von Create vor das Try, beheben. *verwirrtsei* Hab mal das gleiche Prb. gehabt. Kann nur z.Z. nicht nachschauen. *grrr*
Probier das mal aus.

Grüsse, Daniel :)

jbg 17. Jun 2002 22:13

Schreib einmal die Methode load_inifile so um:
Code:
procedure TKundendaten.load_inifile;
begin
  Ini:=TIniFile.Create(ExtractFilePath(Application.ExeName)+'settings.ini' );
  try
    ExtraForm.CheckBox1.Checked:=ini.ReadBool('Sektion1','check_box', true)
    ShowModal('Juhu, ich bin bis hierher gekommen');
  finally
    Ini.Free;
  end;
end;
Und starte dann das Programm über F9. Wenn keine Meldung erscheint, dann wissen wir zumindest genau, dass ExtraForm.Che... daran schuld ist.

m-werk 17. Jun 2002 22:17

Ich hab jetzt was anderes probiert:

Code:
procedure TKundendaten.save_inifile;
var
Ini : TIniFile;
begin
  Ini:=TIniFile.Create(ExtractFilePath(Application.ExeName)+'settings.ini' );
  try
    Ini.WriteBool('Sektion1','check_box',ExtraForm.CheckBox1.Checked);
  finally
    Ini.Free;
  end;
end;

procedure TKundendaten.load_inifile;
var
Ini : TIniFile;
begin
  Ini:=TIniFile.Create(ExtractFilePath(Application.ExeName)+'settings.ini' );
  try
    ExtraForm.CheckBox1.Checked:=ini.ReadBool('Sektion1','check_box', true)
  finally
    Ini.Free;
  end;
end;
und oben vor der implementation habe ich Ini:TIniFile herausgenommen.

Jetzt kommt zwar keine Fehlermeldung mehr aber die ExtraForm öffnet sich auch nicht!

thomasdrewermann 17. Jun 2002 22:20

Versuch mal TRY-EXCEPT-FINALLY wegzulassen....
Du hast die INI-DATEI global deklariert?
Deklarier sie doch einfach mal local...
Genauso mit
Code:
Kundendaten: TKundendaten;
versuch damit auch mal global.

Code:
public
    { Public-Deklarationen }
  procedure save_inifile;
  procedure load_inifile;
end;

var
  Kundendaten: TKundendaten;

Code:
procedure TKundendaten.save_inifile;
var
  ini:tinifile;
begin
  Ini:=TIniFile.Create(ExtractFilePath(Application.ExeName)+'settings.ini' );
  Ini.WriteBool('Sektion1','check_box',ExtraForm.CheckBox1.Checked);
  Ini.Free;
end;

procedure TKundendaten.load_inifile;
var
  ini:tinifle;
begin
  Ini:=TIniFile.Create(ExtractFilePath(Application.ExeName)+'settings.ini' );
  ExtraForm.CheckBox1.Checked:=ini.ReadBool('Sektion1','check_box', true)
  Ini.Free;
end;

procedure TKundendaten.FormShow(Sender: TObject);
begin
  load_inifile;
  if ExtraForm.CheckBox1.Checked Then Geburtsdatum.Click;
end;
Code:
procedure TExtraForm.CheckBox1Click(Sender: TObject);
begin
  Kundendaten.save_inifile;
end;

jbg 17. Jun 2002 22:23

Zitat:

Zitat von m-werk
... aber die ExtraForm öffnet sich auch nicht!

Das liegt vielleicht daran, dass du sie auch nicht anzeigst. Nur das Setzen der CheckBox ruft noch lange nicht ShowModal bzw. Show auf. Das musst du irgendwo einbauen (z.B. im Ereignis OnClick der CheckBox).

m-werk 17. Jun 2002 22:26

Hi, hab ich alles schon probiert, es kommt jetzt zwar keine Fehlermeldung, aber die ExtraForm wird nicht geöffnet, obwohl die Checkbox in der ExtraForm aktiviert ist!

jbg 17. Jun 2002 22:39

Poste mal den Code in Ereignis OnClick von Button Geburtsdatum.

MrSpock 18. Jun 2002 07:11

Hallo m-werk,

dein Code, der ganz oben steht ist OK. Das Ini.Create vor den try ... finally Block zu setzen ist eigentlich nicht gut, weil auch diese Anweisung grundsätzlich zu einem Fehler führen könnte. Du schreibst oben:

Zitat:

Soweit sogut. Wenn ich die Checkbox aktiviere, bekomme ich folgende Fehlermeldung:
Zugriffsverletzung bei Adresse 00383638. Lesen von Adresse 00383638
Das heißt doch, das der Fehler beim Code liegt, der beim Anklicken der CheckBox ausgeführt wird. Kannst du den bitte einmal posten?

m-werk 18. Jun 2002 08:11

So sieht der Code beim Button Geburtsdatum aus:

Code:
procedure TKundendaten.GeburtsdatumClick(Sender: TObject);
var i,r:Integer;
begin
  r:=DM.ADOSHaupt.RecNo;
for i:=1 to DM.ADOSHaupt.RecordCount do begin
  if (StrToDate(Copy(DM.ADOSHaupt.FieldByName('Geburtsdatum').AsString,0,6)+C opy(DateToStr(now+7),7,4))<=now+7)
  and (StrToDate(Copy(DM.ADOSHaupt.FieldByName('Geburtsdatum').AsString,0,6)+C opy(DateToStr(now),7,4))>now)
then begin
  DM.ADOSHaupt.RecNo:=i;
  DM.ADOSHaupt.Filtered:=true;
  ExtraForm.Show;
  Exit;
end
else DM.ADOSHaupt.RecNo:=r;
end;
end;

jbg 18. Jun 2002 10:15

Zitat:

Zitat von MrSpock
Das Ini.Create vor den try ... finally Block zu setzen ist eigentlich nicht gut, weil auch diese Anweisung grundsätzlich zu einem Fehler führen könnte.

So so. Und was macht dein finally-Block wenn Ini irgendwo hinzeigt? Der finally-Block soll ja nur die Resourcen freigeben, die auch reserviert wurde. Wenn TIniFile.Create fehlschlägt, dann wird auch keine Instanz erzeugt.
Selbst Borland macht es vor wie man es machen soll:
Code:
  FlippedList := TList.Create;
  try
    ...
    for Loop := 0 to ControlCount - 1 do with Controls[Loop] do
    begin
      FlippedList.Add(Controls[Loop]);
      Left := TheWidth - Width - Left;
    end;
    ...
  finally
     FlippedList.Free;
  end;
Und so nebenbei wirft der Compiler bei deiner Programmierweise mit Create in den TRY-Block nur Warnungen aus. Die Lösung mit vorherigem setzen auf nil ist auch nicht gerade der schönste Programmierstil. (ich verweise an dieser Stelle auf den Object Pascal Style Guide)


@m-werk:
hast du auch überprüft, ob der Code zum wählen, ob der Dialog nun angezeigt werden soll, auch richtig arbeitet?

Was mir da z.B. aufgefallen ist:
(StrToDate(Copy(DM.ADOSHaupt.FieldByName('Geburtsd atum').AsString,0,6)
Was soll denn die Null bei Copy(). gehöhrt da nicht vielleicht eine 1 hin?

MrSpock 18. Jun 2002 10:34

Hallo jgb,

das tolle an Free is, dass es (im Gegensatz zu Destroy) auch bei Nil funktioniert. Das bedeutet, dass der Finally Teil immer funktioniert.

jbg 18. Jun 2002 10:37

Aber nur, wenn du vorher die Variable auf nil setzt, wenn sie nicht global oder in einer Klasse deklariert ist. Und selbst Borland sagt, dass das nicht gerade der schönste und übersichtlichste Programmierstil ist.

thomasdrewermann 18. Jun 2002 12:02

Teste mal:
Code:
procedure TKundendaten.FormCreate(Sender: TObject);
begin
  load_inifile;
  if ExtraForm.CheckBox1.Checked=true Then GeburtsdatumClick(sender);
end;

jbg 18. Jun 2002 12:23

Der Fehler liegt im Vergleich von Now mit dem zusammengesetzten Datum. Wenn er sein Programm genau um 0:00 Uhr startet, dann funktioniert es. Anstatt Now muss Date verwendet werden. Es sollten auch alle Datensätze durchlaufen werden, und nicht nur der aktuell ausgewählte.

Lösung:
Code:
procedure TKundendaten.GeburtsdatumClick(Sender: TObject);
var
  i, r: Integer;
  s: string;
begin
  r := DM.ADOSHaupt.RecNo;
  for i := 1 to DM.ADOSHaupt.RecordCount do
  begin
    DM.ADOSHaupt.RecNo := i;
    s := Copy(DM.ADOSHaupt.FieldByName('Geburtsdatum').AsString, 1, 6);
    if (StrToDate(s + Copy(DateToStr(Date + 7), 7, 4)) <= Date + 7) and
       (StrToDate(s + Copy(DateToStr(Date), 7, 4)) >= Date) then
    begin
      DM.ADOSHaupt.Filtered := True;
      ExtraForm.Show;
    end;
  end;
  DM.ADOSHaupt.RecNo := r;
end;

m-werk 19. Jun 2002 21:34

Hi, ich habe jetzt den Code vom Button so wie oben beschrieben eingebaut. Der Button funktioniert zwar, aber die ExtraForm öffnet sich noch immer nicht automatisch beim start.

Da wir ja gerade dabei sind, auch den Code vom Geburtstag zu ändern, zeige ich jetzt euch noch den Code, der in dem Datenmodul 'DM' steht, wo ich dann filtere:

Code:
procedure TDM.ADOSHauptFilterRecord(DataSet: TDataSet;                        
  var Accept: Boolean);
begin
if (StrToDate(Copy(ADOSHaupt.FieldByName('Geburtsdatum').AsString,0,6)+Copy(DateToStr(now),7,4))<=now+7)
and (StrToDate(Copy(ADOSHaupt.FieldByName('Geburtsdatum').AsString,0,6)+Copy(DateToStr(now),7,4))>now)
then Accept :=true
else Accept :=false;
end;
Was kann ich da nur noch tun?

jbg 19. Jun 2002 23:44

Nimm mal anstatt Now die Funktion Date. Und bessere auch gleich das Copy(..., 0, 6) in Copy(..., 1, 6) aus

m-werk 20. Jun 2002 12:29

Hi, werd ich heute abend mal probieren.

Was ist jetzt aber mit dem Geburtsdatum.Click oder GeburtsdatumClick(sender)

Ich werd mal probieren, diese procedure in onActivate hineinzustellen.
Ich habe aber fast die befürchtung, dass da dann, wenn die checkbox angewählt ist, wieder eine Meldung von Onhide und so kommen wird.

Ich habe es ja vorher auch bei onActivate gehabt. Da hat sich die Form automatisch beim start dann geöffnet. nur habe ich eine Meldung gehabt. So in der Art, dass die form im onhide nicht geändert werden kann.

Kann ich sonst anstelle von onShow und onActivte noch was anderes probieren?

jbg 20. Jun 2002 13:22

In OnActivate würde ich das in dem Fall nicht stecken: Lies mal dieses dazu. Aber es gibt noch OnShow.

m-werk 20. Jun 2002 15:32

Danke für die INFO. Genau solche Beschreibungen können jemanden weiterhelfen, der sich nicht richtig im Code-tschungel auskennt.

Aber trotzdem: das mit dem onShow hab ich ja immer gemacht. Da ist ja das problem. Ich bekomme die Form nicht automatisch beim Start auf. (siehe postings weiter oben).

jbg 20. Jun 2002 16:31

Ändere mal den Code in GeburtsdatumClick so um:
Code:
procedure TKundendaten.GeburtsdatumClick(Sender: TObject);
var
  i, r: Integer;
  s: string;
begin
  ExtraForm.Show;
  Exit;

  r := DM.ADOSHaupt.RecNo;
  for i := 1 to DM.ADOSHaupt.RecordCount do
  begin
    DM.ADOSHaupt.RecNo := i;
    s := Copy(DM.ADOSHaupt.FieldByName('Geburtsdatum').AsString, 1, 6);
    if (StrToDate(s + Copy(DateToStr(Date + 7), 7, 4)) <= Date + 7) and
       (StrToDate(s + Copy(DateToStr(Date), 7, 4)) >= Date) then
    begin
      DM.ADOSHaupt.Filtered := True;
      ExtraForm.Show;
    end;
  end;
  DM.ADOSHaupt.RecNo := r;
end;
Die Warnungen die der Compiler ausspuckt kannst du ignorieren.
Starte dein Programm. Wenn jetzt die ExtraForm angezeigt wird, dann stimmt etwas mit der if-Anweisung nicht, oder du hast keine Datensätze mit den passenden Geburtsdaten.

m-werk 21. Jun 2002 18:16

So, nun habe ich den Code umfunktioniert, so wie oben beschrieben.

Weiters habe ich im DataModul (DM) den Code beim Filtern auch umgeschrieben.

Code:
procedure TDM.ADOSHauptFilterRecord(DataSet: TDataSet; var Accept: Boolean);
begin
  if (StrToDate(Copy(ADOSHaupt.FieldByName('Geburtsdatum').AsString,1,6)+Copy(DateToStr(Date),7,4))<=Date+7)
  and (StrToDate(Copy(ADOSHaupt.FieldByName('Geburtsdatum').AsString,1,6)+Copy(DateToStr(Date),7,4))>Date)
  then Accept := true
  else Accept := false;
end;
Die ExtraForm öffnet sich aber noch immer nicht

Und wenn ich jetzt auf den Geburtstagsbutton klicke, sehe ich jetzt auf einmal ALLE Leute, egal ob diese in der Woche Geburtstag haben oder nicht. Das hängt jetzt mit dem ExtraForm.Show; Exit; zusammen. Wenn ich das weglasse, funktioniert es. Wenn ich es dazugebe, sehe ich alle Leute.

Warum lässt sich die ExtraForm nicht öffnen.
Langsam aber sicher verzweifle ich dabei noch!

Wie sieht es denn eigentlich aus, wenn man das mit der ExtraForm über die Registry löst?

PS: Ich habe gesehen, dass bei der ExtraForm 'Visible' auf false war. Dann habe ich es auf True gesetzt. Mit dieser Art habe ich dann kurz die ExtraForm gesehen aber dies hat auch nichts geholfen. So habe ich Visible wieder auf false gesetzt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:32 Uhr.

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