views:

601

answers:

4

I am writing some code to type strings using the Robot class. Everything is mostly good (well, I have to use a big switch statement to get character keycodes), except some keys don't have keycodes, because they are actually a combination of SHIFT + some other key. For upper case letters, it is easy to check, using Character.isUpperCase(c), but for all the symbols such as !@#$%^&()+ and various punctuation are not considered "upper case" although they do require shift to be pressed in order to generate thier keystroke. I tried googling for it, but just found a forum post with no satisfactory answers. Is there any way to determine whether a character needs shift to be pressed, and if so, what character is the "un-shifted" version?

EDIT: Here is the code I have so far.

public void GenerateKeyTyped(char c) {
 if (Character.isUpperCase(c)) {
  r.keyPress(KeyEvent.VK_SHIFT);
 }
 r.keyPress(GetKeyCode(c));
 r.keyRelease(GetKeyCode(c));
 if (Character.isUpperCase(c)) {
  r.keyRelease(KeyEvent.VK_SHIFT);
 }
}
A: 

If you look at the ASCII table these symbol keys are located in the range 0x21 - 0x2B
You can probably look at the ASCII table for recognizing all your other symbols.

nik
Yes, I could do another big switch statement, but I was wondering if there was some API for this.
Jeremybub
+1  A: 

I'm not sure if what you're looking for is possible. You could create your own table, but keep in mind that it'll then work for one keyboard layout only (many languages have their own keyboard layouts that are more suited for their specific character sets, also, there's the Dvorak layout that probably has it's own shifted vs unshifted keys) unless you take into account all keyboard layouts you want to support, and create custom tables for those.

Jack Leow
For what it's worth, the standard Windows Dvorak layout has the same set of shifted / unshifted characters as a regular QWERTY keyboard. Generating a particular character on Dvorak requires shift iff it also requires shift on QWERTY.
Aric TenEyck
Ah, good to know, thanks!
Jack Leow
+1  A: 

Can you use AWT classes? Something like this might work:

AWTKeyStroke ks = AWTKeyStroke.getAWTKeyStroke('!');
int modifers = ks.getModifiers();

if ((modifiers & KeyEvent.VK_SHIFT) == KeyEvent.VK_SHIFT) {
    // Shift pressed
}
geofflane
Jeremybub
+1  A: 

I don't know a way to solve your problem directly ( I just ended up using a Map for those characters) but it might give you some ideas:

import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Main3 {

    public static void main(String[] args) {
        try {
            Robot robot = new Robot();

            HashMap<String, String> map = new HashMap<String, String>();
            map.put("!", "1");
            map.put("@", "2");
            map.put("#", "3");

            char[] charz = "abcdefgABCDEFG123!#".toCharArray();

            for(int i = 0; i < charz.length; i++)
            {
                System.out.print(charz[i] + " : ");
                boolean shiftRequired = false;
                String key = String.valueOf(charz[i]);
                String value = map.get(key);

                if (value != null)
                {
                    shiftRequired = true;
                    key = value;
                }
                else if (Character.isUpperCase(key.charAt(0)))
                {
                    shiftRequired = true;
                }
                else
                {
                    key = key.toUpperCase();
                }

                KeyStroke ks = KeyStroke.getKeyStroke("pressed " + key.toUpperCase());

                int keyCode = ks.getKeyCode();
                System.out.println(keyCode);

                if (shiftRequired)
                    robot.keyPress(java.awt.event.KeyEvent.VK_SHIFT);

                robot.keyPress( keyCode );
                robot.keyRelease( keyCode );

                if (shiftRequired)
                    robot.keyRelease(java.awt.event.KeyEvent.VK_SHIFT);
            }


        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}
camickr
I did a similar thing, with two arrays instead of a HashMap.
Jeremybub