Tuesday, November 15, 2016

Remap your Keyboard keys and Mouse buttons using Java

While playing games, we sometimes require to disable a key or remap a key with other key. Also their are times when some of your keyboard key stops working and you want to use that key by instead using some other key.
Below program will help in achieving the same.

Features:

1) helper.txt mentions the code for keyboard keys and mouse button. For eg: 41 is the code for A as seen in helper.txt
2) You run the software.
3) You provide the code of the key which you want to be remapped
4) Now you provide the code of the key which you want to be shown when someone presses the key from step 3
5) Done
6) Now if you type the key from step3 anywhere then instead of it, windows will print the key from step4

Example:

1) User wants that if anyone types 'a' from keyboard then instead of 'a', windows types 'b'
2) Code for a is 41 and b is 42 as could be seen in helper.txt from Git location
3) User run the software
4) User types 41 as the key to be remapped
5) User types 42 as the key to be remapped with
6) Now if user types a anywhere in his computer, then instead of a, system will type b

Git Location:

Working Software:
https://github.com/csanuragjain/keyremapper/blob/master/KeySwapper/Software/Software.zip?raw=true

Source:
https://github.com/csanuragjain/keyremapper/tree/master/KeySwapper/Source

Helper.txt:
https://github.com/csanuragjain/keyremapper/blob/master/helper.txt

Language Used:
Java & C++

Role of Java:

1) Java will take the user input for the key to be remapped
2) Java will call C++ function by using JNI which would actually remap the key

Role of C++:

1) C++ will check when you press the key to be remapped
2) Once user presses the key to be remapped, it will instead call the key with which it should be remapped.

Java Program:
 package com.cooltrickshome;  
 import java.util.Scanner;  
 /**  
  * http://www.kbdedit.com/manual/low_level_vk_list.html  
  * Thanks to http://stackoverflow.com/questions/17419562/how-to-remap-keyboard-key-in-c-with-lowlevelkeyboardproc  
  *  
  */  
 public class RemapKeys {  
 private native void remapPassedKeys(int oldKey, int newKey);  
 static {  
   System.loadLibrary("RemapKeys");  
 }  
 public static void main(String args[]) {  
      final int oldKey;   
      final int newKey;  
      Scanner s=new Scanner(System.in);  
      System.out.println("Open helper.txt to get the keycodes");  
      System.out.println("Enter the keycode for key to be remappped (For example type 42 if you want to remap b)");  
      oldKey=s.nextInt(16);  
      System.out.println("Enter the keycode for key to be remapped with");  
      newKey=s.nextInt(16);  
      s.close();  
      Thread t = new Thread()   
      {   
           public void run() {  
             RemapKeys o = new RemapKeys();  
             try {  
               o.remapPassedKeys(oldKey,newKey);  
             } catch(Exception exc) {  
               exc.printStackTrace();  
             }  
           }  
      };  
      t.start();  
      System.out.println("Sample Keyremapper started.");  
      System.out.println("Do not use for any illegal purpose.");  
      System.out.println("Exit the application to get back to normal");  
 }  
 }  

How it works:

1) We use JNI to call the C++ dll named RemapKeys which has a function named remapPassedKeys.
2) remapPassedKeys function takes 2 argument which is code of key which should be remapped and code of key with which the key should be remapped.
3) In main method we make a scanner object and takes the old and new key code from user
4) Post that we pass the key codes to the remapPassedKeys function which is defined in the RemapKeys.dll
5) We made a seperate thread for calling remapPassedKeys function so that our Java program dont get stucked with the call.

C++ Program:

1) We create RemapKeys.dll by using RemapKeys.h and RemapKeys.cpp (For details check https://cooltrickshome.blogspot.com/2016/11/creating-your-personal-keylogger-from.html)

RemapKeys.h:
 /* DO NOT EDIT THIS FILE - it is machine generated */  
 #include <jni.h>  
 /* Header for class com_cooltrickshome_RemapKeys */  
 #ifndef _Included_com_cooltrickshome_RemapKeys  
 #define _Included_com_cooltrickshome_RemapKeys  
 #ifdef __cplusplus  
 extern "C" {  
 #endif  
 /*  
  * Class:   com_cooltrickshome_RemapKeys  
  * Method:  remapPassedKeys  
  * Signature: (II)V  
  */  
 JNIEXPORT void JNICALL Java_com_cooltrickshome_RemapKeys_remapPassedKeys  
  (JNIEnv *, jobject, jint, jint);  
 #ifdef __cplusplus  
 }  
 #endif  
 #endif  

How it works:
1) It defines the prototype of the remapPassedKeys function which will be called by our Java application.

RemapKeys.cpp
 #include <stdio.h>  
 #include <windows.h>  
 #include <w32api.h>  
 #include "RemapKeys.h"  
 static HHOOK handleKeyboardHook = NULL;  
 HINSTANCE hInst = NULL;  
 DWORD oldKey=NULL;  
 DWORD newKey=NULL;  
 static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {  
      if (nCode == HC_ACTION)  
        {  
          KBDLLHOOKSTRUCT* p = (KBDLLHOOKSTRUCT*) lParam;  
          if (p->vkCode == oldKey)  
               {  
                      switch (wParam){  
                                     case WM_KEYDOWN :{  
                                  keybd_event(newKey, 0x1D, KEYEVENTF_EXTENDEDKEY | 0, 0 );  
                                     break;  
                                                         }  
                                     case WM_KEYUP:{  
                                  keybd_event(newKey, 0x1D, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);  
                                     break;  
                                                          }  
                                                default:  
                                  wParam = WM_SYSKEYDOWN;  
                                  break;  
                                          }  
                 return 1;  
               }  
        }       
       return CallNextHookEx(handleKeyboardHook, nCode, wParam, lParam);  
 }  
 JNIEXPORT void JNICALL Java_com_cooltrickshome_RemapKeys_remapPassedKeys  
  (JNIEnv *, jobject, jint oldValue, jint newValue) {  
        /* printf("Your message here\n");  
            fflush(stdout);*/  
      oldKey=oldValue;  
       newKey=newValue;  
      hInst = GetModuleHandle(NULL);  
      handleKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,hInst, 0);  
      MSG msg;  
       while(GetMessage(&msg, NULL, 0, 0))  
       {  
        TranslateMessage(&msg);  
        DispatchMessage(&msg);  
       }       
 }  

How it works:

1) We save the key code passed by Java program in oldKey and newKey
2) Now we redefine the key by calling SetWindowsHookEx which helps in defining a application-defined hook.
3) Every time key is pressed, LowLevelKeyboardProc gets called
4) We redefine LowLevelKeyboardProc method such that whenever user press any key then it checks if it is the key which user want to be remapped.
5) If the output of step4 is true then instead of original key it will instead pass the new key by calling keybd_event

Sample Output of Program:
Open helper.txt to get the keycodes
Enter the keycode for key to be remappped (For example type 42 if you want to remap b)
30
Enter the keycode for key to be remapped with
31
Sample Keyremapper started.
Do not use for any illegal purpose.
Exit the application to get back to normal

After above input, if you press 0 then 1 would be printed

helper.txt:
http://www.kbdedit.com/manual/low_level_vk_list.html

Name Numeric value Description
VK_ABNT_C1 C1 Abnt C1
VK_ABNT_C2 C2 Abnt C2
VK_ADD 6B Numpad +
VK_ATTN F6 Attn
VK_BACK 08 Backspace
VK_CANCEL 03 Break
VK_CLEAR 0C Clear
VK_CRSEL F7 Cr Sel
VK_DECIMAL 6E Numpad .
VK_DIVIDE 6F Numpad /
VK_EREOF F9 Er Eof
VK_ESCAPE 1B Esc
VK_EXECUTE 2B Execute
VK_EXSEL F8 Ex Sel
VK_ICO_CLEAR E6 IcoClr
VK_ICO_HELP E3 IcoHlp
VK_KEY_0 30 ('0') 0
VK_KEY_1 31 ('1') 1
VK_KEY_2 32 ('2') 2
VK_KEY_3 33 ('3') 3
VK_KEY_4 34 ('4') 4
VK_KEY_5 35 ('5') 5
VK_KEY_6 36 ('6') 6
VK_KEY_7 37 ('7') 7
VK_KEY_8 38 ('8') 8
VK_KEY_9 39 ('9') 9
VK_KEY_A 41 ('A') A
VK_KEY_B 42 ('B') B
VK_KEY_C 43 ('C') C
VK_KEY_D 44 ('D') D
VK_KEY_E 45 ('E') E
VK_KEY_F 46 ('F') F
VK_KEY_G 47 ('G') G
VK_KEY_H 48 ('H') H
VK_KEY_I 49 ('I') I
VK_KEY_J 4A ('J') J
VK_KEY_K 4B ('K') K
VK_KEY_L 4C ('L') L
VK_KEY_M 4D ('M') M
VK_KEY_N 4E ('N') N
VK_KEY_O 4F ('O') O
VK_KEY_P 50 ('P') P
VK_KEY_Q 51 ('Q') Q
VK_KEY_R 52 ('R') R
VK_KEY_S 53 ('S') S
VK_KEY_T 54 ('T') T
VK_KEY_U 55 ('U') U
VK_KEY_V 56 ('V') V
VK_KEY_W 57 ('W') W
VK_KEY_X 58 ('X') X
VK_KEY_Y 59 ('Y') Y
VK_KEY_Z 5A ('Z') Z
VK_MULTIPLY 6A Numpad *
VK_NONAME FC NoName
VK_NUMPAD0 60 Numpad 0
VK_NUMPAD1 61 Numpad 1
VK_NUMPAD2 62 Numpad 2
VK_NUMPAD3 63 Numpad 3
VK_NUMPAD4 64 Numpad 4
VK_NUMPAD5 65 Numpad 5
VK_NUMPAD6 66 Numpad 6
VK_NUMPAD7 67 Numpad 7
VK_NUMPAD8 68 Numpad 8
VK_NUMPAD9 69 Numpad 9
VK_OEM_1 BA OEM_1 (: ;)
VK_OEM_102 E2 OEM_102 (> <)
VK_OEM_2 BF OEM_2 (? /)
VK_OEM_3 C0 OEM_3 (~ `)
VK_OEM_4 DB OEM_4 ({ [)
VK_OEM_5 DC OEM_5 (| \)
VK_OEM_6 DD OEM_6 (} ])
VK_OEM_7 DE OEM_7 (" ')
VK_OEM_8 DF OEM_8 (§ !)
VK_OEM_ATTN F0 Oem Attn
VK_OEM_AUTO F3 Auto
VK_OEM_AX E1 Ax
VK_OEM_BACKTAB F5 Back Tab
VK_OEM_CLEAR FE OemClr
VK_OEM_COMMA BC OEM_COMMA (< ,)
VK_OEM_COPY F2 Copy
VK_OEM_CUSEL EF Cu Sel
VK_OEM_ENLW F4 Enlw
VK_OEM_FINISH F1 Finish
VK_OEM_FJ_LOYA 95 Loya
VK_OEM_FJ_MASSHOU 93 Mashu
VK_OEM_FJ_ROYA 96 Roya
VK_OEM_FJ_TOUROKU 94 Touroku
VK_OEM_JUMP EA Jump
VK_OEM_MINUS BD OEM_MINUS (_ -)
VK_OEM_PA1 EB OemPa1
VK_OEM_PA2 EC OemPa2
VK_OEM_PA3 ED OemPa3
VK_OEM_PERIOD BE OEM_PERIOD (> .)
VK_OEM_PLUS BB OEM_PLUS (+ =)
VK_OEM_RESET E9 Reset
VK_OEM_WSCTRL EE WsCtrl
VK_PA1 FD Pa1
VK_PACKET E7 Packet
VK_PLAY FA Play
VK_PROCESSKEY E5 Process
VK_RETURN 0D Enter
VK_SELECT 29 Select
VK_SEPARATOR 6C Separator
VK_SPACE 20 Space
VK_SUBTRACT 6D Num -
VK_TAB 09 Tab
VK_ZOOM FB Zoom
VK__none_ FF no VK mapping
VK_ACCEPT 1E Accept
VK_APPS 5D Context Menu
VK_BROWSER_BACK A6 Browser Back
VK_BROWSER_FAVORITES AB Browser Favorites
VK_BROWSER_FORWARD A7 Browser Forward
VK_BROWSER_HOME AC Browser Home
VK_BROWSER_REFRESH A8 Browser Refresh
VK_BROWSER_SEARCH AA Browser Search
VK_BROWSER_STOP A9 Browser Stop
VK_CAPITAL 14 Caps Lock
VK_CONVERT 1C Convert
VK_DELETE 2E Delete
VK_DOWN 28 Arrow Down
VK_END 23 End
VK_F1 70 F1
VK_F10 79 F10
VK_F11 7A F11
VK_F12 7B F12
VK_F13 7C F13
VK_F14 7D F14
VK_F15 7E F15
VK_F16 7F F16
VK_F17 80 F17
VK_F18 81 F18
VK_F19 82 F19
VK_F2 71 F2
VK_F20 83 F20
VK_F21 84 F21
VK_F22 85 F22
VK_F23 86 F23
VK_F24 87 F24
VK_F3 72 F3
VK_F4 73 F4
VK_F5 74 F5
VK_F6 75 F6
VK_F7 76 F7
VK_F8 77 F8
VK_F9 78 F9
VK_FINAL 18 Final
VK_HELP 2F Help
VK_HOME 24 Home
VK_ICO_00 E4 Ico00 *
VK_INSERT 2D Insert
VK_JUNJA 17 Junja
VK_KANA 15 Kana
VK_KANJI 19 Kanji
VK_LAUNCH_APP1 B6 App1
VK_LAUNCH_APP2 B7 App2
VK_LAUNCH_MAIL B4 Mail
VK_LAUNCH_MEDIA_SELECT B5 Media
VK_LBUTTON 01 Left Button **
VK_LCONTROL A2 Left Ctrl
VK_LEFT 25 Arrow Left
VK_LMENU A4 Left Alt
VK_LSHIFT A0 Left Shift
VK_LWIN 5B Left Win
VK_MBUTTON 04 Middle Button **
VK_MEDIA_NEXT_TRACK B0 Next Track
VK_MEDIA_PLAY_PAUSE B3 Play / Pause
VK_MEDIA_PREV_TRACK B1 Previous Track
VK_MEDIA_STOP B2 Stop
VK_MODECHANGE 1F Mode Change
VK_NEXT 22 Page Down
VK_NONCONVERT 1D Non Convert
VK_NUMLOCK 90 Num Lock
VK_OEM_FJ_JISHO 92 Jisho
VK_PAUSE 13 Pause
VK_PRINT 2A Print
VK_PRIOR 21 Page Up
VK_RBUTTON 02 Right Button **
VK_RCONTROL A3 Right Ctrl
VK_RIGHT 27 Arrow Right
VK_RMENU A5 Right Alt
VK_RSHIFT A1 Right Shift
VK_RWIN 5C Right Win
VK_SCROLL 91 Scrol Lock
VK_SLEEP 5F Sleep
VK_SNAPSHOT 2C Print Screen
VK_UP 26 Arrow Up
VK_VOLUME_DOWN AE Volume Down
VK_VOLUME_MUTE AD Volume Mute
VK_VOLUME_UP AF Volume Up
VK_XBUTTON1 05 X Button 1 **
VK_XBUTTON2 06 X Button 2 **

Note:
Don't use it for any illegal activity.

Hope it helps :)

No comments:

Post a Comment