keytest.pas 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. PROGRAM KeyTest;
  2. { Set source file encoding to UTF-8 for correct handling of Unicode strings }
  3. {$codepage UTF8}
  4. USES
  5. {$ifdef unix}BaseUnix,{$endif}
  6. Objects, { Base objects, TObject }
  7. UDrivers, { System drivers (keyboard, mouse, video), Unicode version }
  8. UViews, { Base classes for views (TView, TWindow), Unicode version }
  9. UMenus, { Menu elements (TMenuBar, TMenu), Unicode version }
  10. UApp, { Main application class TApplication, Unicode version }
  11. cwstring, { Unicode string handling }
  12. SysUtils; { For the Format function }
  13. TYPE
  14. PKeyInfoView = ^TKeyInfoView;
  15. {
  16. TKeyInfoView is a special view that will display
  17. information about the last keyboard event.
  18. }
  19. TKeyInfoView = OBJECT(TView)
  20. LastKeyEvent: TEvent; { Store the last event here }
  21. TVInputValue: UnicodeString;
  22. Cnt: Integer;
  23. CONSTRUCTOR Init(VAR Bounds: TRect);
  24. PROCEDURE Draw; VIRTUAL;
  25. PROCEDURE UpdateInfo(CONST Event: TEvent);
  26. PROCEDURE HandleEvent(VAR Event: TEvent); VIRTUAL;
  27. END;
  28. PKeyTestApp = ^TKeyTestApp;
  29. {
  30. TKeyTestApp is the main class of our application.
  31. }
  32. TKeyTestApp = OBJECT(TApplication)
  33. KeyInfoView: PKeyInfoView; { Pointer to our view for displaying information }
  34. CONSTRUCTOR Init;
  35. PROCEDURE InitMenuBar; VIRTUAL;
  36. PROCEDURE InitStatusLine; VIRTUAL;
  37. END;
  38. {---------------------------------------------------------------------------}
  39. { TKeyInfoView OBJECT METHODS }
  40. {---------------------------------------------------------------------------}
  41. CONSTRUCTOR TKeyInfoView.Init(VAR Bounds: TRect);
  42. BEGIN
  43. Inherited Init(Bounds);
  44. Options := Options OR ofSelectable; { Make the View selectable so it can get focus }
  45. GrowMode := gfGrowHiX + gfGrowHiY; { Grow along with window resize }
  46. EventMask := $FFFF; { Accept all event types }
  47. FillChar(LastKeyEvent, SizeOf(TEvent), 0); { Initialize with zeros }
  48. LastKeyEvent.What := evNothing; { No events initially }
  49. Cnt := 0;
  50. END;
  51. { Function to format the modifier key state byte into a readable string }
  52. FUNCTION FormatShiftState(State: Byte): UnicodeString;
  53. VAR S: UnicodeString;
  54. BEGIN
  55. S := '';
  56. IF (State AND kbRightShift) <> 0 THEN S := S + 'RightShift ';
  57. IF (State AND kbLeftShift) <> 0 THEN S := S + 'LeftShift ';
  58. IF (State AND kbCtrlShift) <> 0 THEN S := S + 'Ctrl ';
  59. IF (State AND kbAltShift) <> 0 THEN S := S + 'Alt ';
  60. IF (State AND kbScrollState) <> 0 THEN S := S + 'ScrollLock ';
  61. IF (State AND kbNumState) <> 0 THEN S := S + 'NumLock ';
  62. IF (State AND kbCapsState) <> 0 THEN S := S + 'CapsLock ';
  63. IF (State AND kbInsState) <> 0 THEN S := S + 'Insert ';
  64. IF S = '' THEN S := '(none)';
  65. FormatShiftState := S;
  66. END;
  67. PROCEDURE TKeyInfoView.Draw;
  68. VAR
  69. B: TDrawBuffer;
  70. Line: UnicodeString;
  71. Y: Integer;
  72. Color: Byte;
  73. LastKeyCharCode: AnsiChar;
  74. LastKeyUnicodeChar: WideChar;
  75. BEGIN
  76. Color := GetColor(1);
  77. { Fill the view's background with spaces using the current color }
  78. MoveChar(B, ' ', Color, Size.X);
  79. FOR Y := 0 TO Size.Y - 1 DO
  80. WriteLine(0, Y, Size.X, 1, B);
  81. { Set the color for the text }
  82. Color := GetColor(2);
  83. { If no key has been pressed yet, display a prompt }
  84. IF LastKeyEvent.What = evNothing THEN
  85. BEGIN
  86. Line := 'Press any key to analyze...';
  87. MoveStr(B, Line, Color);
  88. WriteLine(1, 1, StrWidth(Line), 1, B);
  89. Exit;
  90. END;
  91. { Display all information from the TEvent record }
  92. Line := Format('Event.What: $%4.4x (evKeyDown)', [LastKeyEvent.What]);
  93. MoveStr(B, Line, Color);
  94. WriteLine(1, 1, StrWidth(Line), 1, B);
  95. Line := Format('KeyCode: $%4.4x', [LastKeyEvent.KeyCode]);
  96. MoveStr(B, Line, Color);
  97. WriteLine(1, 2, StrWidth(Line), 1, B);
  98. LastKeyCharCode:=LastKeyEvent.CharCode;
  99. IF LastKeyCharCode < #32 THEN
  100. LastKeyCharCode:=#32; { Non displayable chars are shown as space }
  101. Line := Format('CharCode: ''%s'' ($%2.2x)', [LastKeyCharCode, Ord(LastKeyEvent.CharCode)]);
  102. MoveStr(B, Line, Color);
  103. WriteLine(1, 3, StrWidth(Line), 1, B);
  104. Line := Format('ScanCode: $%2.2x', [LastKeyEvent.ScanCode]);
  105. MoveStr(B, Line, Color);
  106. WriteLine(1, 4, StrWidth(Line), 1, B);
  107. LastKeyUnicodeChar:=LastKeyEvent.UnicodeChar;
  108. IF LastKeyUnicodeChar < #32 THEN
  109. LastKeyUnicodeChar:=#32; { Non displayable chars are shown as space }
  110. Line := Format('UnicodeChar: ''%s'' (U+%4.4x)', [LastKeyUnicodeChar, Ord(LastKeyEvent.UnicodeChar)]);
  111. MoveStr(B, Line, Color);
  112. WriteLine(1, 5, StrWidth(Line), 1, B);
  113. Line := 'KeyShift: $' + IntToHex(LastKeyEvent.KeyShift, 2);
  114. MoveStr(B, Line, Color);
  115. WriteLine(1, 6, StrWidth(Line), 1, B);
  116. Line := ' ' + FormatShiftState(LastKeyEvent.KeyShift);
  117. MoveStr(B, Line, Color);
  118. WriteLine(1, 7, StrWidth(Line), 1, B);
  119. Line := 'TV_INPUT Env Var: ';
  120. if TVInputValue <> '' then
  121. Line := Line + TVInputValue
  122. else
  123. Line := Line + '(not set)';
  124. MoveStr(B, Line, Color);
  125. WriteLine(1, 9, StrWidth(Line), 1, B);
  126. Line := 'Count: ' + IntToStr(Cnt);
  127. MoveStr(B, Line, Color);
  128. WriteLine(1, 11, StrWidth(Line), 1, B);
  129. END;
  130. PROCEDURE TKeyInfoView.UpdateInfo(CONST Event: TEvent);
  131. BEGIN
  132. LastKeyEvent := Event;
  133. Cnt := Cnt + 1;
  134. DrawView; { Request a redraw }
  135. END;
  136. PROCEDURE TKeyInfoView.HandleEvent(VAR Event: TEvent);
  137. BEGIN
  138. { Call the ancestor's handler }
  139. Inherited HandleEvent(Event);
  140. { If the event is a key press, update the info in our View }
  141. IF Event.What = evKeyDown THEN
  142. BEGIN
  143. UpdateInfo(Event);
  144. ClearEvent(Event); { Clear the event }
  145. END;
  146. END;
  147. {---------------------------------------------------------------------------}
  148. { TKeyTestApp OBJECT METHODS }
  149. {---------------------------------------------------------------------------}
  150. CONSTRUCTOR TKeyTestApp.Init;
  151. VAR
  152. R, ViewRect: TRect;
  153. MainWindow: PWindow;
  154. BEGIN
  155. Inherited Init;
  156. { Create the main window that will contain our View }
  157. GetExtent(R);
  158. R.Grow(-5, -5); { Shrink it a bit to have a margin from the screen edges }
  159. MainWindow := New(PWindow, Init(R, 'Keyboard Event Inspector', wnNoNumber));
  160. { Create our View for displaying information. Its coordinates must be relative
  161. to the parent window. To fill the entire client area, its size should be
  162. 2 chars less in width and height, and its origin should be at (1,1). }
  163. ViewRect.Assign(1, 1, MainWindow^.Size.X - 1, MainWindow^.Size.Y - 1);
  164. KeyInfoView := New(PKeyInfoView, Init(ViewRect));
  165. KeyInfoView^.TVInputValue := {$ifdef unix}fpgetenv('TV_INPUT'){$else unix}''{$endif};
  166. MainWindow^.Insert(KeyInfoView);
  167. { Insert the window into the Desktop }
  168. DeskTop^.Insert(MainWindow);
  169. END;
  170. PROCEDURE TKeyTestApp.InitMenuBar;
  171. VAR R: TRect;
  172. BEGIN
  173. GetExtent(R);
  174. R.B.Y := R.A.Y + 1;
  175. MenuBar := New(PMenuBar, Init(R, NewMenu(
  176. NewSubMenu('~F~ile', hcNoContext, NewMenu(
  177. NewItem('E~x~it', 'Alt+X', kbAltX, cmQuit, hcNoContext, NIL)
  178. ), NIL)
  179. )));
  180. END;
  181. PROCEDURE TKeyTestApp.InitStatusLine;
  182. var
  183. R: TRect;
  184. begin
  185. GetExtent(R);
  186. R.A.Y := R.B.Y - 1;
  187. New(StatusLine,
  188. Init(R,
  189. NewStatusDef(0, $FFFF,
  190. NewStatusKey('~Alt+X~ Exit', kbAltX, cmQuit, nil),
  191. nil
  192. )
  193. )
  194. );
  195. end;
  196. {---------------------------------------------------------------------------}
  197. { MAIN PROGRAM BLOCK }
  198. {---------------------------------------------------------------------------}
  199. VAR
  200. MyApp: TKeyTestApp;
  201. BEGIN
  202. MyApp.Init;
  203. MyApp.Run;
  204. MyApp.Done;
  205. END.