Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi ReadLn() für Fensterprogramme? (https://www.delphipraxis.net/118712-readln-fuer-fensterprogramme.html)

Kill0r 13. Aug 2008 12:17


ReadLn() für Fensterprogramme?
 
Hallo :)

Ich habe ein Problem welches vielleicht nicht ganz dem normalen Windows-Konzept entspricht und ich bin mir nicht sicher, ob es lösbar ist. Also ich schreibe gerade eine Art Konsolenprogramm, welches aber eigentlich ein normales Windowsprogramm ist mit einem TImage was mir als Anzeige dient (d.h. Ich schreibe den Text welcher ich anzeigen will dort drauf)
Nun möchte ich so etwas wie einen WaitForUserInput Befehl implementieren, welcher solange alle Tastendrücke in einen String speichert, bis die Entertaste gedrückt wurde.
Die Benutzung würde folgendermassen aussehen:
Delphi-Quellcode:
Drawer.AddToWriteBuffer('What''s your name? ');
Nickname := WaitForUserInput;
AskServerOrClient;
AskServerOrClient soll erst dann ausgeführt werden, wenn bei der Eingabe die Entertaste gedrückt wurde und WaitForUserInput den eingegebenen String zurückliefert. Also ziemlich ähnliche Funktionsweise wie der ReadLn() Befehl bei Konsolenprogrammen.

Ich habe mich schon an einer Lösung mittels While Schleife versucht, welche aber logischerweise alle Messages blockierte, so dass nicht mal mehr das Fenster überhaupt angezeigt wurde und dies in einer Endlosschleife endete. Die Tasten habe ich dort über FormKeyPress abgefragt und in einer Variable gespeichert welche dann von WaitForUserInput ausgelesen wurde, was mir nicht sehr sinnvoll und umständlich erscheint... Vielleicht wisst ihr auch da eine bessere Variante? Ich nehme mal an ich müsste dies über einen Thread lösen (damit habe ich bereits Erfahrungen gesammelt :wink:) Aber ich wüsste nicht wie das realisieren soll :(

Ich möchte anmerken, dass ich keinen vollständigen Code brauche ;) Denkanstösse / Konzepte reichen mir völlig :-D
Danke fürs Durchlesen meines Romans :mrgreen:


Cu
Kill0r

Neutral General 13. Aug 2008 13:14

Re: ReadLn() für Fensterprogramme?
 
Hi,

Versuch mal deine while-Methode. Aber schreib noch folgendes in die Schleife:

Delphi-Quellcode:
while not EntertasteGedrueckt do
begin
  Application.ProcessMessages;
end;

MSSSSM 13. Aug 2008 14:12

Re: ReadLn() für Fensterprogramme?
 
Und deklariere noch eine Zählvariable und führe das am besten nur alle 50-100 (oder 5-10 je nach dem) aus
Für Alle 50 mal schreibst du ins While
Delphi-Quellcode:
if Zaehlvariable mod 50 = 0 then Application.ProcessMessages;

automatix 13. Aug 2008 14:51

Re: ReadLn() für Fensterprogramme?
 
Oder:
Delphi-Quellcode:
while not EntertasteGedrueckt do
begin
  Sleep(50);
  Application.ProcessMessages;
end;

littleDave 13. Aug 2008 15:41

Re: ReadLn() für Fensterprogramme?
 
Delphi-Quellcode:
Sleep(50);
find ich schon zu viel - ein
Delphi-Quellcode:
Sleep(1);
reicht bei mir schon vollkommen aus um zumindest die CPU-Auslastung auf < 1% zu setzen.

Kill0r 13. Aug 2008 15:44

Re: ReadLn() für Fensterprogramme?
 
Hey :wink:
Danke für eure Bemühungen, aber ich glaube nicht, dass mir das wirklich weiterhelfen wird.
Meine aktuelle Prozedur (mit eingefügtem Application.ProcessMessages) sieht so aus:
Delphi-Quellcode:
function TUser.WaitForUserInput: String;
begin
  InputString := '';
  NextKey := '';
  EnableInput;

  while InputEnabled do
  begin
    Application.ProcessMessages;
    if NextKey = #8 then
    begin
      SetLength(InputString, Length(InputString)-1);
      DrawInput;
      NextKey := '';
    end
    else
    if not (NextKey = '') then
    begin
      InputString := InputString + NextKey;
      DrawInput;
      NextKey := '';
    end;
  end;
 
  Result := InputString;
end;
Hatte Application.ProcessMessages schon mal drin, aber dann rattert er einfach durch (führt AskServerOrClient bereits aus) und bleibt nicht stehen. Ausserdem scheint mir das nicht die optimale Lösung. :(

Hier noch die FormKeyPress Prozedur:
Delphi-Quellcode:
procedure TfrmChat.FormKeyPress(Sender: TObject; var Key: Char);
begin
  User.CheckKey(Key);
end;
Und noch die User.CheckKey Prozedur:
Delphi-Quellcode:
procedure TUser.CheckKey(Key: Char);
begin
  if InputEnabled then
  begin
    if Key = #13 then
    begin
      User.DisableInput;
    end
    else
    begin
      NextKey := Key;
    end;
  end;
end;
Ich nehme mir mal das Problem mit dem Durchlaufen vor, zumindest das sollte ja nicht passieren. :shock:
Solltet ihr noch irgendwelchen Code brauchen, sagt Bescheid. Dies ist zumindest meiner Ansicht nach der wichtigste Teil. :)

Ausserdem: Gibt es vielleicht eine Art getch(); Befehl um eine Taste abzufragen für Delphi? Bin bei meiner Google Suche darauf gestossen, leider gibts den Befehl anscheinend nur in C++. GetAsyncKeyState bringt mich nicht wirklich weiter, alle Tasten per Polling abzufragen ist nicht gerade besser :lol: Dann hätte ich eben eine Idee um das Problem mit einem Thread zu lösen.

Cu
Kill0r

Reinhard Kern 13. Aug 2008 15:51

Re: ReadLn() für Fensterprogramme?
 
Zitat:

Zitat von Kill0r
Hallo :)

Ich habe ein Problem welches vielleicht nicht ganz dem normalen Windows-Konzept entspricht und ich bin mir nicht sicher, ob es lösbar ist. Also ich schreibe gerade eine Art Konsolenprogramm, welches aber eigentlich ein normales Windowsprogramm ist mit einem TImage was mir als Anzeige dient (d.h. Ich schreibe den Text welcher ich anzeigen will dort drauf)
...
Kill0r

Hallo,

ein ganz anderer Lösungsansatz: du zeigst den auszugebenden Text z.B. in einem TMemo an (TImage geht auch, wenn es dafür einen Grund gibt). Für die Eingabe von Kommandos legst du jeweils ein Editfenster mit gleicher Breite und 1 Zeile Höhe an die entsprechende Stelle über das TMemo. Bei gleichem Hintergrund und fehlendem Rand ist das Editfenster unsichtbar. Wird die Eingabe mit Enter abgeschlossen, wird das Editfenster gelöscht, die Anzeige 1 Zeile nach oben geschoben und der eingebene Text als nächste Zeile darunter geschrieben.

Damit entfallen alle Probleme mit ProcessMessages oder Threads oder blockierter Anwendung. Es gibt ganz windowskonform ein Eingabecontrol und ein Ausgabecontrol. Die Verwendung unsichtbarer Editfenster zur Dateneingabe ist eine bewährte Methode, die ich z.B. in TStringGrids verwende.

Gruss Reinhard

Kill0r 13. Aug 2008 16:08

Re: ReadLn() für Fensterprogramme?
 
Hi :-D
Ich weiss nicht ob ich lachen oder weinen soll :shock: (Absolut nicht böse gemeint :mrgreen:)
Ziemlich ähnlich wie du es beschrieben hast (einfach alles in einem TMemo) habe ich es in einer früheren Version von dem Programm gelöst. Ich bin eben gerade daran eine Total Revision des Programms durchzuführen, welches schon 2 Jahre auf dem Buckel hat seit der letzten Version. Deswegen will ich auch alles möglichst sauber und ohne grosse Bastelei (nur dort wo es wegen der ungewöhnlichen Bedienung notwendig ist ;)) machen. Da es mit der alten Lösung diverse Probleme wegen dem TMemo gab (Flackern, Scrollen funktionierte nicht richtig, Parsen der Eingabe gestaltete sich schwierig, wenig Gestaltungsfreiheiten usw.) bin ich auf TImage umgestiegen und verwalte die Zeilenumbrüche und was alles dazu gehört selber. Die Anzeige selber funktioniert auch bestens nur eben die Eingabe bereitet mir Sorgen... :?

Siehe Beiträge bezüglich der alten Version:
Eigene Konsole: Problem bei der Eingabe
Form "reagiert" nach Minimieren nicht mehr

Danke für euere Bemühungen :-D

Cu
Kill0r


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