keytest.pas 7.1 KB

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