Delphi-PRAXiS

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/)
-   -   Delphi OpenDialog - Relikt in *.pgn-Tool (https://www.delphipraxis.net/183224-opendialog-relikt-%2A-pgn-tool.html)

wendelin 21. Dez 2014 10:12

OpenDialog - Relikt in *.pgn-Tool
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo,
mein Problemchen ist der Umstand, daß NACH (während) dem (des) LADEN(s) einer *.pgn-Datei (= TextDatei)
bis zur Abarbeitung der Proc. je nach Größe der zu ladenden Datei ein Relikt des
OpenDialog - Windows auf dem Main-Window verbleibt. Siehe Bilder ! Sowas stört einfach !

Wie kann ich das unterbinden ?

für Eure Antworten bin ich dankbar.

Wendelin

mm1256 21. Dez 2014 10:42

AW: OpenDialog - Relikt in *.pgn-Tool
 
Application.ProcessMessages ??

Uwe Raabe 21. Dez 2014 10:58

AW: OpenDialog - Relikt in *.pgn-Tool
 
Zitat:

Zitat von mm1256 (Beitrag 1284268)
Application.ProcessMessages ??

Er hat Jehova gesagt :shock:

mm1256 21. Dez 2014 11:02

AW: OpenDialog - Relikt in *.pgn-Tool
 
"Jehova" versteh ich jetzt nicht. Liegt's daran, dass ich erst aufgestanden bin?

mjustin 21. Dez 2014 11:14

AW: OpenDialog - Relikt in *.pgn-Tool
 
Zitat:

Zitat von wendelin (Beitrag 1284265)

Wie kann ich das unterbinden ?

Ich würde den lang laufenden Prozess in einem Thread ausführen. Der Hauptthread startet den Thread, danach wird die Kontrolle sofort an die VCL zurückgegeben und dadurch auch die Bildschirmdarstellung aktualisiert.

himitsu 21. Dez 2014 12:27

AW: OpenDialog - Relikt in *.pgn-Tool
 
Zitat:

Zitat von mm1256 (Beitrag 1284272)
"Jehova"

Zwischen dem Öffnendialog und dem Laden der Datei dem Programm/Windows die Chance geben sich neu zu zeichnen. :zwinker:

Oder die andere genannte Alternative, also das Laden in den Hintergrund legen und die VCL sofort wieder um sich selber kümmern zu lassen.

Uwe Raabe 21. Dez 2014 13:22

AW: OpenDialog - Relikt in *.pgn-Tool
 
Zitat:

Zitat von mm1256 (Beitrag 1284272)
"Jehova" versteh ich jetzt nicht. Liegt's daran, dass ich erst aufgestanden bin?

Vielleicht bin ich auch einfach nur zu alt: Er hat Jehova gesagt!

wendelin 21. Dez 2014 16:15

AW: OpenDialog - Relikt in *.pgn-Tool
 
Hallo, vielen Dank für Eure Antworten.

Allerdings habe ich noch nie mit Thread's gearbeitet.
Vielleicht kann mir jemand mit Hilfe von Delphi-Code (Pseudo-Code) an Hand eines Beispiels
die Vorgehensweise erklären.

Danke Wendelin

mein Code

Delphi-Quellcode:
procedure TMyPGN.SpeedButton7Click(Sender: TObject);
VAR
  MyFileName,PathName,LeerZ  : String;
  Zahl_ENDE                  : Integer;
begin
  LeerZ := '';
(* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ *)
  OpenDialog2.FileName  := g_ArbeitsVerz ;
(* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ *)
  OpenDialog2.InitialDir := g_ArbeitsVerz ;
  PathName              := g_ArbeitsVerz ;
  MyFileName            := 'Ihre Eingabe';
  OpenDialog1.FileName  := PathName + MyFileName;
  if OpenDialog1.Execute then
  begin
    Memo1.Clear;
    MyStringListA.LoadFromFile(OpenDialog1.FileName);
  end;
  Memo1.Lines.Text := MyStringListA.Text;
  If Trim(MyStringListA.Strings[0]) <> '' then // ev. Leerzeile am Anfang !!
  begin                                        // einfügen
    Memo1.Clear;
    MyStringListA.Insert(0,LeerZ);
    Memo1.Lines.Text := MyStringListA.Text;
  end;
  Zahl_ENDE := MyStringListA.Count;
  If Trim(MyStringListA.Strings[Zahl_ENDE - 1]) <> '' then
  begin                                        // ev. Leerzeile am ENDE !!
    Memo1.Clear;                               // einfügen
    MyStringListA.Insert(Zahl_ENDE,LeerZ);
    Memo1.Lines.Text := MyStringListA.Text;
  end;
  Panel5.Caption := 'Zeilen :' + IntToStr(Memo1.Lines.Count); // Zahl der Zeilen anzeigen
  AusgabeAnzahlPartienAlt;
  Gewinn_Verlust_Remis_NEU;

dGeek 21. Dez 2014 16:38

AW: OpenDialog - Relikt in *.pgn-Tool
 
Hier sind vier Möglichkeiten erklärt, einen Thread zu erzeugen.
Ich bevorzuge ganz klar die "The Delphi Way" Methode.

http://www.thedelphigeek.com/2012/02...un-5-four.html

mm1256 21. Dez 2014 19:05

AW: OpenDialog - Relikt in *.pgn-Tool
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1284288)
Zitat:

Zitat von mm1256 (Beitrag 1284272)
"Jehova" versteh ich jetzt nicht. Liegt's daran, dass ich erst aufgestanden bin?

Vielleicht bin ich auch einfach nur zu alt: Er hat Jehova gesagt!

Danke Uwe, du bist so gut zu mir :thumb: (kein Sarkasmus, ich mein das ernst!)

Wenn ich mir den obigen Code so anschaue, würde da nicht vielleicht ein BeginUpdate und ein EndUpdate schon viel bringen? Und dazu natürlich noch das, was man(n) nicht ausspricht ;-)

himitsu 21. Dez 2014 19:38

AW: OpenDialog - Relikt in *.pgn-Tool
 
Zitat:

Zitat von mm1256 (Beitrag 1284310)
Wenn ich mir den obigen Code so anschaue, würde da nicht vielleicht ein BeginUpdate und ein EndUpdate schon viel bringen?

Nein, nicht wirklich, außer MyStringListA ist keine TStringList.

Es würde viel mehr bringen, wenn man nicht sinnlos dem arschlangsamen Memo mehrmals den kompletten Inhalt neu zuweist.

Delphi-Quellcode:
procedure TMyPGN.SpeedButton7Click(Sender: TObject);
VAR
  MyFileName : String;
begin
  OpenDialog2.FileName := g_ArbeitsVerz;
  OpenDialog2.InitialDir := g_ArbeitsVerz;
  MyFileName := 'Ihre Eingabe';
  OpenDialog1.FileName := g_ArbeitsVerz + MyFileName;
  if not OpenDialog1.Execute then
    Exit; // Wenn man auf Abbrechen drückte, dann wurde dennoch alles in MyStringListA dennoch verarbeitet?
  MyStringListA.LoadFromFile(OpenDialog1.FileName);
  If Trim(MyStringListA.Strings[0]) <> '' then // auf erste/letzte Zeile zugreifen ... und was wenn es keine Zeilen gibt?
    MyStringListA.Insert(0, ''); // wenn am Anfang eine Leerzeine, dann NOCHMAL Eine dahin?
  If Trim(MyStringListA.Strings[MyStringListA.Count - 1]) <> '' then
    MyStringListA.Add(''); // hier auch?
  Memo1.Lines.Text := MyStringListA.Text; // einmal zuweisen reicht und vorher zu löschen war eh nutzlos
  Panel5.Caption := 'Zeilen :' + IntToStr(MyStringListA.Count); // Zahl der Zeilen anzeigen
  AusgabeAnzahlPartienAlt;
  Gewinn_Verlust_Remis_NEU;

Ach ja, Threads bringen hier absolut garnichts, da die meiste Zeit, praktisch fast die Ganze, mit Zugriffen auf die VCL verbraten werden.

wendelin 22. Dez 2014 10:58

AW: OpenDialog - Relikt in *.pgn-Tool
 
Hallo, mal ein paar allgemeine Bemerkungen.

1. Sicher hast Du recht, den Code kann man kürzen.
2. Ich bin reiner Hobby-Prog.
3. Aus vielen Antworten von versch. IT-Crack's ?? in dieser Comm. kann man immer wieder eine gewisse Arroganz herauslesen.
(zu manchen Fragen erfolgt KEINE substantielle Antwort aber ziemlich viel Nonsens)
4. Vor meiner Pensionierung war ich niedergelassener Arzt.
Was glaubst Du, was die Pat. gesagt hätten, wenn ich auf med. Fragen meiner Pat. geantwortet hätte : Schauen Sie doch mal in die 'Rentner-Bravo'
(Apotheken-Rundschau) oder ins Internet.


Dr.M.U. alias Wendelin

mm1256 22. Dez 2014 12:46

AW: OpenDialog - Relikt in *.pgn-Tool
 
Hallo Doc,

Zustimmung in allen Punkten. In dieser Hinsicht haben wir Gemeinsamkeiten. Als IT-Autodidakt, der wie einige Andere hier kein IT-Studium hinter sich hat, wird man manchmal etwas "von oben herab" behandelt, vielleicht sogar als "geistig weniger bemittelt" betrachtet, wenn man Code schreibt oder Ansichten vertritt, die nicht Stand der Technik, oder im Sinne der hier anwesenden Spezialisten sind.

Ich kann mich nur schwer an diese Umgangsformenk gewöhnen, aber, was solls. Es sind überwiegend die "jungen Wilden" die auch untereinander nicht mehr mit der Geduld und der Höflichkeit umgehen, die wir (...alten Säcke...<g>...) als Standard betrachten. Um es mal in Doc-Sprache zu sagen: Das Rezept ist einfach anzunehmen, alternative Therapievorschläge sind kontraindiziert.

Um aber nochmals zum Thema zurück zu kommen. Hast du denn "das Verbotene" schon ausprobiert?

Medium 22. Dez 2014 13:08

AW: OpenDialog - Relikt in *.pgn-Tool
 
Auch wenn die Art und Weise vielleicht nicht immer nach jedermanns Gusto ist, halte ich es dennoch für richtig (und wichtig) darauf hinzuweisen, dass eine vorgeschlagene Therapie nicht zur Heilung, sondern nur zum Kaschieren der Symptome taugt, und bei vielen Patienten auch noch nach Jahren zu erheblichen Nebenwirkungen und Folgeerkrankungen führen kann. (Und das ist jetzt gar nicht mal so arg metaphorisch gemeint wie man denken könnte in diesem Fall hier.) Würden sich Ärzte derartiges verschweigen, wäre ich als Patient gelinde gesagt leicht nervös.

Uwe Raabe 22. Dez 2014 13:27

AW: OpenDialog - Relikt in *.pgn-Tool
 
Zitat:

Zitat von mm1256 (Beitrag 1284374)
Um aber nochmals zum Thema zurück zu kommen. Hast du denn "das Verbotene" schon ausprobiert?

Ich bin kein Arzt und würde mir deshalb auch niemals erlauben, irgendeine Diagnose zu stellen. Informatik habe ich auch nicht studiert und das Programmieren habe ich mir weitestgehend selbst beigebracht. Ich traue mir aber dennoch zu, in Bezug auf Delphi/Pascal-Programmierung durchaus fundierte und belastbare Aussagen zu treffen und Empfehlungen zu geben, die überwiegend auf einer über 30-jährigen Erfahrung beruhen.

Daher, um für die noch nicht so lange zugehörigen Forenmitglieder mal zu verdeutlichen, warum Application.ProcessMessages "verboten" ist: Mit diesem Aufruf werden Nachrichten aus der MessageQueue abgearbeitet. Das mag für das Neuzeichnen des Forms hier vielleicht noch erwünscht sein, für andere Eventhandler fällt das aber im Allgemeinen unter die Rubrik "unerwartet".

Nehmen wir z.B. mal diesen einfachen Code in einem Eventhandler an:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  DoSomeStuff;
  if OpenDialog1.Execute then begin
    Application.ProcessMessages;
    DoSomeOtherStuffThatNeedsSomeTime;
  end
  else begin
    DoSomeEvenOtherStuff;
  end;
end;
Bei einem Click auf Button1 wird nun zunächst DoSomeStuff aufgerufen, dann der Dialog geöffnet und nach Bestätigen beendet. Nehmen wir nun noch an, daß der User während DoSomeStuff nochmal auf den Button klickt, sei es aus Ungeduld, fehlendem Feedback des Programms oder motorischer Unzulänglichkeit. Das nun folgende Application.ProcessMessages wertet diesen Click aus, ruft DoSomeStuff auf und öffnet den Dialog erneut. Dabei ist DoSomeOtherStuffThatNeedsSomeTime aber noch gar nicht gelaufen. Wird der Dialog abgebrochen, erfolgt ein Aufruf von DoSomeEvenOtherStuff, der Eventhandler wird beendet, das Application.ProcessMessages ebenso und es folgt ein DoSomeOtherStuffThatNeedsSomeTime.

Aus dem eigentlich vorhersehbaren und durchaus überschaubaren Event-Handling ist ein ziemliches Wirrwar im Programmablauf geworden, daß selbst erfahrene Programmierer kaum noch nachvollziehen, geschweige denn in den Griff kriegen können. Und hier habe ich bewusst nur den einen Eventhandler betrachtet. Es kann auch durchaus zu konkurrierenden Abläufen in mehreren Eventhandlern auch in unterschiedlichen Forms kommen. Meistens versucht man dann durch zusätzliche Flags das Reentering der Eventhandler zu unterbinden. Das fördert aber nicht gerade die Lesbarkeit und Wartbarkeit eines Programms.

Ich weiß nicht, wie oft ich schon sporadische Laufzeitfehler in fremdem Code suchen musste, bei dem sich das Problem auf mindestens einen Aufruf von Application.ProcessMessages zurückführen ließ. Dabei schließe ich frei verfügbare und käuflich erwerbbare Bibliotheken (z.B. RxLib oder QuickReport um nur zwei zu nennen) gar nicht aus. Das ist dann ganz besonders gemein, da der eigentliche Programmcode ja durchaus korrekt sein mag und es nur wegen eines entsprechenden Aufrufs innerhalb der Bibliothek zu der Fehlfunktion kommt.

Deshalb ist Application.ProcessMessages meiner Meinung nach einfach verboten. Es ist nur ein Hilfmittel um eigentlich schlechten oder gar falschen Code trotzdem noch halbwegs zum Laufen zu bringen. Man erweist sich dadurch also nur einen Bärendienst.

mm1256 22. Dez 2014 14:56

AW: OpenDialog - Relikt in *.pgn-Tool
 
Hallo Uwe,

über diese Nebeneffekte von Application.ProcessMessages habe ich schon geflucht wie ein Hufschmied. Aber, sobald man dann mal konkret eine Frage nach einer Alternative stellt, gibt's meistens entweder keine Antwort, oder welche mit so viel "wenn und aber" drin, dass sich mir eine bessere Alternative bisher nicht erschlossen hat: Bei modalen Aufrufen und sonst wo es geht, Form.Enabled:=false, oder die Komponente(n) die eine Rekursion auslösen könnten disablen, während eine Aktion läuft.

In diesem Fall müsste man halt den SpeedButton disablen, um sicher zu gehen.

Delphi-Quellcode:
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  SpeedButton1.Enabled := false;
  try
    Tu was
  finally
    SpeedButton1.Enabled := true;
    Application.Processmessages;
  end;
end;
Für alternative oder bessere Vorschläge hab ich immer ein offenes Ohr!

Uwe Raabe 22. Dez 2014 15:15

AW: OpenDialog - Relikt in *.pgn-Tool
 
Es gibt verschiedene Ansätze, die je nach Anforderung mehr oder weniger gut geeignet sind. Die am häufigsten genannte ist sicher, die Arbeit in einen Thread auszulagern. Das bringt natürlich andere Probleme mit sich, denen man sich bewusst sein muss.

Wenn die Aufgabe das zulässt kann man die Arbeit auch schrittweise ausführen - z.B. immer x Zeilen lesen und verarbeiten und das Update der GUI vielleicht in einem Schritt am Ende ausführen. Der Event wird dann zeinah verlassen und die einzelnen Steps triggert man z.B. mit einer Windows-Message an das Form. Eventuell lagert man die schrittweise Verarbeitung in eine eigene Klasse aus um das Form nicht zu überladen. Dann kann man gleich auch einen Progressbar mitlaufen lassen, der dem Anwender den Fortschritt anzeigt. Eine allgemein gültige Herangehensweise gibt es leider nicht.

Wichtig ist, daß man erstmal feststellt, wo denn überhaupt die Zeit verbraten wird, damit man nicht an der falschen Stelle rumdoktert. Vielleicht sitzt das Problem ja in diesem Fall gar nicht bei der Memo-Zuweisung sondern in den beiden Methoden, die am Ende aufgerufen werden.

wendelin 23. Dez 2014 09:48

AW: OpenDialog - Relikt in *.pgn-Tool
 
Hallo,

danke für Eure Erklärungen bez. Application Process.. u.s.w.
Wäre für mich sowieso nicht in Frage gekommen, da ich damit nur schlechte Erfahrungen gemacht habe.
Außerdem macht es die entsprechenden Procs. deutlich langsamer.
Zu meiner ursprünglichen Frage : Vielleicht gibt es ja in der API eine Möglichkeit vor oder auch nach dem Öffnen eines Open/Save-
Dialog - Fenster's dieses so zu verschieben, daß es NICHT das Main-Window überdeckt ? (Kann man natürlich auch manuell machen, wär
aber eleganter).

Frohe Weihnachten, Wendelin

Bernhard Geyer 23. Dez 2014 10:07

AW: OpenDialog - Relikt in *.pgn-Tool
 
Zitat:

Zitat von wendelin (Beitrag 1284484)
Zu meiner ursprünglichen Frage : Vielleicht gibt es ja in der API eine Möglichkeit vor oder auch nach dem Öffnen eines Open/Save-
Dialog - Fenster's dieses so zu verschieben, daß es NICHT das Main-Window überdeckt ? (Kann man natürlich auch manuell machen, wär
aber eleganter).

Da gibt es keine offizielle API (Jedenfalls keine Einfache - Man kann sich naturlich das Fensterhandle geben lassen und mit SetWindowPos es umschieben). Und wohin willst du es verschieben wenn diene Anwendung z.B. im Vollbild läuft?
Das Problem ist doch ganz einfach das das entsprechende Fensterteil keine Möglichkeit hat sich neu zu zeichnen.

Statt Application.Processmessages wäre u.U. ein Update/Repaint/Refresch-Aufruf hilfreich.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:19 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