Warum funktioniert crt.readkey nicht im Grafikmodus?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
thosch
Beiträge: 283
Registriert: Mo 10. Jul 2017, 20:32

Warum funktioniert crt.readkey nicht im Grafikmodus?

Beitrag von thosch »

Hallo, wie erhalte ich systemunabhängig und Tastaturyayoutunabhängig die in die Tastatur eingegebenen Zeichen im Grafikmodus systemunabhängig. Gibt es in Lazarus vordefinierte Eingaberoutinen die systemunabhängig auch im Grafikmodus arbeiten? Wenn ja, in welcher(n) Unit(s)?

Warum funktioniert crt.ReadKey nicht im Grafikmodus. Ein Workaround, falls Konsolenausgabe und Grafikausgabe auf verschidene Ausgabebildschirme schreiben, täte es auch, so dass im Grafikmodus die Readkey Ausgabe auf den Grafikbildschirm umgeleitet würde. Geht das und wenn ja, wie. Was muss ich da einstellen in

Windows und was

In Linux?

Ich verwende Windows 10 und Manjario Linux und habe auf meinem Laptop lxle Linux.

PascalDragon
Beiträge: 395
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Warum funktioniert crt.readkey nicht im Grafikmodus?

Beitrag von PascalDragon »

thosch hat geschrieben:
So 21. Nov 2021, 10:29
Hallo, wie erhalte ich systemunabhängig und Tastaturyayoutunabhängig die in die Tastatur eingegebenen Zeichen im Grafikmodus systemunabhängig. Gibt es in Lazarus vordefinierte Eingaberoutinen die systemunabhängig auch im Grafikmodus arbeiten? Wenn ja, in welcher(n) Unit(s)?
Hänge dich in deinem Form an die OnKeyDown und/oder OnKeyUp Ereignisse und schalte KeyPreview des Forms auf True. Du erhältst dann als Parameter die sogenannten Virtual Key Codes (das sind dann die VK_*-Konstanten, die glaube ich in LCLIntf deklariert sind).
thosch hat geschrieben:
So 21. Nov 2021, 10:29
Warum funktioniert crt.ReadKey nicht im Grafikmodus. Ein Workaround, falls Konsolenausgabe und Grafikausgabe auf verschidene Ausgabebildschirme schreiben, täte es auch, so dass im Grafikmodus die Readkey Ausgabe auf den Grafikbildschirm umgeleitet würde. Geht das und wenn ja, wie.
Die Entwicklung von GUI Anwendungen und die von Textanwendungen verfolgen unterschiedliche Programmierparadigmen. Der Hauptthread einer GUI Anwendung wartet im Code des zugehörigen Widgetsets (WinAPI, GTK, Qt, etc.), bis ein Ereignis eintritt (zum Beispiel ein Zeichen wurde eingegeben). Das heißt die Anwendung kann in dieser Zeit nichts anderes ausführen. Kommt dann ein solches Ereignis so wird es durch die verschiedenen Komponenten durchgeleitet bis es letztlich bei der fokussierten Komponente ankommt.
Bei einer Textanwendung ist der Hauptthread jedoch mit zum Beispiel ReadKey beschäftigt und kann dann eben nichts anderes abarbeiten.
Rein prinzipiell hindert einen nichts daran eine graphische Oberfläche mit einer interaktiven Konsolenausgabe zu kombinieren, man muss aber dann wissen was man macht.
FPC Compiler Entwickler

thosch
Beiträge: 283
Registriert: Mo 10. Jul 2017, 20:32

Re: Warum funktioniert crt.readkey nicht im Grafikmodus?

Beitrag von thosch »

Danke! Das mit dem OnKeyDown geht super. so kann ich die VK Codes mhelos ermitteln.

Nun habe ich aber das Phänomen, dass ich gelegentlich andere Zeichen als die auf der ermittelten TAste erwarteten erhalte.

Ich habe ein Arryay:

var
keyboard: array [0..255] of byte

das ich mit den VK Konstanten indiziere um meinen Tastencode zu erhalten.

So wird das keyboard Array abgefragt:

Code: Alles auswählen

     if theMessage=wm_keydown then begin
                                       // fillchar(keyboard,sizeof(keyboard),0);
                                        keyboard[loword(wPar)]:=true;

                                          end;
     if theMessage=wm_keyup then begin

                                                        keyboard[loword(wPar)]:=false;

                                        end;
Und so hier frage ich dann die Tasten ab:

Code: Alles auswählen

    if keyboard[vk_0] and not pressed_0 then begin
        if keyboard[vk_shift] or keyboard[vk_Rshift] then s:=s+'=' else s:=s+'0';                                                                                 
        pressed_0 := true
    end;
    if not keyboard[vk_0] then pressed_0 := false;
Dazu habe ich mir für jede VK_xxx Konstante eine pressed_xxx Konstante gleichen Präfixnamens definiert.

Nun passiert es bei einigen Zeichen, so auch bei der deutschen Tastatur beim Fragezeichen, dass ich dieses zwar mit zusätzlicher Shift Taste auch korrekt bekomme, der Zeichencode wird korrekt angezeigt das Zeichen wird korrekt ausgegeben, aber ohne Shift müsste das 'ß' kommen, was aber nicht passiert.

Warum nicht?

So hier habe ich die Abfrage der Fragezeichentaste meiner deutschen Tastatur abgefragt.

Code: Alles auswählen

    if Keyboard[vk_question] and not pressed_question then   
    begin                                              // Code = 159
       if keyboard[vk_shift] or keyboard[vk_Rshift] then s := s + '?' else s := s + 'ß';
       pressed_question := true;
    end;
    if not keyboard[vk_question] then pressed_question := false;
Warum erhalte ich da dieses 'ß' nicht, als Code erhalte ich bei der Ausgabe für das Fragezeichen den korrekten Code 63, beim 'ß' dagegen den Code 159, der aber nicht für das 'ß' steht und angezeigt wird aber ebenfalls das Fragezeichen.

Warum ist das so und wie kann ich in solcher Situation erreichen, dass das korrekte Zeichen hier das 'ß' wie gewünscht angezeigt wird.

Benutzeravatar
theo
Beiträge: 8710
Registriert: Mo 11. Sep 2006, 19:01

Re: Warum funktioniert crt.readkey nicht im Grafikmodus?

Beitrag von theo »

Ich weiss nicht, ob ich dich richtig verstehe.

Wenn du wissen möchtest, welche Taste gedrückt wurde, verwende:
OnKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState

Wenn du wissen möchtest, welches Zeichen/Buchstabe dabei herumkommt, verwende:
OnUTF8KeyPress(Sender: TObject; var UTF8Key: TUTF8Char);

PascalDragon
Beiträge: 395
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Warum funktioniert crt.readkey nicht im Grafikmodus?

Beitrag von PascalDragon »

thosch hat geschrieben:
Mo 22. Nov 2021, 10:39
Nun passiert es bei einigen Zeichen, so auch bei der deutschen Tastatur beim Fragezeichen, dass ich dieses zwar mit zusätzlicher Shift Taste auch korrekt bekomme, der Zeichencode wird korrekt angezeigt das Zeichen wird korrekt ausgegeben, aber ohne Shift müsste das 'ß' kommen, was aber nicht passiert.

Warum nicht?

So hier habe ich die Abfrage der Fragezeichentaste meiner deutschen Tastatur abgefragt.

Code: Alles auswählen

    if Keyboard[vk_question] and not pressed_question then   
    begin                                              // Code = 159
       if keyboard[vk_shift] or keyboard[vk_Rshift] then s := s + '?' else s := s + 'ß';
       pressed_question := true;
    end;
    if not keyboard[vk_question] then pressed_question := false;
Warum erhalte ich da dieses 'ß' nicht, als Code erhalte ich bei der Ausgabe für das Fragezeichen den korrekten Code 63, beim 'ß' dagegen den Code 159, der aber nicht für das 'ß' steht und angezeigt wird aber ebenfalls das Fragezeichen.
Ich bekommen bei mir (Win64) immer die 219, was $DB ist und damit VK_OEM_4 entspricht (die Taste hat schließlich keine international standardmäßige Belegung). Der Tastencode ändert sich durch die Modifier nicht (der generierte Buchstabe jedoch schon).
FPC Compiler Entwickler

thosch
Beiträge: 283
Registriert: Mo 10. Jul 2017, 20:32

Re: Warum funktioniert crt.readkey nicht im Grafikmodus?

Beitrag von thosch »

Wie aber bekomme ich da jetzt die von mir gewünschte Taste, dh. den Buchstaben?

Offenbar wird mir bei diesen strittigen Codes ein falscher Buchstabe angezeigt, nicht der den ich mit s := s + '<mein gewünschter Buchstabe>'; haben will. Da wird vom System automatisch was anderes hin geschrieben.

Warum und wie kann ich das verhindern und erreichen dass das von mir gewollte Zeichen ausgegeben wird?

thosch
Beiträge: 283
Registriert: Mo 10. Jul 2017, 20:32

Re: Warum funktioniert crt.readkey nicht im Grafikmodus?

Beitrag von thosch »

theo hat geschrieben: Wenn du wissen möchtest, welches Zeichen/Buchstabe dabei herumkommt, verwende:
OnUTF8KeyPress(Sender: TObject; var UTF8Key: TUTF8Char);
Dake für den Tipp mit UTF8Keypress, da sehe ich welches Zeichen auf der Taste liegt.

Aber wie komme ich an den UTF8 Code systemunabhängig?

In einer Consolenanwendung zum Beispiel.

Da gibt es ja kein Formular.

Der Sinn des ganzen ist, ich will eine eigene Readkey Funktion bauen die wie crt.Readkey arbeitet, aber im Grafikmodus verwendet werden kann und das auf allen von Freepascal unterstützten Plattformen. Auch ohne LCL, sonst wäre es ja einfach.

Ich habe eine LCL unabhängige Grafikbibliothek für die ich das brauche.




Habe soeben noch UTF8 Funktionen in Freepascal in der Doku gefunden, da werd ich mal schauen ob ich da meine Codes passend konvertieren kann.

.

PascalDragon
Beiträge: 395
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Warum funktioniert crt.readkey nicht im Grafikmodus?

Beitrag von PascalDragon »

thosch hat geschrieben:
Mo 22. Nov 2021, 14:18
Wie aber bekomme ich da jetzt die von mir gewünschte Taste, dh. den Buchstaben?
Du musst hier unterscheiden zwischen Taste und Buchstabe. Die Taste ist immer die gleiche, egal welches Tastaturlayout (zumindest bei diesen Spezialtasten, bei z.B. y und z bei DE vs. EN sieht das anders aus). Und OnKeyDown und OnKeyUp geben dir eben den Code der Taste zurück. Willst du den Buchstaben, den das Tastaturlayout dir generiert, dann musst du OnKeyPress bzw. OnUTF8KeyPress nutzen. Du musst dir dann eben diese drei Ereignisse passend zusammen basteln, damit du was ähnliches wie ReadKey bekommst (was letztlich einfach von der Zeicheneingabe der Konsole liest, wo es das Konzept Taste und Buchstabe nicht derart getrennt gibt).
FPC Compiler Entwickler

thosch
Beiträge: 283
Registriert: Mo 10. Jul 2017, 20:32

Re: Warum funktioniert crt.readkey nicht im Grafikmodus?

Beitrag von thosch »

Danke soweit, das funkt erst mal, ich habe in meinem Tstbeispiel beide Ereigniss drin, sohol OnKeyPress als auch OnUTF8Keypress.

Funktioniert super. Genau was ich gesucht habe!

Antworten