keytest.pas 8.4 KB

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