Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   ShowModal mit Programmablauf und selbst schließen? (https://www.delphipraxis.net/158991-showmodal-mit-programmablauf-und-selbst-schliessen.html)

HJay 10. Mär 2011 11:25

ShowModal mit Programmablauf und selbst schließen?
 
Ich komme mir selbst blöde vor, aber wie löst man folgende Aufgabe geradlinig:

Ich möchte eine TForm modal öffnen, dann dort SOFORT bestimmte Operationen (Datanbankzugriffe) ausführen, währenddessen den Fortschritt anzeigen und DANACH das modale Fenster auch gleich wieder selbst schließen.

Code:
TFormProgress.Show(Sender: TObject);
begin
  ShowMessage('start');
  // here some time-consiming operations
  Close; // ModalResult := mrOK;
  ShowMessage('after close');
end;
Beide ShowMessage werden ausgeführt, bevor das Fenster zu sehen ist und dann bleibt es sichtbar und schließt nicht. "Close" wird also ignoriert (ModalResult auch).

Wo plaziert man idealerweise Code, der beim Öffnen des modalen Fensters gleich ausgeführt werden soll, aber eben erst NACHDEM das Fenster sichtbar ist?

Wie kann man ein modales Fenster in diesem Falle wieder selbst schließen, sobald fertig?

OnPaint kann ich nicht verwenden, weil sich das Fenster für die Fortschrittsanzeige häufig neu zeichnet.

Ich hätte wirklich gerne ein modales Fenster, damit die Fertigstellung abgewartet werden muss.

Vielen Dank im voraus!

WM_CLOSE 10. Mär 2011 11:32

AW: ShowModal mit Programmablauf und selbst schließen?
 
versuch es so

Delphi-Quellcode:
type
  TMyForm=class(TForm)
  private
    ...
  public
    ...
    procedure ShowModal; override;
  end;

BUG 10. Mär 2011 11:38

AW: ShowModal mit Programmablauf und selbst schließen?
 
Du kannst dem Formular eine neue öffentliche Methode verpassen.

Delphi-Quellcode:
TFormProgress.showAndDoSomething: TModalResult;
begin
  show;
  doSomething;
  hide; // bzw. close;
  result := ModalResult;
end;
Die könntest du dann wie showModal einsetzen.
EDIT wegen roter Kasten: oder du überschreibst eben showModal damit.

dataspider 10. Mär 2011 11:41

AW: ShowModal mit Programmablauf und selbst schließen?
 
Hi,

ich mach es gern so:

Code:
unit frm_Modal;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TfrmModal = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    procedure AppIdle(Sender: TObject; var Done: Boolean);
  end;

var
  frmModal: TfrmModal;

implementation

{$R *.dfm}

procedure TfrmModal.FormCreate(Sender: TObject);
begin
  Application.OnIdle := AppIdle;
end;

procedure TfrmModal.AppIdle(Sender: TObject; var Done: Boolean);
begin
  Application.OnIdle := nil;
  // Mach was
  Close;
end;


end.
Frank

HJay 10. Mär 2011 11:46

AW: ShowModal mit Programmablauf und selbst schließen?
 
Zitat:

Zitat von WM_CLOSE (Beitrag 1087257)
versuch es so

Sorry, diesen Tipp verstehe ich nicht. Was soll ich dann in der neuen ShowModal-Prozedur machen?

Ich möchte
* die TFormProgress modal öffnen und sichtbar machen
* dann erst den Programmablauf starten
* nach Fertigstellung dann die modale Form wieder programmgesteuert schließen

SirThornberry 10. Mär 2011 11:46

AW: ShowModal mit Programmablauf und selbst schließen?
 
Ich hab das Gefühl alle Antworten gehen an der Frage vorbei.
Hier geht es doch darum ein Formular Modal anzuzeigen und darauf etwas darzustellen.
Warum öffnet man ein Formular modal? In der Regel um zu vermeiden das auf anderen Formularen rumgeklickt wird etc. währen auf dem Modal geöffnetem Fenster etwas passiert.
Ein Form also einfach nur mit Show anzuzeigen, darauf etwas zu machen und dann mit Hide wieder auszublenden deckt nicht das ab was man durch das modale Anzeigen erreichen will.

@HJay: Tröste dich, ich verstehe auch nicht wie der gepostete Source von wm_close dein Problem lösen soll. Durch überschreiben des ShowModal bewirkt man ja auch nur das mein eine neue Methode mit gleichem Namen an der Stelle platziert. Aber wie das gewünschte Vorhaben zu erreichen ist geht daraus für mich nicht hervor.

HJay 10. Mär 2011 11:57

AW: ShowModal mit Programmablauf und selbst schließen?
 
SirThornberry: Danke, das beruhigt mich etwas. Du hast das Problem exakt richtig dargestellt. Ich vermute einfach, dass ich nur zu blöde bin und es dafür eine einfache Standardlösung geben muss, weil dieses Problem doch sehr oft auftreten muss.

Meine Datenbanzugriffe benötigen etliche Sekunden, teilweise gar Minuten. Beim ersten Mal kann der User auch nichts anderes sinnvolles machen, als eben abzuwarten, bis die Daten zur Verfügung stehen. Schade, aber ist eben so.

Ich möchte die TProgressForm modal öffnen, damit der User warten muss und nicht auf der TMainForm herumclickt, also genau wie Du gesagt hast.

Das Fenster soll also aufgehen, den Fortschritt anzeigen und sich dann selbstätig wieder schließen. Das Hauptformular wartet derzeit darauf und macht dann weiter.

Wenn ich auf die modale Eigenschaft verzichte, geht das ganze natürlich mit

Delphi-Quellcode:
FormProgress.Show;
FormProgress.DoTheDeed;
aber dann wird weder automatisch auf DoTheDeed gewartet noch die Vorteile der Modalität genutzt.

Hoffentlich gibt es eine geradlinige Lösung... es gibt doch viele Programme, die ein Statusfenster anzeigen, während sie irgendwas machen... muss doch gehen!

HJay 10. Mär 2011 12:09

AW: ShowModal mit Programmablauf und selbst schließen?
 
Minimaler Fortschrtt: Wenn ich OnShow leer lasse und die Rechenroutine in OnActivate ausführe, dann ist das Formular wenigstens schon zu sehen und stellt den Fortschritt richtig da.

Allerdings schließt es sich immer noch nicht von alleine. Sowohl Close als auch ModalResult := mrOK in OnActiviate werden ignoriert, es bleibt einfach offen.

OnActivate ist also immer noch zu früh, um eigentlichen Programmcode auszuführen. Man müsste den Code erst starten, sobald das Fenster selbst "fertig" ist.

BUG 10. Mär 2011 12:13

AW: ShowModal mit Programmablauf und selbst schließen?
 
Zitat:

Zitat von HJay (Beitrag 1087281)
OnActivate ist also immer noch zu früh, um eigentlichen Programmcode auszuführen. Man müsste den Code erst starten, sobald das Fenster selbst "fertig" ist.

dataspiders Code sieht so aus, als könnte er das leisten.

alfold 10. Mär 2011 12:30

AW: ShowModal mit Programmablauf und selbst schließen?
 
Hier liegt die Anwort eigentlich schon auf der Hand.

Du solltest die VCL auch nur dafür nutzen für was sie da ist. Zu Anzeige eines Fortschrittes. und in Deiner Form1 für das schliessen sorgen! Wenn Du schon Form2 über Form1 mit Showmodal aufrufst!

z.B.

Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if form2.ProgressBar1.Position = 100 then form2.Close;
end;
und schon funktioniert alles

Gruss alfold

WM_CLOSE 10. Mär 2011 12:34

AW: ShowModal mit Programmablauf und selbst schließen?
 
OK das war mein Fehler, ich dachte man könnte das Laden (das was so lange dauert) im ShowModal machen.
Das mit dem OnIdle ist gar nicht schlecht.

HJay 10. Mär 2011 12:53

AW: ShowModal mit Programmablauf und selbst schließen?
 
Zitat:

Zitat von dataspider (Beitrag 1087269)
Hi, ich mach es gern so:

Hallo Frank, ja, das war die Lösung. Vielen Dank. Ich hatte sie nicht gleich verstanden, weil das globale Application-Objekt so eigenartig hier aussah, aber es ist logisch: In der modalen Form geht auch die gesamte Application in idle, wenn die Form fertig ist, sich zu zeichnen und nichts weiter passiert. Hoffentlich passt das wirklich exakt im strengen Sinne, also dass OnIdle niemals vorher aufgerufen werden kann.

Wie auch immer: Vielen Dank, es funktioniert und das sogar eigentlich genaugenommen sehr geradlinig. Toller Tipp!

Zitat:

Zitat von BUG (Beitrag 1087283)
dataspiders Code sieht so aus, als könnte er das leisten.

Ja, in der Tat. Danke noch mal für Deinen Hinweis, doch ein genaueres Auge darauf zu werfen! ;-)

Zitat:

Zitat von alfold (Beitrag 1087292)
Hier liegt die Anwort eigentlich schon auf der Hand.

Du solltest die VCL auch nur dafür nutzen für was sie da ist. Zu Anzeige eines Fortschrittes. und in Deiner Form1 für das schliessen sorgen! Wenn Du schon Form2 über Form1 mit Showmodal aufrufst!

Das sehe ich nun gar nicht so. Dass man in einer Form nach der Fertigstellung etwas machen will, ist doch wahrlich nicht ungewöhnlich. Ganz im Gegenteil frage ich mich, warum es nicht ein Event á la "OnReady" in jeder TForm gibt, das genau das leistet. Das wäre sogar typisch VCL.

1. OnCreate
2. OnShow
3. OnActivate
4. OnPaint
5. OnReady

Stellt sich eher die Frage, ob man so etwas nachrüsten könnte. Wo wäre da ein Ansatzpunkt?

alfold 10. Mär 2011 13:09

AW: ShowModal mit Programmablauf und selbst schließen?
 
steht alles hier: http://www.delphi-treff.de/tipps/kom...nes-formulars/
Das Formular wird das erste mal nach dem Ereignis OnShow sichtbar und damit auch ready. Vorrausgesetzt man führt keine langen Berechnungen oder andere Dinge durch, die das Anzeigen verzögern!

Gruss alfold

himitsu 10. Mär 2011 13:50

AW: ShowModal mit Programmablauf und selbst schließen?
 
Nja, als Erstes sollte man sich mal im Klaren sein, wann "wirklich" welche s ereignis ausgelöst wird.

OnShow/OnHide wird jeweils aufgerufen, wenn die Sichtbarkeit geändert werden soll, also wird OnShow aufgerufen bevor die Form sichtbar wird.

> Ergebnis, selbst wenn du in OnShow das Hide aufrufst, wird dadurch nichts verändert, da es noch versteckt ist und danach wird dann die Form eingeblendet und bleibt natürlich sichtbar.




Hierfür könnte man jetzt Delphi-Referenz durchsuchenOnActivate nutzen (aber nicht vergessen weitere Aufrufe zu blocken, da eine Form ja mehrmals "aktiviert" werden kann),
oder man schickt im OnShow eine eigene Message an seine Form (Delphi-Referenz durchsuchenPostMessage), welche erfahrungsgemäß "standardmäßig" erst nach dem Anzeigen ankommt und reagiert dann dort. (außer jemand spielt mal wieder am Delphi-Referenz durchsuchenApplication.ProcessMessages rum)

HJay 10. Mär 2011 15:58

AW: ShowModal mit Programmablauf und selbst schließen?
 
Mir gefällt Franks Lösung mit Application.OnIdle jetzt sehr gut. Geradlinig und dennoch simpel.

Allerdings bleibt die Frage, ob man das auch irgendwie ebenso geradlinig auf Formular-Ebene hätte lösen können. Also eine Routine definieren, die nach allen anderen genannten Ereignissen dann aufgerufen wird.

Die Idee mit der Message an sich selbst ist auch nicht so schlecht, vorausgesetzt, die Reihenfolge der Messages bleibt streng erhalten und die neue Message kommt mit Sicherheit automatisch richtig nach der letzten der obengenannten Messages.

dataspider 10. Mär 2011 16:13

AW: ShowModal mit Programmablauf und selbst schließen?
 
Zitat:

Zitat von himitsu (Beitrag 1087327)
Hierfür könnte man jetzt Delphi-Referenz durchsuchenOnActivate nutzen

OnActivate eignet sich IMHO genausowenig wie OnShow.

Frank

alfold 10. Mär 2011 16:19

AW: ShowModal mit Programmablauf und selbst schließen?
 
Und was spricht dagegen die einfachste Möglichkeit einzusetzen, als der Versuch zusätzlich konstrukte zu etablieren und die Kontrolle damit aus der Hand zu geben, in der Hoffnung die neue Form = Showmodal wird schon alles richtig machen!

Gruss alfold

himitsu 10. Mär 2011 16:29

AW: ShowModal mit Programmablauf und selbst schließen?
 
Zitat:

Mir gefällt Franks Lösung mit Application.OnIdle jetzt sehr gut. Geradlinig und dennoch simpel.
OnIdle ist noch ungeeigneter, als irgendein anderes Ereignis der Form.

Man mißbraucht kein globales Ereignis für eine lokale Sache. :warn:

Gründe:
- Was passiert wohl, wenn OnIdle schon belegt ist?
- Was passiert wohl, wenn man die Form gleichzeitig zweimal anzeigt?
- ...

PS: PostMessage an die Form, mit einer eigenen/passenden MessageID entspricht etwa der gleichen Idee, muß daß dort das Ereignis durchweg innerhalb der Form verbleibt.

Es wird doch nicht umsonst immer wieder davor gewarnt, das globale Variablen/Ereignisse gefährlich sind,
wenn man sie lokal begrenzt nutzen will.

dataspider 10. Mär 2011 16:43

AW: ShowModal mit Programmablauf und selbst schließen?
 
Zitat:

Zitat von himitsu (Beitrag 1087404)
OnIdle ist noch ungeeigneter, als irgendein anderes Ereignis der Form.

Hier verträgt jemand keine Kritik...
Probier es aus. OnActivate ist nicht nur ungeeignet, es funktioniert in diesem Fall einfach nicht.
Man schließt ein Form nicht in den Ereignissen ...

Und ja, sollte man OnIdle auch anderswo verwenden, dann muss man sich über mögliche Konsequenzen im Klaren sein.

Frank

alfold 10. Mär 2011 16:47

AW: ShowModal mit Programmablauf und selbst schließen?
 
@ himitsu
Hab ich doch auch geschrieben :zwinker:
Nur nicht so schön formuliert :P :thumb:

:dancer::dancer2:

alfold

Bummi 10. Mär 2011 16:53

AW: ShowModal mit Programmablauf und selbst schließen?
 
vielleicht auch so, oder so ähnlich
Delphi-Quellcode:
begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Form2 := TForm2.Create(nil);
  Form2.Show;
  Application.CreateForm(TForm1, Form1);

  Application.Run;
end.

_______________________________________


procedure TForm1.FormActivate(Sender: TObject);
begin
   EnableWindow(Handle, false);
   Form2.BringtoFront;
   Sleep(5000); // unsere ganze zu tuende Arbeit
   EnableWindow(Handle, true);
   onActivate := nil; // oder das was später hier passieren soll
   Form2.Close;
end;

himitsu 10. Mär 2011 17:12

AW: ShowModal mit Programmablauf und selbst schließen?
 
Kritik ... was ist das?

Mal im Ernst, es ging mir mehr darum daß man keine Globalen nutzen soll, als darum daß keiner auf mich hört. :angle2:

Hier mal ein schönes und aktuelles Beispiel:
http://www.delphipraxis.net/158969-f...-aus-edit.html

Oder wie wäre es damit?
Schreib das mal ins OnCreate der Form oder in ein Button-Klick-Ereignis
Delphi-Quellcode:
if Assigned(Application.OnIdle) then
  ShowMessage('huhu?');
So, wie du siehst, siehst du nichts (falls doch, dann bist du auf's nachfolgende Kleingedruckte gestoßen), aber nun zieh z.B. einmal auf irgendeine Form ein Delphi-Referenz durchsuchenTApplicationEvents drauf
und was ist nun?
Genau, DU würdest bei Nutzung von dieser Komponente behindern, da du etwas überschreibst.
Und um das mal erwähnt zu haben ... diese Komponente wird versteckt in einigen anderen Delphikomponenten auch noch verwendet.


Manchmal geht es eben nicht um "Ehre", welche gekränkt sein könnte, sondern einfach nur um Erfahung.

alfold 10. Mär 2011 17:19

AW: ShowModal mit Programmablauf und selbst schließen?
 
@Bummi
es geht ihm nicht darum das er aus der Form1 die Form2 closen tut.
Form2.Schowmodal soll sich nach abarbeitung aller Aufgaben selbst schliessen!

Gruss alfold

Bummi 10. Mär 2011 17:42

AW: ShowModal mit Programmablauf und selbst schließen?
 
@alfold
ich meine eben dieses Verhalten lässt sich mit o.g. simulieren...Splash wird angezeigt, alles bleibt unbedienbar bis Form1 fertig ist, Splash wird ausgeblendet...

WM_CLOSE 10. Mär 2011 19:37

AW: ShowModal mit Programmablauf und selbst schließen?
 
wie wäre es, das splash mit MSDN-Library durchsuchensetwindowpos "modal" zu machen?
showModal ist schließlich dazu gedacht mit der weiteren Ausführung zu warten, bis das form geschlossen wurde. dann wäre die ausführung des splash wieder asynchron.

HJay 10. Mär 2011 21:13

AW: ShowModal mit Programmablauf und selbst schließen?
 
Sicher, wenn Application.OnIdle auch anderweitig verwendet wird, muss man auf der Hut sein. Die Gefahr besteht derzeit bei mir nicht, glaube ich. Aber dennoch, danke für die Warnung.

Kann mal jemand einen kurzen Code-Vorschlag machen, wie man das statt Application.OnIdle mit einer eindeutigen Message an die eigene Form machen würde? Ich kenne mich mit Messages nicht so aus.

Wir wird die Reihenfolge der Messages sichergestellt, also dass die eigene Message als letztes erhalten wird?

Vielen Dank im voraus!

alfold 10. Mär 2011 21:23

AW: ShowModal mit Programmablauf und selbst schließen?
 
Ich kann immer noch nicht verstehen warum man es manchmal kompliziert macht wenn es auch simple gehen kann!
Ich gehe mal davon aus das DeineProgress Anzeige korrekt funktioniert in bezug Deiner Datenanforderung. So wie Du es oben beschrieben hast.

Leg Dir in Deiner TFormProgress ein timer mit rein, frage dort ab ob Progress.Position = 100 ist , wenn ja then Close. Schon ist Dein ganzes Problem Gelöst!
Diese einfach aber sichere Möglichkeit sollte nichts abwägiges haben.

Gruss alfold

BUG 10. Mär 2011 21:50

AW: ShowModal mit Programmablauf und selbst schließen?
 
Zitat:

Zitat von alfold (Beitrag 1087522)
Leg Dir in Deiner TFormProgress ein timer mit rein, frage dort ab ob Progress.Position = 100 ist , wenn ja then Close. Schon ist Dein ganzes Problem Gelöst!

Es gibt keine Delphianwendung in der man nicht noch mindestens einen Timer unterbringen kann :lol:
Er weiß doch selbst, wann die Aufgabe erledigt ist (schließlich muss ja irgendwer Progress.Position setzen), die Frage ist, wann er anfangen kann.

alfold 10. Mär 2011 23:32

AW: ShowModal mit Programmablauf und selbst schließen?
 
War das nicht schon geklärt!? Im OnActivate.
Nun fehlte ihm doch blos, wo er close reinschreiben soll wenn er mit allem fertig ist!
Habs mit einem timer ausprobiert und fertig!

Alles andere sehe ich als overhead an.
Etwa so: Wenn ich fertig bin schick mir ne message das ich mich beenden kann, weil close im onActivate nicht geht!
Und über die anderen Vorschläge wurde ja schon Diskutiert:wink:

PS: Allerdings habe ich schon weiter oben erwähnt, das dies ein typisches Beispiel ist, vermischen von VCL und Daten. Die Daten wird er bestimmt nicht in der TFormProgress benötigen sondern in seiner MainForm.

Gruss alfold

himitsu 11. Mär 2011 02:46

AW: ShowModal mit Programmablauf und selbst schließen?
 
Zitat:

Zitat von HJay (Beitrag 1087516)
Die Gefahr besteht derzeit bei mir nicht, glaube ich. Aber dennoch, danke für die Warnung.

Bitte.

Derzeit ... und wenn du daran in 2 Jahren was änderst, dann hast'e dieses hier bestimmt schonwieder vergessen.

PS: Ich würde zwar auch eher zu "einfach" tendieren,
aber das wäre jetzt nicht einfach, sondern billig fehleranfällig.


Delphi-Quellcode:
TForm5 = class(TForm)
  procedure FormShow(Sender: TObject);
  procedure WMMachWas(var Msg: TMessage); message WM_USER+1;
private
  { Private-Deklarationen }
public
  { Public-Deklarationen }
end;

procedure TForm5.FormShow(Sender: TObject);
begin
  ...
  PostMessage(Handle, WM_USER+1, 0, 0);
  ...
end;
PS: So wäre es sogar übersichtlicher, da der Bearbeitungsweg "eindeutig" ist.

Chemiker 11. Mär 2011 06:38

AW: ShowModal mit Programmablauf und selbst schließen?
 
Hallo HJay,

meiner Meinung nach, ist es auch ungeschickt jedes Mal den Datenbank-Zugriff zu unterbrechen um die Anzeige zu aktualisieren. Ein Mehrwert hat der Benutzer dadurch nicht, im Gegenteil das ganze dauert nur unnötig lange weil man erst feststellen muss wie viel Datensätze verarbeitet werden sollen. Eine einfache Massagebox mit den Hinweis, dass der PC arbeitet würde dann reichen.

Bis bald Chemiker

hoika 11. Mär 2011 07:07

AW: ShowModal mit Programmablauf und selbst schließen?
 
Hallo,

ich mache das so.

ins FormActivate kommt der Code, etwa so

Delphi-Quellcode:
Application.ProcessMessages
// der Code
Zitat:

Etwa so: Wenn ich fertig bin schick mir ne message das ich mich beenden kann, weil close im onActivate nicht geht!
Close nicht, aber

Delphi-Quellcode:
PostMessage(Handle, WM_CLOSE, 0, 0);

Heiko

dataspider 11. Mär 2011 07:14

AW: ShowModal mit Programmablauf und selbst schließen?
 
Hi,

Himitsu hat das Beispiel zwar schon im Ansatz geschrieben,
ich komplettiere mal:

Code:

Interface
Uses
   ...
Const
  FM_STARTED = WM_USER + 1; // Formular komplett erzeugt
...
  protected
    procedure FmStarted(var Message: TMessage); message FM_STARTED; // MethodenName frei, Konstante für MessageId wichtig
implementation
...
procedure TfrmModal.FmStarted(var Message: TMessage);
begin
  // Verarbeitung
  ModalResult := mrOK; // oder Close
end;
// und ntürlich der Aufruf von PostMessage wie bei Himitsu
Ich habe hier allerdings Bedenken.
Falls in der Verarbeitung z.B. wegen ScrollBar ain Application.ProcessMessages kommt, funktioniert es wieder nicht.

Aber, Probieren geht über ...

Frank

alfold 11. Mär 2011 10:02

AW: ShowModal mit Programmablauf und selbst schließen?
 
Und nun? Wenn er beim einlesen der Daten evtl noch ein Try except block drin hat(?) oder es generell zur Unterbrechung kommt steht seine TFormProgress da und er kann nur noch eins machen strg+alt+del um sein Prog abzuschiessen. Oder mann macht nun noch zusätzliches rein um auch noch dieses abzufangen damit er wieder an seine MainForm kommt!
Das mag bei Ihm ja alles gehen. Wenn es dann aber auf eine anderen Maschine kommt ......

Es ist und bleibt ne unsaubere Lösung!

Ich schreibe dies nicht weil ich mich wichtig tun will, sondern aus eigener Erfahrung!

Ich kann nur nicht verstehen warum man von einem falschen Ansatz her nach Lösungen sucht um diesen evtl noch zu verschlimmern :?:

Gruss alfold

dataspider 11. Mär 2011 10:51

AW: ShowModal mit Programmablauf und selbst schließen?
 
Zitat:

Zitat von alfold (Beitrag 1087628)
Es ist und bleibt ne unsaubere Lösung!

Was ist die saubere Lösung? Der Timer?

Ich finde es sehr vermessen, alles, was nicht den eigenen Vorlieben entspricht, als unsauber zu deklarieren.

Auszug aus der Forms:
Code:
Show;
try
  SendMessage(Handle, CM_ACTIVATE, 0, 0);
  ModalResult := 0;
  repeat
    Application.HandleMessage;
    if Application.Terminated then ModalResult := mrCancel else
      if ModalResult <> 0 then CloseModal;
  until ModalResult <> 0;
Wie man sieht, wird nach allen Ereignissen (Show, Activate etc.) ModalResult auf 0 gesetzt.
Schliessen hier nicht möglich.
Das nächste ist HandleMessage - ProcessMessage und Idle.

Was ist nun unsauber daran, genau hier einzusteigen?

Sowohl Timer als auch PostMessage als auch Application.OnIdle kann man verwenden.

Ich persönlich bevorzuge weiterhin OnIdle, bezeichne die anderen Lösungen aber nicht gleich als unsauber.

Ich habe früher dafür auch einen Timer benutzt.
Aber man muss doch die Zeit gut wählen, damit er wirklich fertig ist (auch ProcessMessages braucht Zeit).

Den Fragesteller zu verunsichern, kann ja nicht das Ziel sein.

Frank

alfold 11. Mär 2011 11:29

AW: ShowModal mit Programmablauf und selbst schließen?
 
Ne der Timer nicht!
Daten da holen wo ich sie brauche in Main! TFormprogress nur als Anzeige!
fertig!
Schon spare ich mir das ganze konstrukt ein!

Gruss alfold

dataspider 11. Mär 2011 11:40

AW: ShowModal mit Programmablauf und selbst schließen?
 
Zitat:

Zitat von HJay (Beitrag 1087255)
Ich hätte wirklich gerne ein modales Fenster, damit die Fertigstellung abgewartet werden muss.

OK, darüber kann man diskutieren.
Aber es ist mit der o.g. Anforderung auch nicht so einfach zu realisieren.

Frank

alfold 11. Mär 2011 12:05

AW: ShowModal mit Programmablauf und selbst schließen?
 
Da das Daten holen sicherlich in einer schleife läuft bis alle Daten da sind, hilft auch bringtofront um TformProgess ständig oben zu haben!
Da brauche ich kein ShowModal.

Gruss alfold

HJay 11. Mär 2011 12:09

AW: ShowModal mit Programmablauf und selbst schließen?
 
Vorab vielen Dank üfr die interessanten Diskussionen zum Thema.

1. Ich halte ein modales Fenster für notwendig, damit auf der FormMain nicht herumgeclickt werden kann, während die Routine läuft. Genau dazu sind modale Fenster gedacht und als Meldungsfenster (was passiert und wie der Fortschritt ist), ist es auch ideal. Wenn jemand einen besseren Vorschlag hat, nur raus damit, aber ich finde ein modales Fenster dafür perfekt geeignet.

2. Die Idee mit dem Timer habe ich auch mal testweise umgesetzt und zwar in der Form, dass der Timer nach FormActivate gestartet wird und auf dem TimerEvent dann die Routine liegt. Dies geht, aber man muss den Timer natürlich großzügig dimensionieren, damit die Form auch wirklich fertig ist. Letztlich ein Timer ja aber für mich gefühlt nur ein Workaround um das eigentliche Problem, nämlich exakt nach Fertigstellung der Form auch mit der Routine zu beginnen.

3. @alfold: Du hast zahlreiche kritische Bemerkungen abgegeben, die meines Erachtens größtenteils am Ziel vorbeigehen:

3a: "Close" ist hier gar nicht das Problem, außer dass es leider nicht von einem Activate- oder Show-Event aus passieren kann. Sowohl Timer als auch Application.OnIdle lösen mein Close-Problem. Das Hauptanliegen meiner Frage ist doch, wie ich in einer modalen Form automatisch mit einer Routine beginnen kann, NACHDEM das Fenster sichtbar ist und so, dass es refreshed werden kann.

3b: Daten holen wo gebraucht", ja, klingt erst einmal eingängig, ist es aber nicht. Die Aufgabe wäre dann, ein Fortschrittsfenster zu haben, das modal ist und weitere Nuttzinteraktion unterbindet... Ha, genau darum geht es doch. Wo nun die Daten geholt werden, ist schnuppe. In diesem Falle wird sogar eine Routine aus einer anderen Unit aufgerufen, die eben nur den Datenimport macht. Wo das passiert, ist doch für meine Frage völlig schnuppe.

3c: BringToFront und ähnliche Konstrukte sind doch auch nur Workarounds und verhindern nicht, dass der Nutzer auf der Form woanders herumclicken kann.

4. @Dataspider und Himitsu: Danke für den PostMessage-Code und den Code zur Implementierung. Das ist interessant und sicherlich für vieles zu gebrauchen. Muss ich mal üben. Für dieses Problem hilft es mir aber leider doch nichts, da ich meiner Fortschrittsanzeige sowohl Repaint als auch Application.ProcessMessages verwenden muss, damit die Form auf Zack bleibt.

5. @Chemiker: Das ist nicht wirklich richtig. Die Form-Refreshs dauern zusammen nur einige Millisekunden, während mein Datenzugriff Dutzende Sekunden dauern kann. Der Mehrwert des Nutzers ist also sehr hoch, der Zeitverlust kaum messbar. Ich persönlich finde es immer toll, wenn man abschätzen kann, wielange es noch dauern wird und nicht nur eine stupide Box kommt, dass der Rechner angeblich was tut.

Zusammenfassend stelle ich für mich fest, dass Dataspiders Application.OnIdle bisher die einzige gangbare Lösung ist. Zugleich sehe ich auch die möglichen Gefahren und Einschränkungen.

Ich gebe zu, dass eine noch bessere Lösung wünschenswert wäre. Timer und Message sind es jedoch nicht, aus obengenannten Gründen.

Ganz ehrlich kam ich mir anfangs selten blöde vor, dass sich dieses einfache Problem, das doch jeder Programmierer mal öfter haben muss, nicht lösen konnte. Inzwischen wundere ich mich, dass es dafür offensichtlich keine wirklich geradlinige Lösung gibt.

Ein Statusfenster mit Fortschrittsanzeige, das abgewartet werden muss, ist doch nichts seltenes...

alfold 11. Mär 2011 12:20

AW: ShowModal mit Programmablauf und selbst schließen?
 
Ich sehe hier aber nur den Vorteil!
Ich bleibe in Main habe dort die ganze kontrolle und muss mich nicht damit rumärgern wenn im Showmodal evtl noch was passiert :wink:
Auch wenn es nur einfache Bordmittel sind, sind diese manchmal efficienter als konstrukte die bei mir zu hause super funcen, aber wehe ich komm auf einer anderen Maschine und ein anderer benutzt dieses Prog.

Ich rede also nicht an Deinem Problem vorbei, sondern ich zeige nur auf was die Folgen sein können!

Solange Du in der ladeschleife bist kann mann zwar auf Main klicken aber viel dürfte da nicht passieren da Dein Progress oben bleibt, wenn man es vernünftig ansetzt!

Aber ich gebe dir durchaus recht, entscheiden musst Du, wie Du es umsetzten willst.

Gruss alfold


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:46 Uhr.
Seite 1 von 2  1 2      

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