/* * [KeyPlayer.java] * * Summary: Keystroke and Mouse Event Tutor. * * Copyright: (c) 1999-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.0 1999-10-16 initial version * 1.1 2005-06-30 add stomp bat files,add stomp bat files, avoids dumping * control chars to the console. * 1.2 2006-03-06 reformat with IntelliJ, add Javadoc * 1.3 2007-05-26 add pad and ican. IntelliJ inspector, renamed KeyPlay or KeyPlayer. * 1.4 2007-12-19 add hex displays * 1.5 2010-01-25 convert to JDK 1.6, add 1.6 VK-names to output. Major refactoring. Tidier display. */ package com.mindprod.keyplayer; import com.mindprod.common18.ST; import com.mindprod.fastcat.FastCat; import java.awt.Frame; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import static java.lang.System.*; /** * Keystroke and Mouse Event Tutor. *

* Application to let you experiment to learn how mouse and keystroke * events work. Output appears on the console. Just click the mouse or hit keystrokes and watch what details of the * events generated. *

 * Compile with:
 * CD \
 * javac.exe com.mindprod.keyplayer.KeyPlayer.java
 * 

* Execute with: * CD \ * java.exe com.mindprod.keyplayer.KeyPlayer *

* * @author Roedy Green, Canadian Mind Products * @version 1.5 2010-01-25 convert to JDK 1.6, add 1.6 VK-names to output. Major refactoring. Tidier display. * @since 1999-10-16 */ public final class KeyPlayer { private static final int FIRST_COPYRIGHT_YEAR = 1999; /** * undisplayed copyright notice * * @noinspection UnusedDeclaration */ private static final String EMBEDDED_COPYRIGHT = "Copyright: (c) 1999-2017 Roedy Green, Canadian Mind Products, http://mindprod.com"; /** * date this version released. * * @noinspection UnusedDeclaration */ private static final String RELEASE_DATE = "2010-01-24"; /** * embedded version string. * * @noinspection UnusedDeclaration */ private static final String VERSION_STRING = "1.5"; /** * lets us look up the VK-name of a keystroke. */ private static final String[] lookup = new String[ 0x10000 ]; /** * used to compose all output. We reuse it over and over */ private static final FastCat sb = new FastCat( 2000 ); static { for ( int i = 0; i < 0x10000; i++ ) { // default value for any unknown values lookup[ i ] = "unknown"; } lookup[ 0x0000 ] = "VK_UNDEFINED"; lookup[ 0x0003 ] = "VK_CANCEL"; lookup[ 0x0008 ] = "VK_BACK_SPACE"; lookup[ 0x0009 ] = "VK_TAB"; lookup[ 0x000a ] = "VK_ENTER"; lookup[ 0x000c ] = "VK_CLEAR"; lookup[ 0x0010 ] = "VK_SHIFT"; lookup[ 0x0011 ] = "VK_CONTROL"; lookup[ 0x0012 ] = "VK_ALT"; lookup[ 0x0013 ] = "VK_PAUSE"; lookup[ 0x0014 ] = "VK_CAPS_LOCK"; lookup[ 0x0015 ] = "VK_KANA"; lookup[ 0x0018 ] = "VK_FINAL"; lookup[ 0x0019 ] = "VK_KANJI"; lookup[ 0x001b ] = "VK_ESCAPE"; lookup[ 0x001c ] = "VK_CONVERT"; lookup[ 0x001d ] = "VK_NONCONVERT"; lookup[ 0x001e ] = "VK_ACCEPT"; lookup[ 0x001f ] = "VK_MODECHANGE"; lookup[ 0x0020 ] = "VK_SPACE"; lookup[ 0x0021 ] = "VK_PAGE_UP"; lookup[ 0x0022 ] = "VK_PAGE_DOWN"; lookup[ 0x0023 ] = "VK_END"; lookup[ 0x0024 ] = "VK_HOME"; lookup[ 0x0025 ] = "VK_LEFT"; lookup[ 0x0026 ] = "VK_UP"; lookup[ 0x0027 ] = "VK_RIGHT"; lookup[ 0x0028 ] = "VK_DOWN"; lookup[ 0x002c ] = "VK_COMMA"; lookup[ 0x002d ] = "VK_MINUS"; lookup[ 0x002e ] = "VK_PERIOD"; lookup[ 0x002f ] = "VK_SLASH"; lookup[ 0x0030 ] = "VK_0"; lookup[ 0x0031 ] = "VK_1"; lookup[ 0x0032 ] = "VK_2"; lookup[ 0x0033 ] = "VK_3"; lookup[ 0x0034 ] = "VK_4"; lookup[ 0x0035 ] = "VK_5"; lookup[ 0x0036 ] = "VK_6"; lookup[ 0x0037 ] = "VK_7"; lookup[ 0x0038 ] = "VK_8"; lookup[ 0x0039 ] = "VK_9"; lookup[ 0x003b ] = "VK_SEMICOLON"; lookup[ 0x003d ] = "VK_EQUALS"; lookup[ 0x0041 ] = "VK_A"; lookup[ 0x0042 ] = "VK_B"; lookup[ 0x0043 ] = "VK_C"; lookup[ 0x0044 ] = "VK_D"; lookup[ 0x0045 ] = "VK_E"; lookup[ 0x0046 ] = "VK_F"; lookup[ 0x0047 ] = "VK_G"; lookup[ 0x0048 ] = "VK_H"; lookup[ 0x0049 ] = "VK_I"; lookup[ 0x004a ] = "VK_J"; lookup[ 0x004b ] = "VK_K"; lookup[ 0x004c ] = "VK_L"; lookup[ 0x004d ] = "VK_M"; lookup[ 0x004e ] = "VK_N"; lookup[ 0x004f ] = "VK_O"; lookup[ 0x0050 ] = "VK_P"; lookup[ 0x0051 ] = "VK_Q"; lookup[ 0x0052 ] = "VK_R"; lookup[ 0x0053 ] = "VK_S"; lookup[ 0x0054 ] = "VK_T"; lookup[ 0x0055 ] = "VK_U"; lookup[ 0x0056 ] = "VK_V"; lookup[ 0x0057 ] = "VK_W"; lookup[ 0x0058 ] = "VK_X"; lookup[ 0x0059 ] = "VK_Y"; lookup[ 0x005a ] = "VK_Z"; lookup[ 0x005b ] = "VK_OPEN_BRACKET"; lookup[ 0x005c ] = "VK_BACK_SLASH"; lookup[ 0x005d ] = "VK_CLOSE_BRACKET"; lookup[ 0x0060 ] = "VK_NUMPAD0"; lookup[ 0x0061 ] = "VK_NUMPAD1"; lookup[ 0x0062 ] = "VK_NUMPAD2"; lookup[ 0x0063 ] = "VK_NUMPAD3"; lookup[ 0x0064 ] = "VK_NUMPAD4"; lookup[ 0x0065 ] = "VK_NUMPAD5"; lookup[ 0x0066 ] = "VK_NUMPAD6"; lookup[ 0x0067 ] = "VK_NUMPAD7"; lookup[ 0x0068 ] = "VK_NUMPAD8"; lookup[ 0x0069 ] = "VK_NUMPAD9"; lookup[ 0x006a ] = "VK_MULTIPLY"; lookup[ 0x006b ] = "VK_ADD"; // lookup[ 0x006c ] = "VK_SEPARATER"; lookup[ 0x006c ] = "VK_SEPARATOR"; lookup[ 0x006d ] = "VK_SUBTRACT"; lookup[ 0x006e ] = "VK_DECIMAL"; lookup[ 0x006f ] = "VK_DIVIDE"; lookup[ 0x0070 ] = "VK_F1"; lookup[ 0x0071 ] = "VK_F2"; lookup[ 0x0072 ] = "VK_F3"; lookup[ 0x0073 ] = "VK_F4"; lookup[ 0x0074 ] = "VK_F5"; lookup[ 0x0075 ] = "VK_F6"; lookup[ 0x0076 ] = "VK_F7"; lookup[ 0x0077 ] = "VK_F8"; lookup[ 0x0078 ] = "VK_F9"; lookup[ 0x0079 ] = "VK_F10"; lookup[ 0x007a ] = "VK_F11"; lookup[ 0x007b ] = "VK_F12"; lookup[ 0x007f ] = "VK_DELETE"; lookup[ 0x0080 ] = "VK_DEAD_GRAVE"; lookup[ 0x0081 ] = "VK_DEAD_ACUTE"; lookup[ 0x0082 ] = "VK_DEAD_CIRCUMFLEX"; lookup[ 0x0083 ] = "VK_DEAD_TILDE"; lookup[ 0x0084 ] = "VK_DEAD_MACRON"; lookup[ 0x0085 ] = "VK_DEAD_BREVE"; lookup[ 0x0086 ] = "VK_DEAD_ABOVEDOT"; lookup[ 0x0087 ] = "VK_DEAD_DIAERESIS"; lookup[ 0x0088 ] = "VK_DEAD_ABOVERING"; lookup[ 0x0089 ] = "VK_DEAD_DOUBLEACUTE"; lookup[ 0x008a ] = "VK_DEAD_CARON"; lookup[ 0x008b ] = "VK_DEAD_CEDILLA"; lookup[ 0x008c ] = "VK_DEAD_OGONEK"; lookup[ 0x008d ] = "VK_DEAD_IOTA"; lookup[ 0x008e ] = "VK_DEAD_VOICED_SOUND"; lookup[ 0x008f ] = "VK_DEAD_SEMIVOICED_SOUND"; lookup[ 0x0090 ] = "VK_NUM_LOCK"; lookup[ 0x0091 ] = "VK_SCROLL_LOCK"; lookup[ 0x0096 ] = "VK_AMPERSAND"; lookup[ 0x0097 ] = "VK_ASTERISK"; lookup[ 0x0098 ] = "VK_QUOTEDBL"; lookup[ 0x0099 ] = "VK_LESS"; lookup[ 0x009a ] = "VK_PRINTSCREEN"; lookup[ 0x009b ] = "VK_INSERT"; lookup[ 0x009c ] = "VK_HELP"; lookup[ 0x009d ] = "VK_META"; lookup[ 0x00a0 ] = "VK_GREATER"; lookup[ 0x00a1 ] = "VK_BRACELEFT"; lookup[ 0x00a2 ] = "VK_BRACERIGHT"; lookup[ 0x00c0 ] = "VK_BACK_QUOTE"; lookup[ 0x00de ] = "VK_QUOTE"; lookup[ 0x00e0 ] = "VK_KP_UP"; lookup[ 0x00e1 ] = "VK_KP_DOWN"; lookup[ 0x00e2 ] = "VK_KP_LEFT"; lookup[ 0x00e3 ] = "VK_KP_RIGHT"; lookup[ 0x00f0 ] = "VK_ALPHANUMERIC"; lookup[ 0x00f1 ] = "VK_KATAKANA"; lookup[ 0x00f2 ] = "VK_HIRAGANA"; lookup[ 0x00f3 ] = "VK_FULL_WIDTH"; lookup[ 0x00f4 ] = "VK_HALF_WIDTH"; lookup[ 0x00f5 ] = "VK_ROMAN_CHARACTERS"; lookup[ 0x0100 ] = "VK_ALL_CANDIDATES"; lookup[ 0x0101 ] = "VK_PREVIOUS_CANDIDATE"; lookup[ 0x0102 ] = "VK_CODE_INPUT"; lookup[ 0x0103 ] = "VK_JAPANESE_KATAKANA"; lookup[ 0x0104 ] = "VK_JAPANESE_HIRAGANA"; lookup[ 0x0105 ] = "VK_JAPANESE_ROMAN"; lookup[ 0x0106 ] = "VK_KANA_LOCK"; lookup[ 0x0107 ] = "VK_INPUT_METHOD_ON_OFF"; lookup[ 0x0200 ] = "VK_AT"; lookup[ 0x0201 ] = "VK_COLON"; lookup[ 0x0202 ] = "VK_CIRCUMFLEX"; lookup[ 0x0203 ] = "VK_DOLLAR"; lookup[ 0x0204 ] = "VK_EURO_SIGN"; lookup[ 0x0205 ] = "VK_EXCLAMATION_MARK"; lookup[ 0x0206 ] = "VK_INVERTED_EXCLAMATION_MARK"; lookup[ 0x0207 ] = "VK_LEFT_PARENTHESIS"; lookup[ 0x0208 ] = "VK_NUMBER_SIGN"; lookup[ 0x0209 ] = "VK_PLUS"; lookup[ 0x020a ] = "VK_RIGHT_PARENTHESIS"; lookup[ 0x020b ] = "VK_UNDERSCORE"; lookup[ 0x020c ] = "VK_WINDOWS"; lookup[ 0x020d ] = "VK_CONTEXT_MENU"; lookup[ 0xf000 ] = "VK_F13"; lookup[ 0xf001 ] = "VK_F14"; lookup[ 0xf002 ] = "VK_F15"; lookup[ 0xf003 ] = "VK_F16"; lookup[ 0xf004 ] = "VK_F17"; lookup[ 0xf005 ] = "VK_F18"; lookup[ 0xf006 ] = "VK_F19"; lookup[ 0xf007 ] = "VK_F20"; lookup[ 0xf008 ] = "VK_F21"; lookup[ 0xf009 ] = "VK_F22"; lookup[ 0xf00a ] = "VK_F23"; lookup[ 0xf00b ] = "VK_F24"; lookup[ 0xff20 ] = "VK_COMPOSE"; lookup[ 0xff58 ] = "VK_BEGIN"; lookup[ 0xff7e ] = "VK_ALT_GRAPH"; lookup[ 0xffc8 ] = "VK_STOP"; lookup[ 0xffc9 ] = "VK_AGAIN"; lookup[ 0xffca ] = "VK_PROPS"; lookup[ 0xffcb ] = "VK_UNDO"; lookup[ 0xffcd ] = "VK_COPY"; lookup[ 0xffcf ] = "VK_PASTE"; lookup[ 0xffd0 ] = "VK_FIND"; lookup[ 0xffd1 ] = "VK_CUT"; } /** * Display cooked keystroke (result of combination of keys) * * @param e the Keystroke event. */ private static void displayCookedKeystroke( final KeyEvent e ) { final char keyChar = e.getKeyChar(); sb.append( " cooked KeyChar=\'" ); sb.append( safe( keyChar ) ); sb.append( "\'=0x" ); sb.append( ST.toLZHexString( ( int ) keyChar, 4 ) ); sb.append( "=" ); sb.append( ST.leftJustified( ( int ) keyChar, 5, false ) ); } /** * display the event id of the keystroke event * * @param e the mouse event. */ private static void displayKeystrokeID( final KeyEvent e ) { sb.append( " ID=" ); sb.append( e.getID() ); } /** * display keystroke modifier state eg. ALT_MASK * * @param e keystroke event that just happened. */ private static void displayKeystrokeModifiers( final KeyEvent e ) { final int mods = e.getModifiers(); if ( ( mods & InputEvent.ALT_MASK ) != 0 ) { sb.append( " ALT_MASK" ); } if ( ( mods & InputEvent.CTRL_MASK ) != 0 ) { sb.append( " CTRL_MASK" ); } if ( ( mods & InputEvent.META_MASK ) != 0 ) { sb.append( " META_MASK" ); } if ( ( mods & InputEvent.SHIFT_MASK ) != 0 ) { sb.append( " SHIFT_MASK" ); } } /** * display mouse modifier such as ALT-BUTTON1_MASK * * @param e mouse event click etc. */ private static void displayModifiers( final MouseEvent e ) { int mods = e.getModifiers(); if ( ( mods & InputEvent.ALT_MASK ) != 0 ) { sb.append( " ALT_MASK" ); } if ( ( mods & InputEvent.BUTTON1_MASK ) != 0 ) { sb.append( " BUTTON1_MASK" ); } if ( ( mods & InputEvent.BUTTON2_MASK ) != 0 ) { sb.append( " BUTTON2_MASK" ); } if ( ( mods & InputEvent.BUTTON3_MASK ) != 0 ) { sb.append( " BUTTON3_MASK" ); } if ( ( mods & InputEvent.CTRL_MASK ) != 0 ) { sb.append( " CTRL_MASK" ); } if ( ( mods & InputEvent.META_MASK ) != 0 ) { sb.append( " META_MASK" ); } if ( ( mods & InputEvent.SHIFT_MASK ) != 0 ) { sb.append( " SHIFT_MASK" ); } } /** * display the evente id of the mouse event * * @param e the mouse event. */ private static void displayMouseID( final MouseEvent e ) { sb.append( " ID=" ); sb.append( e.getID() ); } /** * display the raw keystroke * * @param e Keystroke event */ private static void displayRawKeystroke( final KeyEvent e ) { final int keyCode = e.getKeyCode(); sb.append( " raw KeyCode=\'" ); sb.append( safe( ( char ) keyCode ) ); sb.append( "\'=0x" ); sb.append( ST.toLZHexString( keyCode, 4 ) ); sb.append( "=" ); sb.append( ST.leftJustified( keyCode, 5, false ) ); sb.append( " " ); sb.append( ST.rightPad( getVkName( keyCode ), 22 /* a few are even longer */, false ) ); } /** * display the x,y coordinates of the mouse * * @param e the event reporting position */ private static void displayXY( final MouseEvent e ) { sb.append( ST.rightPad( " (" + e.getX() + "," + e.getY() + ")", 12, false ) ); } /** * debugging tool to track keystrokes. Whenever you hit a key on the keyboard, three events will show up at your * KeyListener, first an event at keyPressed, then at keyTyped, then at keyReleased. If you hold a key down and it * repeats, you will see that triple repeated over and over. If you hit the ctrl key and hold it down you will see * repeated events at keyPressed and finally one at keyReleased when you let go. There is no event at keyTyped. When * you hit Ctrl+C you see keyCode 03, ^C, ETX not the letter C. Java combines the keys for you. It is not your * problem to track the ctrl or shift state and modify the meanings of other keystrokes. * * @param e what sort of keystroke typed */ private static void dumpKeyEvent( KeyEvent e ) { displayKeystrokeID( e ); displayRawKeystroke( e ); displayCookedKeystroke( e ); displayKeystrokeModifiers( e ); // separate events with a blank line. out.println( sb.toString() ); sb.clear(); } // end dumpKeyEvent /** * debugging tool to track mouse clicks. * * @param e what sort of mouse event. */ private static void dumpMouseEvent( MouseEvent e ) { displayMouseID( e ); displayXY( e ); displayModifiers( e ); out.println( sb ); sb.clear(); } // end dumpMouseEvent /** * looup the corresponding VkName for the numeric code * * @param code will be in range 0 .. 0xffff * * @return name of the key e.g. "VK_ENTER" */ private static String getVkName( int code ) { return ( 0 <= code && code < 0x10000 ) ? lookup[ code ] : "unknown"; } /** * convert unprintable chars to '.' * * @param c character to test for safety * * @return the same character if safe, dot if not. */ private static char safe( char c ) { if ( 32 <= c && c <= 254 ) { return c; } else { return '_'; } } // end safe /** * main method. * * @param args not used . */ public static void main( String[] args ) { final Frame frame = new Frame( "KEYPLAY " + VERSION_STRING + " Keystroke and Mouse Tutor, Focus Window. Output on console" ); frame.setSize( 200, 200 ); frame.addKeyListener( new java.awt.event.KeyAdapter() { /** * Called when key pressed. * @param e describes key. * @see java.awt.event.KeyAdapter#keyPressed(KeyEvent) */ public void keyPressed( KeyEvent e ) { sb.append( '\n' ); sb.append( ST.rightPad( "keyPressed", 11, false ) ); dumpKeyEvent( e ); } /** * Called when key released. * @param e describes key. * @see java.awt.event.KeyAdapter#keyReleased(KeyEvent) */ public void keyReleased( KeyEvent e ) { sb.append( ST.rightPad( "keyReleased", 11, false ) ); dumpKeyEvent( e ); } /** * Called when key typed. * @param e describes key. * @see java.awt.event.KeyAdapter#keyTyped(KeyEvent) */ public void keyTyped( KeyEvent e ) { sb.append( ST.rightPad( "keyTyped", 11, false ) ); dumpKeyEvent( e ); } } // end anonymous class );// end addKeyListener line frame.addMouseListener( new java.awt.event.MouseAdapter() { /** * Called when mouse clicked. * @param e describes mouse position. * @see java.awt.event.MouseAdapter#mouseClicked(MouseEvent) */ public void mouseClicked( MouseEvent e ) { sb.append( ST.rightPad( "mouseClicked", 13, false ) ); dumpMouseEvent( e ); } /** * Called when mouse enters Component. * @param e describes mouse position. * @see java.awt.event.MouseAdapter#mouseEntered(MouseEvent) */ public void mouseEntered( MouseEvent e ) { sb.append( '\n' ); sb.append( ST.rightPad( "mouseEntered", 13, false ) ); dumpMouseEvent( e ); } /** * Called when mouse leaves Component. * @param e describes mouse position. * @see java.awt.event.MouseAdapter#mouseExited(MouseEvent) */ public void mouseExited( MouseEvent e ) { sb.append( '\n' ); sb.append( ST.rightPad( "mouseExited", 13, false ) ); dumpMouseEvent( e ); } /** * Called when mouse button pressed. * @param e describes mouse position. * @see java.awt.event.MouseAdapter#mousePressed(MouseEvent) */ public void mousePressed( MouseEvent e ) { sb.append( '\n' ); sb.append( ST.rightPad( "mousePressed", 13, false ) ); dumpMouseEvent( e ); } /** * Called when mouse button released. * @param e describes mouse position. * @see java.awt.event.MouseAdapter#mouseReleased(MouseEvent) */ public void mouseReleased( MouseEvent e ) { sb.append( ST.rightPad( "mouseReleased", 13, false ) ); dumpMouseEvent( e ); } } // end anonymous class );// end addKeyListener line frame.addWindowListener( new java.awt.event.WindowAdapter() { /** * Handle request to shutdown. * @param e event giving details of closing. */ public void windowClosing( java.awt.event.WindowEvent e ) { System.exit( 0 ); } // end WindowClosing } // end anonymous class );// end addWindowListener line frame.validate(); frame.setVisible( true ); } // end main } // end KeyPlayer