Tastaturabfrage optimieren, wie?

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

Tastaturabfrage optimieren, wie?

Beitrag von thosch »

Hallo,

ich habe folgenden Code:

Code: Alles auswählen

 
unit MyKey;
 
Interface
 
uses sysutils, classes, crt;
 
type
  TKeyEvent = record
    CharCode: byte;
    ScanCode: byte;
    VirtCode: byte;                 //wegen Windows, hier trägt die Abfrageroutine den VK_XXX Code ein
    ShiftState: TShiftState;
    ShiftDirection: byte;         //Linke oder rechte Shift, Ctrl, ALt Taste, braucht noch plattformabhängige Zusatzabfrage
  end;
 
  function GetVKeyOf(bioskey: word): TKeyEvent;
  function GetKeyCode: word;
 
 
implementation
 
  function GetVKeyOf(bioskey: word): TKeyEvent;
  var
    VKey: TKeyEvent;
  begin
    if (bioskey and $ff) = 0 then
    begin
      case bioskey shr 8 of
        $47: writeln('Home/Pos1');
        $48: writeln('Pfeil hoch');
        $49: writeln('Seite hoch');
        $4B: writeln('Pfeil links');
        $4D: writeln('Pfeil rechts');
        $4F: writeln('End');
        $50: writeln('Pfeil ab');
        $51: writeln('Seite runter');
      end;
      VKey.ScanCode := bioskey shr 8;
    end
    else
    begin
      case chr(bioskey and $ff) of
        'a'..'z':
          begin
            VKey.CharCode := bioskey and $ff;
            VKey.ScanCode := 0;
            VKey.VirtCode := VK_A + (bioskey and $ff) - VK_A;
            VKey.ShiftState := [];           
          end;
        'ä','ö','ü','ß':
          begin
            VKey.CharCode := bioskey and $ff;
            VKey.ScanCode := 0;
            VKey.VirtCode := 0;
            VKey.ShiftState := [];           
          end;
        'A'..'Z':
          begin
            VKey.CharCode := bioskey and $ff;
            VKey.ScanCode := 0;
            VKey.VirtCode := VK_A + (bioskey and $ff) - VK_A;
            VKey.ShiftState := [ssShift];           
          end;
        'Ä','Ö','Ü':
          begin
            VKey.CharCode := bioskey and $ff;
            VKey.ScanCode := 0;
            VKey.VirtCode := 0;
            VKey.ShiftState := [ssShift];           
          end;
        else
          begin
            VKey.CharCode := bioskey and $ff;
            VKey.ScanCode := 0;
            VKey.VirtCode := 0;
            VKey.ShiftState := [];           
          end;
      end;
    end;
    GetVKeyOf := VKey;
  end;
 
  function GetKeyCode: word;
  var
    ch: char; chb: byte; scan: byte; KeyCode: word;
  begin
    GetKeyCode := 0;
    if keypressed then
    begin
      ch := readkey; chb := ord(ch);
      if chb = 0 then scan := ord(readkey);
      KeyCode := (scan shl 8) + chb;
      GetKeyCode := KeyCode;
    end;
  end;
 
end.
 



Code: Alles auswählen

 
program MyKeytest;
 
uses sysutils, classes, crt, MyKey;
 
var
  KeyEv: TKeyEvent;   //Das eigentliche Tastaturereignis
  KeyWd: word;          //nur zum Testen, ob der KeyCode richtig ankommt
 
begin
  REPEAT
    KeyEv := GetVKeyOf(GetKeyCode);
    if keypressed then write(KeyEv.VirtCode);
    case KeyEv.Scancode of
     $47: begin write('Home/Pos1 ---'); writeln(KeyEv.Scancode); end;
     $48: begin write('Pfeil hoch ---'); writeln(KeyEv.Scancode); end;
     $49: begin write('Seite hoch ---'); writeln(KeyEv.Scancode); end;
     $4B: begin write('Pfeil links ---'); writeln(KeyEv.Scancode); end;
     $4D: begin write('Pfeil rechts ---'); writeln(KeyEv.Scancode); end;
     $4F: begin write('End ---'); writeln(KeyEv.Scancode); end;
     $50: begin write('Pfeil ab ---'); writeln(KeyEv.Scancode); end;
     $51: begin write('Seite ab ---'); writeln(KeyEv.Scancode); end;
     VK_HOME: begin write('H o m e'); writeln(KeyEv.Scancode); end;
     else if keypressed then writeln('Zeichen: ',KeyEv.CharCode,' Scan: ', KeyEv.Scancode);
    end;
 
  UNTIL KeyEv.CharCode and 15 = 27;
end.
 


Ich will nun die Codes, die ich nicht extra in der CASE Anweisung aufgeführt habe, einfach anzeigen, zunächst den Zahlenwert des Codes. Leider funktioniert das nicht so, wie ich es haben will. Wenn ich die Buchstabentasten A-Z,a-z,ä.ö,ü,Ä,Ö,Ü, ... drücke, muss ich mehrmals drücken, bevor ich den Tastencode A = 65 überhaupt erhalte. Warum ist das so, was muss ich wie anders machen, um die Tastencodes zu erhalten? Bei einigen Scancodes tritt das Problem auch auf. Wie PgDn.

Das Ganze soll Plattformübergreifend werden, deshalb habe ich diese Variante mit ReadKey aus der Unit CRT gewählt, auch weil ich da den Ablauf noch am besten verstehe. Ich gehe dann halt von den Bios Codes aus, die ja in jedem Rechner erst mal vorhanden sein dürften.

Mit dem doppelten "writeln" sehe ich ob die Abfragen und case Anweisungen korrekt durchlaufen werden.

Gibt es einen besseren Weg zur Tastaturabfrage und wenn ja, welchen. GetMessage ist plattformabhängig, ich suche aber einen Weg, der in jedem von FPC unterstützten Betriebssystem mit wirklich jedem Bildschirmmodus funktioniert.

.
Zuletzt geändert von thosch am Do 6. Dez 2018, 10:11, insgesamt 3-mal geändert.

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Tastaturabfrage funktioniert nicht

Beitrag von siro »

Du hast in deiner Funktion GetKeyCode folgende Zeile:

Code: Alles auswählen

GetKeyCode := KeyCode; 


KeyCode wird aber nirgends gesetzt ???
Somit dürfte dein Ergebnis recht zufällig ausfallen, oder verstehe ich da etwas falsch ?
Soll das evtl.

Code: Alles auswählen

GetKeyCode := DosKeyCode; 

heissen ?

Siro
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Tastaturabfrage funktioniert nicht

Beitrag von siro »

passt jetzt grade hier rein:
Ich habe eine 20 Jahre alte Unit von mir gefunden zwecks Tastaturabfrage, vielleicht kann davon noch irgend jemand was verwenden.
Hier hab ich auch die Konstanten der Tastencodes festgelegt.

Code: Alles auswählen

 
              {*********************************************}
              { Compiler      : Boorland Pascal 7.0         }
              {               : Turbo Pascal    6.0         }
              { Zielplattform : Protected Mode              }
              {                 und Real Mode               }
              { Update        : 09.02.1998 Siro             }
              { Funktion      : PC-Tastatur-Routinen        }
              {*********************************************}
 
      {-------------------------------------------------------------}
      { fuer Turbo-Pascal muss folgende Zeile hinter IMPLEMENTATION }
      { eingefuegt werden:                                          }
      {                                                             }
      {             CONST Seg0040 = $0040;                          }
      {                                                             }
      { bei Boorland Pascal MUSS diese Zeile entfernt werden        }
      {-------------------------------------------------------------}
 
UNIT KB;
 
INTERFACE
 
CONST Seg0040 = $0040;   { Zeile ausklammern bei Borland Pascal }
 
CONST { Definition der einzelnen Tastencodes }
 
      KB_None       =   0;   { 0 = kein Tastencode }
 
      KB_ESC        =  27;   { Esc  Taste                }
      KB_Space      =  32;   { Leer Taste                }
      KB_Return     =  13;   { Return Taste              }
      KB_Enter      =  13;   { Entertaste = Return Taste }
      KB_BackSlash  =  92;   { Schraegstrich \           }
      KB_BackSpace  =   8;   { Rckschritt               }
      KB_TabRight   =   9;   { Tabulator rechts          }
      KB_TabLeft    = 271;   { Tabulator links, in Verbindung mit Shift }
 
      KB_Left  = 331;        { Cursor Links    }
      KB_Right = 333;        { Cursor Rechts   }
      KB_Home  = 327;        { Cursor Home     }
      KB_End   = 335;        { Cursor End      }
      KB_PgUp  = 329;        { Seite aufw„rts  }
      KB_PgDn  = 337;        { Seite abw„rts   }
      KB_Up    = 328;        { Cursor aufw„rts }
      KB_Down  = 336;        { Cursor abw„rts  }
      KB_Ins   = 338;        { Insert Taste    }
      KB_Del   = 339;        { Delete Taste    }
 
      KB_F1  = 315;          { Funktionstaste F1  }
      KB_F2  = 316;          { Funktionstaste F2  }
      KB_F3  = 317;          { Funktionstaste F3  }
      KB_F4  = 318;          { Funktionstaste F4  }
      KB_F5  = 319;          { Funktionstaste F5  }
      KB_F6  = 320;          { Funktionstaste F6  }
      KB_F7  = 321;          { Funktionstaste F7  }
      KB_F8  = 322;          { Funktionstaste F8  }
      KB_F9  = 323;          { Funktionstaste F9  }
      KB_F10 = 324;          { Funktionstaste F10 }
      KB_F11 = 389;          { Funktionstaste F11 }
      KB_F12 = 390;          { Funktionstaste F12 }
 
      KB_Shift_F1  = 340;    { Funktionstaste F1  mit Shifttaste }
      KB_Shift_F2  = 341;    { Funktionstaste F2  mit Shifttaste }
      KB_Shift_F3  = 342;    { Funktionstaste F3  mit Shifttaste }
      KB_Shift_F4  = 343;    { Funktionstaste F4  mit Shifttaste }
      KB_Shift_F5  = 344;    { Funktionstaste F5  mit Shifttaste }
      KB_Shift_F6  = 345;    { Funktionstaste F6  mit Shifttaste }
      KB_Shift_F7  = 346;    { Funktionstaste F7  mit Shifttaste }
      KB_Shift_F8  = 347;    { Funktionstaste F8  mit Shifttaste }
      KB_Shift_F9  = 348;    { Funktionstaste F9  mit Shifttaste }
      KB_Shift_F10 = 349;    { Funktionstaste F10 mit Shifttaste }
      KB_Shift_F11 = 391;    { Funktionstaste F11 mit Shifttaste }
      KB_Shift_F12 = 392;    { Funktionstaste F12 mit Shifttaste }
 
      KB_CTRL_A =  1;        { "A" Taste mit CTRL-Taste }
      KB_CTRL_B =  2;        { "B" Taste mit CTRL-Taste }
      KB_CTRL_C =  3;        { "C" Taste mit CTRL-Taste }
      KB_CTRL_D =  4;        { "D" Taste mit CTRL-Taste }
      KB_CTRL_E =  5;        { "E" Taste mit CTRL-Taste }
      KB_CTRL_F =  6;        { "F" Taste mit CTRL-Taste }
      KB_CTRL_G =  7;        { "G" Taste mit CTRL-Taste }
      KB_CTRL_H =  8;        { "H" Taste mit CTRL-Taste }
      KB_CTRL_I =  9;        { "I" Taste mit CTRL-Taste }
      KB_CTRL_J = 10;        { "J" Taste mit CTRL-Taste }
      KB_CTRL_K = 11;        { "K" Taste mit CTRL-Taste }
      KB_CTRL_L = 12;        { "L" Taste mit CTRL-Taste }
      KB_CTRL_M = 13;        { "M" Taste mit CTRL-Taste }
      KB_CTRL_N = 14;        { "N" Taste mit CTRL-Taste }
      KB_CTRL_O = 15;        { "O" Taste mit CTRL-Taste }
      KB_CTRL_P = 16;        { "P" Taste mit CTRL-Taste }
      KB_CTRL_Q = 17;        { "Q" Taste mit CTRL-Taste }
      KB_CTRL_R = 18;        { "R" Taste mit CTRL-Taste }
      KB_CTRL_S = 19;        { "S" Taste mit CTRL-Taste }
      KB_CTRL_T = 20;        { "T" Taste mit CTRL-Taste }
      KB_CTRL_U = 21;        { "U" Taste mit CTRL-Taste }
      KB_CTRL_V = 22;        { "V" Taste mit CTRL-Taste }
      KB_CTRL_W = 23;        { "W" Taste mit CTRL-Taste }
      KB_CTRL_X = 24;        { "X" Taste mit CTRL-Taste }
      KB_CTRL_Y = 25;        { "Y" Taste mit CTRL-Taste }
      KB_CTRL_Z = 26;        { "Z" Taste mit CTRL-Taste }
 
      KB_CTRL_F1  = 350;     { Funktionstaste F1  mit CTRL-Taste }
      KB_CTRL_F2  = 351;     { Funktionstaste F2  mit CTRL-Taste }
      KB_CTRL_F3  = 352;     { Funktionstaste F3  mit CTRL-Taste }
      KB_CTRL_F4  = 353;     { Funktionstaste F4  mit CTRL-Taste }
      KB_CTRL_F5  = 354;     { Funktionstaste F5  mit CTRL-Taste }
      KB_CTRL_F6  = 355;     { Funktionstaste F6  mit CTRL-Taste }
      KB_CTRL_F7  = 356;     { Funktionstaste F7  mit CTRL-Taste }
      KB_CTRL_F8  = 357;     { Funktionstaste F8  mit CTRL-Taste }
      KB_CTRL_F9  = 358;     { Funktionstaste F9  mit CTRL-Taste }
      KB_CTRL_F10 = 359;     { Funktionstaste F10 mit CTRL-Taste }
      KB_CTRL_F11 = 393;     { Funktionstaste F11 mit CTRL-Taste }
      KB_CTRL_F12 = 394;     { Funktionstaste F12 mit CTRL-Taste }
 
      KB_CTRL_Left  = 371;   { Cursor Links  mit CTRL-Taste }
      KB_CTRL_Right = 322;   { Cursor Rechts mit CTRL-Taste }
      KB_CTRL_Home  = 375;   { Cursor Home   mit CTRL-Taste }
      KB_CTRL_End   = 373;   { Cursor End    mit CTRL-Taste }
      KB_CTRL_PgUp  = 388;   { PgUp-Taste    mit CTRL-Taste }
      KB_CTRL_PgDn  = 374;   { PgDn-Taste    mit CTRL-Taste }
 
      KB_ALT_1 = 376;        { "1" Taste mit ALT-Taste }
      KB_ALT_2 = 377;        { "2" Taste mit ALT-Taste }
      KB_ALT_3 = 378;        { "3" Taste mit ALT-Taste }
      KB_ALT_4 = 379;        { "4" Taste mit ALT-Taste }
      KB_ALT_5 = 380;        { "5" Taste mit ALT-Taste }
      KB_ALT_6 = 381;        { "6" Taste mit ALT-Taste }
      KB_ALT_7 = 382;        { "7" Taste mit ALT-Taste }
      KB_ALT_8 = 383;        { "8" Taste mit ALT-Taste }
      KB_ALT_9 = 384;        { "9" Taste mit ALT-Taste }
      KB_ALT_0 = 385;        { "0" Taste mit ALT-Taste }
 
      KB_ALT_A = 286;        { "A" Taste mit ALT-Taste }
      KB_ALT_B = 304;        { "B" Taste mit ALT-Taste }
      KB_ALT_C = 302;        { "C" Taste mit ALT-Taste }
      KB_ALT_D = 288;        { "D" Taste mit ALT-Taste }
      KB_ALT_E = 274;        { "E" Taste mit ALT-Taste }
      KB_ALT_F = 289;        { "F" Taste mit ALT-Taste }
      KB_ALT_G = 290;        { "G" Taste mit ALT-Taste }
      KB_ALT_H = 291;        { "H" Taste mit ALT-Taste }
      KB_ALT_I = 279;        { "I" Taste mit ALT-Taste }
      KB_ALT_J = 292;        { "J" Taste mit ALT-Taste }
      KB_ALT_K = 293;        { "K" Taste mit ALT-Taste }
      KB_ALT_L = 294;        { "L" Taste mit ALT-Taste }
      KB_ALT_M = 306;        { "M" Taste mit ALT-Taste }
      KB_ALT_N = 305;        { "N" Taste mit ALT-Taste }
      KB_ALT_O = 280;        { "O" Taste mit ALT-Taste }
      KB_ALT_P = 281;        { "P" Taste mit ALT-Taste }
      KB_ALT_Q = 272;        { "Q" Taste mit ALT-Taste }
      KB_ALT_R = 275;        { "R" Taste mit ALT-Taste }
      KB_ALT_S = 287;        { "S" Taste mit ALT-Taste }
      KB_ALT_T = 276;        { "T" Taste mit ALT-Taste }
      KB_ALT_U = 278;        { "U" Taste mit ALT-Taste }
      KB_ALT_V = 303;        { "V" Taste mit ALT-Taste }
      KB_ALT_W = 273;        { "W" Taste mit ALT-Taste }
      KB_ALT_X = 301;        { "X" Taste mit ALT-Taste }
      KB_ALT_Y = 277;        { "Y" Taste mit ALT-Taste }
      KB_ALT_Z = 44;         { "Z" Taste mit ALT-Taste }
 
      KB_ALT_F1  = 360;      { Funktionstaste F1  mit ALT-Taste }
      KB_ALT_F2  = 361;      { Funktionstaste F2  mit ALT-Taste }
      KB_ALT_F3  = 362;      { Funktionstaste F3  mit ALT-Taste }
      KB_ALT_F4  = 363;      { Funktionstaste F4  mit ALT-Taste }
      KB_ALT_F5  = 364;      { Funktionstaste F5  mit ALT-Taste }
      KB_ALT_F6  = 365;      { Funktionstaste F6  mit ALT-Taste }
      KB_ALT_F7  = 366;      { Funktionstaste F7  mit ALT-Taste }
      KB_ALT_F8  = 367;      { Funktionstaste F8  mit ALT-Taste }
      KB_ALT_F9  = 368;      { Funktionstaste F9  mit ALT-Taste }
      KB_ALT_F10 = 369;      { Funktionstaste F10 mit ALT-Taste }
      KB_ALT_F11 = 395;      { Funktionstaste F11 mit ALT-Taste }
      KB_ALT_F12 = 396;      { Funktionstaste F12 mit ALT-Taste }
 
      KB_ALT_SPACE = 258;    { SPACE Taste mit ALT-TASTE }
      KB_Cursor_5  = 332;    { mittlere Cursor 5 }
 
Type YesNoRangeType   = #13..#127;   { gueltige Character fuer YES NO }
Type KeyCodeRangeType = 1..396;      { gueltige Tastencodes }
 
Procedure KB_Clear;
Procedure KB_Read (Var KeyCode : Word);
Function  KB_Pressed           : Boolean;
Function  KB_CtrlPressed       : Boolean;
Function  KB_AltPressed        : Boolean;
Function  KB_ScrollPressed     : Boolean;
Function  KB_NumPressed        : Boolean;
Function  KB_CapsPressed       : Boolean;
Function  KB_InsPressed        : Boolean;
Function  KB_ShiftPressed      : Boolean;
Function  KB_ShiftRightPressed : Boolean;
Function  KB_ShiftLeftPressed  : Boolean;
 
Function  KB_ScrollActive      : Boolean;
Function  KB_NumActive         : Boolean;
Function  KB_CapsActive        : Boolean;
Function  KB_InsActive         : Boolean;
 
Function  KB_Last:Word;
Procedure KB_Wait      (KeyCode        : KeyCodeRangeType);
Function  KB_YesNo     (YesChar,NoChar : YesNoRangeType):Boolean;
Procedure KB_Put       (KeyCode        : KeyCodeRangeType);
Procedure KB_PutString (S:String);
{****************************************************************************}
 
IMPLEMENTATION
 
CONST
 
BIOS_READ_PTR  = $001A;  { BIOS-Variable Tastatur-Lesezeiger      0040:001A }
BIOS_LAST_PTR  = $001C;  { BIOS-Variable Zeiger auf letzte Taste  0040:001C }
BIOS_START_PTR = $0080;  { Zeiger auf Start des Tastaturpuffers   0040:0080 }
BIOS_END_PTR   = $0082;  { Zeiger auf Ende  des Tastaturpuffers   0040:0082 }
 
BIOS_STATUS_1  = $0017;  { BIOS-Variable Tastatur-Status-Byte 1   0040:0017 }
BIOS_STATUS_2  = $0018;  { BIOS-Variable Tastatur-Status-Byte 2   0040:0018 }
 
NEW_BUF_OFFSET = $0200;  { neuer Tastaturpuffer Startoffset }
 
Bit_ShiftRight = $01;    { Bits im BIOS Statusbyte }
Bit_ShiftLeft  = $02;
Bit_Shift      = $03;
Bit_Ctrl       = $04;
Bit_Alt        = $08;
Bit_Scroll     = $10;
Bit_Num        = $20;
Bit_Caps       = $40;
Bit_Ins        = $80;
 
VAR
 
OldExitProc     : Pointer;       { Orginal Exit Procedure }
 
org_start_ptr : Word;  { Orginal Start des Tastatur-Puffers }
org_end_ptr   : Word;  { Orginal Ende  des Tastatur-Puffers }
 
LastKey       : Word;  { enth„lt stets die zuletzt gelesene Taste }
                       { die mit Readkey gelesen wurde }
 
Function KB_Last:Word; Assembler;
ASM MOV AX,LastKey
    RET
end;
{============================================================================}
Procedure KB_Clear; Assembler;
 
           { loescht den kompletten Tastaturpuffer }
 
ASM  MOV AX,Seg0040             { Bios Datensegment }
     MOV ES,AX                  { ueber AX }
     PUSHF                      { IRQ-Flag merken }
     CLI                        { Interrupts sperren }
     MOV AX,ES:[BIOS_START_PTR] { AX = Start des Puffers BIOS }
     MOV ES:[BIOS_READ_PTR],AX  { naechstes Zeichen = Pufferstart BIOS }
     MOV ES:[BIOS_LAST_PTR],AX  { letztes   Zeichen = Pufferstart BIOS }
     POPF                       { IRQ-Flag restaurieren }
     RET
end;
{============================================================================}
Function KB_ShiftRightPressed:Boolean; Assembler;
 
 { liefert True, wenn rechte Shifttaste momentan gedrueckt, sonst False. }
 
ASM  XOR  AX,AX                  { False }
     MOV  BX,Seg0040             { Bios Datensegment }
     MOV  ES,BX
     TEST Byte Ptr ES:[BIOS_STATUS_1],Bit_ShiftRight
     JZ   @@1
     INC  AX                     { True }
@@1: RET
end;
{============================================================================}
Function KB_ShiftLeftPressed:Boolean; Assembler;
 
 { liefert True, wenn linke Shifttaste momentan gedrueckt, sonst False. }
 
ASM  XOR  AX,AX                  { False }
     MOV  BX,Seg0040             { Bios Datensegment }
     MOV  ES,BX
     TEST Byte Ptr ES:[BIOS_STATUS_1],Bit_ShiftLeft
     JZ   @@1
     INC  AX                     { True }
@@1: RET
end;
{============================================================================}
Function KB_ShiftPressed:Boolean; Assembler;
 
 { liefert True, wenn eine Shifttaste momentan gedrueckt, sonst False. }
 
ASM  XOR  AX,AX
     MOV  BX,Seg0040             { Bios Datensegment }
     MOV  ES,BX
     TEST Byte Ptr ES:[BIOS_STATUS_1],Bit_Shift
     JZ   @@1
     INC  AX
@@1: RET
end;
{============================================================================}
Function KB_CtrlPressed:Boolean; Assembler;
 
  { liefert True, wenn die CTRL-Taste momentan gedrueckt, sonst False. }
 
ASM  XOR  AX,AX
     MOV  BX,Seg0040             { Bios Datensegment }
     MOV  ES,BX
     TEST Byte Ptr ES:[BIOS_STATUS_1],Bit_Ctrl
     JZ   @@1
     INC  AX
@@1: RET
end;
{============================================================================}
Function KB_AltPressed:Boolean; Assembler;
   { liefert True, wenn die ALT-Taste momentan gedrueckt, sonst False. }
 
ASM  XOR  AX,AX
     MOV  BX,Seg0040             { Bios Datensegment }
     MOV  ES,BX
     TEST Byte Ptr ES:[BIOS_STATUS_1],Bit_Alt
     JZ   @@1
     INC  AX
@@1: RET
end;
{============================================================================}
Function KB_ScrollActive:Boolean; Assembler;
 
   { liefert True, wenn die SCROLL-Taste aktiviert ist, sonst False. }
 
ASM   XOR  AX,AX
      MOV  BX,Seg0040             { Bios Datensegment }
      MOV  ES,BX
      TEST Byte Ptr ES:[BIOS_STATUS_1],Bit_Scroll
      JZ   @@1
      INC  AX
@@1:  RET
end;
{============================================================================}
Function KB_NumActive:Boolean; Assembler;
 
  { liefert True, wenn die NUMLOCK-Taste aktiviert ist, sonst False. }
 
ASM   XOR  AX,AX
      MOV  BX,Seg0040             { Bios Datensegment }
      MOV  ES,BX
      TEST Byte Ptr ES:[BIOS_STATUS_1],Bit_Num
      JZ   @@1
      INC  AX
@@1:  RET
end;
{============================================================================}
Function KB_CapsActive:Boolean; Assembler;
 
   { liefert True, wenn die CAPSLOCK-Taste aktiviert ist, sonst False. }
 
ASM   XOR  AX,AX
      MOV  BX,Seg0040             { Bios Datensegment }
      MOV  ES,BX
      TEST Byte Ptr ES:[BIOS_STATUS_1],Bit_Caps
      JZ   @@1
      INC  AX
@@1:  RET
end;
{============================================================================}
Function KB_InsActive:Boolean; Assembler;
 
  { liefert True, wenn die INSERT-Taste aktiviert ist, sonst False. }
 
ASM   XOR  AX,AX
      MOV  BX,Seg0040             { Bios Datensegment }
      MOV  ES,BX
      TEST Byte Ptr ES:[BIOS_STATUS_1],Bit_Ins
      JZ   @@1
      INC  AX
@@1:  RET
end;
{============================================================================}
Function KB_ScrollPressed:Boolean; Assembler;
 
 { liefert True, wenn die SCROLL-Taste momentan gedrueckt ist, sonst False. }
 
ASM   XOR  AX,AX
      MOV  BX,Seg0040             { Bios Datensegment }
      MOV  ES,BX
      TEST Byte Ptr ES:[BIOS_STATUS_2],Bit_Scroll
      JZ   @@1
      INC  AX
@@1:  RET
end;
{============================================================================}
Function KB_NumPressed:Boolean; Assembler;
 
 { liefert True, wenn die NUMLOCK-Taste momentan gedrueckt ist, sonst False.}
 
ASM   XOR  AX,AX
      MOV  BX,Seg0040             { Bios Datensegment }
      MOV  ES,BX
      TEST Byte Ptr ES:[BIOS_STATUS_2],Bit_Num
      JZ   @@1
      INC  AX
@@1:  RET
end;
{============================================================================}
Function KB_CapsPressed:Boolean; Assembler;
 
 { liefert True, wenn die CAPSLOCK-Taste momentan gedrueckt ist, sonst False. }
 
ASM   XOR  AX,AX
      MOV  BX,Seg0040             { Bios Datensegment }
      MOV  ES,BX
      TEST Byte Ptr ES:[BIOS_STATUS_2],Bit_Caps
      JZ   @@1
      INC  AX
@@1:  RET
end;
{============================================================================}
Function KB_InsPressed:Boolean; Assembler;
 
{ liefert True, wenn die INSERT-Taste momentan gedrueckt ist, sonst False.}
 
ASM   XOR  AX,AX
      MOV  BX,Seg0040             { Bios Datensegment }
      MOV  ES,BX
      TEST Byte Ptr ES:[BIOS_STATUS_2],Bit_Ins
      JZ   @@1
      INC  AX
@@1:  RET
end;
{============================================================================}
Function KB_pressed:Boolean; Assembler;
 
      { liefert TRUE, wenn sich mindestens ein Zeichen im }
      { Tastaturpuffer befindet, ansonsten FALSE.         }
 
ASM    PUSHF                       { IRQ-FLAG merken }
       CLI                         { Interrupts sperren }
       XOR  AX,AX
       MOV  BX,Seg0040             { Bios Datensegment }
       MOV  ES,BX
       MOV  BX,ES:[BIOS_READ_PTR]  { BIOS-Lesezeiger }
       CMP  BX,ES:[BIOS_LAST_PTR]  { = BIOS Letztezeiger ? }
       JE   @@1                    { dann kein Zeichen im Puffer }
       INC  AX                     { sonst TRUE, Zeichen im Puffer }
@@1:   POPF                        { IRQ-Flag restaurieren }
       RET
end;
{============================================================================}
Procedure KB_read(Var KeyCode:Word); ASSEMBLER;
 
   { Liest wenn vorhanden ein Zeichen aus dem Tastaturpuffer }
   { in die uebergebene Variable KeyCode ein.                }
   { Befindet sich kein Zeichen im Tastaturpuffer, so wird   }
   { solange gewartet bis ein Zeichen vorhanden ist.         }
 
ASM         XOR  AX,AX
            MOV  DI,Seg0040             { Bios Datensegment }
            MOV  ES,DI
            MOV  BX,ES:[BIOS_READ_PTR]  { BIOS-Lesezeiger }
@@wait:     CMP  BX,ES:[BIOS_LAST_PTR]  { = BIOS Letztezeiger ? }
            JE   @@wait                 { dann kein Zeichen im Puffer }
            MOV  AX,ES:[BX]             { sonst Code aus Puffer holen }
            CMP  AL,224                 { extended Code ? }
            JE   @@extended             { ja }
            CMP  AL,240                 { extended Code ? }
            JE   @@extended             { ja }
            CMP  AL,0                   { extended Code ? }
            JZ   @@extended             { ja }
            XOR  AH,AH                  { sonst normale Ascii Taste }
            JMP  @@normal
@@extended: MOV  AL,1                   { AL Code + 256 }
            XCHG AL,AH
@@normal:   ADD  BX,2                   { BIOS Lesezeiger + 2 }
            CMP  BX,ES:[BIOS_END_PTR]   { am Ende des BIOS Puffer ? }
            JNE  @@1                    { nein }
            MOV  BX,ES:[BIOS_START_PTR] { sonst an Start des BIOS Puffers }
@@1:        MOV  ES:[BIOS_READ_PTR],BX  { BIOS Lesezeiger speichern }
            LES  BX,KeyCode             { Adresse der Variablen KeyCode }
            MOV  ES:[BX],AX             { KeyCode uebergeben }
            MOV  LastKey,AX             { zuletzt gelesen Taste merken }
end;
{============================================================================}
Procedure KB_put(KeyCode:KeyCodeRangeType); Assembler;
 
  { alle Register retten wird speater von Mouse Unit aufgerufen }
 
   ASM PUSH AX
       PUSH BX
       PUSH CX
       PUSH ES
       MOV  AX,KeyCode                 { Tastencode nach AX }
       OR   AH,AH                      { erweiterter CODE ? }
       JZ   @@1                        { nein, dann ok }
       SUB  AX,256                     { sonst Tastencode - 256 }
       XCHG AL,AH                      { AL=0 AH=Code }
@@1:   MOV  DI,Seg0040                 { Bios Datensegment }
       MOV  ES,DI                      { nach ES }
       PUSHF                           { IRQ-Flag merken }
       CLI                             { Interrupts sperren }
       MOV  BX,ES:[BIOS_Last_Ptr]      { Einlesezeiger }
       MOV  CX,BX                      { nach CX }
       ADD  CX,2                       { +2 }
       CMP  CX,ES:[BIOS_End_Ptr]       { am Ende des Puffers  ? }
       JNE  @@2                        { nein, dann ok }
       MOV  CX,ES:[BIOS_Start_Ptr]     { sonst Puffer von vorn }
@@2:   CMP  CX,ES:[BIOS_Read_Ptr]      { Einlesezeiger = Auslesezeiger }
       JE   @@3                        { ja, Puffer voll Exit }
       MOV  ES:[BX],AX                 { nein dann Zeichen eintragen }
       MOV  ES:[BIOS_Last_Ptr],CX      { Einlesezeiger speichern }
@@3:   POPF                            { IRQ-FLAG restaurieren }
       POP  ES
       POP  CX
       POP  BX
       POP  AX
end;
{============================================================================}
Procedure KB_PutString(S:String);
Var i:Integer;
Begin
  For i:=1 to Length(S) do KB_Put( Ord(S[i]) );
end;
{============================================================================}
Procedure KB_Wait(KeyCode:KeyCodeRangeType);
Var Key:Word;
Begin
  repeat
    KB_Read(Key);
  Until Key=KeyCode;
end;
{============================================================================}
{$F+}
Procedure KB_ExitProc;
Begin
  ASM MOV AX,Seg0040                 { Bios Datensegment }
      MOV ES,AX
      MOV AX,org_start_ptr
      PUSHF
      CLI
      MOV ES:[BIOS_START_PTR],AX
      MOV ES:[BIOS_READ_PTR],AX
      MOV ES:[BIOS_LAST_PTR],AX
      MOV AX,org_end_ptr
      MOV ES:[BIOS_END_PTR],AX
      POPF
  end;
  ExitProc:=OldExitProc;
end;
{$F-}
{============================================================================}
Function KB_YesNo(YesChar,NoChar:YesNoRangeType):Boolean;
Var Key:Word;  ch:Char;
Begin
  KB_YesNo := False;
  YesChar  := UpCase(YesChar);
  NoChar   := UpCase(NoChar);
  Repeat
    KB_read(Key);
    ch := Upcase(Chr(Key));
    if ch = YesChar then KB_YesNo := TRUE;
  Until (ch=YesChar) or (ch=NoChar);
end;
{============================================================================}
Begin                 { Initialisierung }
  ASM MOV DI,Seg0040               { Bios Datensegment }
      MOV ES,DI
      MOV AX,ES:[BIOS_START_PTR]   { Orginal Start }
      MOV org_start_ptr,AX         { merken }
      MOV AX,ES:[BIOS_END_PTR]     { Orginal Ende }
      MOV org_end_ptr,AX           { merken }
      MOV AX,NEW_BUF_OFFSET        { Offset 400h+200h=600h neuer Puffer }
      PUSHF                        { IRQ-Flag merken }
      CLI                          { Interrupts sperren }
      MOV ES:[BIOS_START_PTR],AX   { Startadresse setzen }
      MOV ES:[BIOS_READ_PTR],AX    { Lesezeiger auf Start }
      MOV ES:[BIOS_LAST_PTR],AX    { Schreibzeiger auf Start }
      ADD AX,200                   { 200 Bytes = Platz fuer 100 Tastencodes }
      MOV ES:[BIOS_END_PTR],AX
      POPF                         { IRQ-Flag restaurieren }
  end;
  OldExitProc := ExitProc;
  ExitProc    := @KB_ExitProc;
end.
 
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

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

Re: Tastaturabfrage funktioniert nicht

Beitrag von thosch »

siro hat geschrieben:Du hast in deiner Funktion GetKeyCode folgende Zeile:

Code: Alles auswählen

GetKeyCode := KeyCode; 


KeyCode wird aber nirgends gesetzt ???
Somit dürfte dein Ergebnis recht zufällig ausfallen, oder verstehe ich da etwas falsch ?
Soll das evtl.

Code: Alles auswählen

GetKeyCode := DosKeyCode; 

heissen ?

Siro


Danke für den Hinweis! Nein, es darf nicht GetKeyCode := DosKeyCode heißen. Eher muss die Variable DosKeyCode in KeyCode umbenannt werden.

Code: Alles auswählen

 
   KeyCode := (scan shl 8) + chb;
   GetKeyCode := KeyCode;
 


Das ist aber noch nicht alles. Ich muss die Buchstabentasten immer noch mehrfach drücken, bevor ich den Tastencode korrekt erhalte.

Habe den Code aus einer alten Unit aus Turbo Pascal übernommen und will die nun so nach Windows portieren, dass ich sie da genau so nutzen kann, aber auch mit Linux zusammen. Da es die Unit CRT für Freepascal für alle Plattformen gibt und dort ReadKey und keypressed definiert sind, sollte das auch funktionieren. Die Keyboard Unit funktioniert bei mir im Grafikmodus nicht, habe da ein altes Programm, das die Unit Graph nutzt, welches ich nach Windows portieren will. Dort ist die Tastaturabfrage mit Tastaturinterrupts gelöst, da bin ich aber bezüglich der Portierbarkeit skeptisch, da sind auch int21 Aufrufe drin, die ja auf keinen Fall portabel sein dürften, eher noch die BIOS Interrupts, da ja das BIOS auf jedem Rechner drauf ist, wie aber schaut es dann mit EFI BIOS aus? Deshalb will ich die universelle Funktion ReadKey verwenden und Keypressed aus derselben CRT Unit abfragen. Und dann die Tastencodes auswerten. Deshalb auch die Datenstruktur mit dem Felt ViertCode, in das ich die VK_XXX konstante eintrage.


@Siro: Wird denn Deine Unit auch von 32Bit Freepascal übersetzt. Ich bin da wegen der 16 Bit Register skeptisch. Hatte da schon massive Probleme bis hin zur Funktionsunfähigkeit des übersetzten Codes, der oft genug angepasst werden muss, dann aber nicht mehr funktioniert. Der Code in der Unit ist schließlich 16 Bit Assembler. Das könnte mit dem 16Bit FPC Compiller klappen, aber mit dem 32 Bittigen????

.

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Tastaturabfrage optimieren, wie?

Beitrag von siro »

Hallo Thosch, war ne Weile nicht da,

das ist, wie erwähnt, eine SEHR alte Software und wurde noch nicht für 32 Bit ausgelegt.
Zudem ist alles "unnötigerweise" in Assembler codiert, das war damals eher Spass am programmieren.
Auf 32 Bit Systemem heissen die Register dann nicht AX sonder EAX, aus BX wird EBX usw.

Für neue Software würde ich es auf keinen Fall mehr einsetzen.

Der beliebte DOS Interrupt 21h gehört auch nicht mehr rein, das ist wirklich Steinzeit,
was ich zumindest aber noch kennen gelernt habe.
Auch die Unit Graph ist ja ganz beliebt gewesen mit den speziellen BGI Treibern.
Hier hab ich sogar meine eigene Treiber geschrieben.
Bin froh, dass man sich darum nicht mehr kümmern muss. Das ist doch erheblich komfortabler geworden
auf allen Systemen.

Ich habe grad das ERSTE MAL eine Konsolenanwenudng mit Free Pascal probiert
und bin erstaunt, das funktioniert ja ganz hervorragend. (Lazarus ist ein Genuss :wink: )
So habe ich Dir mal ein kleines Beispiel programmiert wie man das, zumindest auf Windows Rechnern, machen kann
Ob das auch auf Linux geht, kann ich nicht sagen, ich habe keins.
Im Prinzip sehe ich aber, dass dein Code ja recht ähnlich ist....

Code: Alles auswählen

 
{ Free Pascal Tastatur auswerten }
{ Konsolenanwenung auf Windows probiert }
{ Siro:  08.12.2018 }
 
program project1;
 
uses crt,
     sysutils;  // wegen IntToStr
 
const
 KB_ESC   =  27;   { Esc  Taste                }
 KB_Left  = 331;   { Cursor Links    }
 KB_Right = 333;   { Cursor Rechts   }
 KB_F1    = 315;   { Funktionstaste F1  }
 
 
var key:Word;  // die 16 Bit Variable für den Keycode
 
begin
  repeat
    if KeyPressed then begin                  // wenn eine Taste gedrueckt wurde
      key:=Ord(ReadKey);                      // den Tastencode lesen
      if key=0 then key:=ord(ReadKey) + 256// bei 0 den erweiterten Tastencode lesen und eine 256 dazu addieren
      writeln(IntToStr(key));                 // Testweise den Tastencode anzeigen
 
      // hier jetzt deine ganzen Tasten auswerten:
      case key of
        ord('x') : Writeln('kleines x wurde gedrückt');
        ord('A')..ord('Z') : Writeln('Ein Großbuchstabe wurde gedrückt ' + Chr(key));   // den Buchstaben ausgeben
        KB_F1    : Writeln('Hilfe');
        KB_LEFT  : Writeln('Cursor links');
        KB_RIGHT : Writeln('Cursor links');
         else Writeln('es ist eine andere Taste');
       end;
    end;
 
  until key = KB_ESC;    // wiederholen bis ESC Taste gedrückt wird
end.


Siro
Zuletzt geändert von siro am Sa 8. Dez 2018, 10:36, insgesamt 6-mal geändert.
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Tastaturabfrage optimieren, wie?

Beitrag von siro »

vergiss mal, was ich geschrieben hab, obwohl das natürlich funktioniert,
aber:
Dein Problem liegt ganz woanders:

Du hast die Variable scan in der Funktion GetKeyCode NICHT initialisiert.
Die wird nur initialisiert wenn chb = 0 ist, also bei Sondertasten
sonst steht sie irgendwo.

Code: Alles auswählen

if chb = 0 then scan := ord(readkey) 
           else scan := 0;


Probier mal...

Siro
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Tastaturabfrage optimieren, wie?

Beitrag von kupferstecher »

siro hat geschrieben:Ich habe grad das ERSTE MAL eine Konsolenanwenudng mit Free Pascal probiert


@Thosch, handelt es sich denn überhaupt um ein Kommandozeilenprogramm? Ein klassisches wohl eher nicht, sonst wäre ja readln ausreichend. Ich würde das dann lieber in eine (einfache) GUI-Anwendung umbauen. Dort kannst du ja eine Art Konsolenfenster einbauen um die Ausgabe einfach zu halten, wie das auch bei Fpcupdeluxe gemacht wird. Alle Tastendrücke werden an die Komponenten geleitet, können aber auch von der Form abgefangen werden, Stichwort "keypreview".

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

Re: Tastaturabfrage optimieren, wie?

Beitrag von thosch »

@Siro: Danke für den Tipp, aber leider hilft auch das nicht weiter.

@Kupferstecher: Ja, im Moment ist das ein Kommandozeilenversion. Die aber später in eine grafische Applikation überführt werden soll.

Wie kann ich solche Tatendrücke an die Komponenten weiter leiten? Welche Quelltexte sollte ich mir dazu genauer anschauen?

Aber zuerst muss ich mal die richtigen Tasten von der ReadKey Funktion erhalten!

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Tastaturabfrage optimieren, wie?

Beitrag von kupferstecher »

Das ist jeweils die OnKeyPress-Methode des jeweiligen Instruments (Objektinspektor). Wenn verschiedene Insrumente den Fokus haben koennen, waehrend die Eingabe erfolgt, kannst du den Instumenten jeweils die gleiche Methode zuweisen, oder eben auf Formularebene per KeyPreview alle Eingaben abfangen.

Ich wuerde an deiner Stelle einfach mal das Gui-Grundgeruest einrichten ohne die eigentliche Programmfunktionalitaet. Dann merkst du schnell wie einfach die Tastaturverarbeitung ist.

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

Re: Tastaturabfrage optimieren, wie?

Beitrag von thosch »

Soweit schon klar. OnKeypress kenne ich. Habe auch schon VCL (Delphi) und LCL (Lazarus) programmiert. Aber irgendwo müssen die Tastatuereignisse doch her kommen. Der Rechner hat nach wie vor sein Bios, wo es die Interrupt-Funktion INT16h zur Tastaturabfrage gibt. DOS Interrupts entfallen, die dürfte es in Linux nicht geben und in Windows nicht mehr geben. Bleibt also nur INT 16h aus dem BIOS. Nun sind ja Hardwarezugriffe unter Windows und Linux wegen des Multitasking und auf der GUI wegen der Fenstertechnik nicht möglich. Aber intern muss doch mein Betreibssystem an die gderückte Taste kommen. Die Funktion readkey gibt es in Freepascal für alle unterstützten Betriebssysteme. Und die gab es schon zu DOS Zeiten. Da muss es doch einen Weg geben, an die gedrückten Tasten zu kommen. Diese Tastencodes leite ich später weiter an OnKeyPress. OnKeypress nimmt die Tastencodes entgegen und verarbeitet sie. Im OnKeyPress Ereignis werden die Tastaturcodes nicht erzeugt sondern nur verarbeitet. Zuerst will ich jedoch das Tastaturereignis erzeugen. Dazu brauche ich die readkey Funktion. Mein Code funktioniert aber nicht, ich muss immer die jeweilige Taste mehrmals drücken, bevor ich den Tastencode erhalte und die Häufigkeit (wie oft ich die Taste drücken muss, bevor der richtige Tastencode kommt, ist auch noch von Taste zu Taste unterschiedlich und ich kann da keine Gesetzmäßigkeit erkennen, welche Taste ich wie oft drücken muss. Wenn es da Tastencodeabhängig eine Gesetzmäßigkeit gibt, müsste ich außerdem für jede Taste n-1 Tastendrücke simulieren, um an den Tastencode zu kommen. Wie simuliere ich einen Tastendruck?

Alles nicht besonders befriedigend.

Ich will verstehen, was hinter den Kulissen abläuft.

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Tastaturabfrage optimieren, wie?

Beitrag von siro »

Moin Thosch ,

ich hab dein Programm mal probiert.
und bekomme es ersteinmal garnicht compiliert.
er kennt die Konstanten nicht VK_
dann meckert mich der Compiler an bei allen Umlauten,
liegt vermutlich am Zeichensatz,

Nachdem ich das notdürftig beseitigt habe, comilierte er es und dann habe ich dein Hauptprogramm mal umgebaut.
und meiner Meinung nach verhält es sich nun richtig.

Code: Alles auswählen

 
begin
    REPEAT
 
     if keypressed then begin              // !!!!! NUR wenn Taste gedrückt wurde
       KeyEv := GetVKeyOf(GetKeyCode);        // darf GetVKeyOf aufgerufen werden.
       write(KeyEv.VirtCode);
       case KeyEv.Scancode of
       $47: begin write('Home/Pos1 ---'); writeln(KeyEv.Scancode); end;
       $48: begin write('Pfeil hoch ---'); writeln(KeyEv.Scancode); end;
       $49: begin write('Seite hoch ---'); writeln(KeyEv.Scancode); end;
       $4B: begin write('Pfeil links ---'); writeln(KeyEv.Scancode); end;
       $4D: begin write('Pfeil rechts ---'); writeln(KeyEv.Scancode); end;
       $4F: begin write('End ---'); writeln(KeyEv.Scancode); end;
       $50: begin write('Pfeil ab ---'); writeln(KeyEv.Scancode); end;
       $51: begin write('Seite ab ---'); writeln(KeyEv.Scancode); end;
       VK_HOME: begin write('H o m e'); writeln(KeyEv.Scancode); end;
       else writeln('Zeichen: ',KeyEv.CharCode,' Scan: ', KeyEv.Scancode);   // zusätzliches keypressed entfert
      end;
 
     end// if Keypressed
  UNTIL KeyEv.CharCode { and 15 }= 27;    // AND 15 ausgeklammert,  mit ESC  Taste beenden geht sonst nicht.
end.     


Du rufst die Funktion GetVKeyOf auf obwohl keine Taste gedrückt ist, meiner Meinung nach liegt da der Hase begraben.
Gibt es eigentlich einen Unterschied zwischen VK_HOME und $47 ???? ist meiner Meinung nach identisch,
Muss aber anscheinend anders definiert sein, sonst würde der Compiler meckern hab ich grad festgestellt.

Zusatz:
Diese gesamte Programmierung ist unter einer grafischen Oberfläche aber völlig irrelevant, das funktioniert dann völlig anders.
Für Konsole auf Windows okay, aber das wars dann auch schon.

Siro
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

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

Re: Tastaturabfrage optimieren, wie?

Beitrag von thosch »

Danke @siro, der Aufruf vor keypressed war die Ursache für mein Problem.

Allerdings erhalte ich nun überhaupt nur die Groß- und Kleinbuchstaben wie auch die Cursortasten und Home,End,PgUp,PgDn und die Funktionstasten. Keine Alt+Key Kombinationen, die Ctrl+Key Kombinationen nur, soweit sie von der Konsole verarbeitet werden, sonst Wert NULL, ebenso verhalten sic die Ziffern und Sonderzeichen, die einfach mit dem Wert NULL quittiert werden.

Liegt das nun am Zeichensatz oder ist da noch was anderes faul? Der deutsche Zeichensatz sollte doch mit den Unicodes erst mal übereinstimmen.

Und wenn es denn der Zeichensatz wäre, kann man den irgendwie anpassen?

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Tastaturabfrage optimieren, wie?

Beitrag von kupferstecher »

thosch hat geschrieben:der Aufruf vor keypressed war die Ursache für mein Problem.

Ich bin mir nicht sicher, ob das nicht nur ein Symptom beseitigt hat. Die eigentliche Abfrage mit "readkey" in der Funktion GetKeyCode war doch schon mit "if keypressed" abgesichert.

Mir scheint aber ein Fehler in GetKeyCode zu sein:

Code: Alles auswählen

   begin
      ch := readkey; chb := ord(ch);
      if chb = 0 then scan := ord(readkey);
      KeyCode := (scan shl 8) + chb;
      GetKeyCode := KeyCode;
    end;

Wenn die Variable ch nicht Null ist, d.h. bei 'normalen' Tasten, dann ist die Variable scan nicht initialisiert, fließt aber in das Ergebnis mit ein.

Ich würde hergehen und einfach mal ein Minimalprogramm schreiben um die Tastenabfrage nachzuvollziehen, dann weißt du zumindest, was im Programm ankommt:

Code: Alles auswählen

program keyreader
var keyval: char;
begin
while true do begin
  sleep(10);
  if keypressed then begin
    keyval:= readkey;
    writeln(ord(keyval));
    if keyval = #0 then begin
      keyval:= readkey;
      writeln(ord(keyval));
    end;
  end;
end;
 
end;

Antworten