How would I send text to the computer (like a keyboard) via a Java class?
I have considered using the Robot class to press and release each key, but that would be tedious and there is no way to get the KeyCode from a char.
-
Do you want to send text to other programs or your own program?Pace– Pace2011-11-07 12:43:29 +00:00Commented Nov 7, 2011 at 12:43
-
My goal is to send text to a word document, a google search, etc.Dylan Wheeler– Dylan Wheeler2011-11-07 12:46:45 +00:00Commented Nov 7, 2011 at 12:46
4 Answers
No, there is also a soft way (well, on Windows it works at least ;-)):
private static void outputString(Robot robot,String str)
{
Toolkit toolkit = Toolkit.getDefaultToolkit();
boolean numlockOn = toolkit.getLockingKeyState(KeyEvent.VK_NUM_LOCK);
int[] keyz=
{
KeyEvent.VK_NUMPAD0,
KeyEvent.VK_NUMPAD1,
KeyEvent.VK_NUMPAD2,
KeyEvent.VK_NUMPAD3,
KeyEvent.VK_NUMPAD4,
KeyEvent.VK_NUMPAD5,
KeyEvent.VK_NUMPAD6,
KeyEvent.VK_NUMPAD7,
KeyEvent.VK_NUMPAD8,
KeyEvent.VK_NUMPAD9
};
if(!numlockOn)
{
robot.keyPress(KeyEvent.VK_NUM_LOCK);
}
for(int i=0;i<str.length();i++)
{
int ch=(int)str.charAt(i);
String chStr=""+ch;
if(ch <= 999)
{
chStr="0"+chStr;
}
robot.keyPress(KeyEvent.VK_ALT);
for(int c=0;c<chStr.length();c++)
{
int iKey=(int)(chStr.charAt(c)-'0');
robot.keyPress(keyz[iKey]);
robot.keyRelease(keyz[iKey]);
}
robot.keyRelease(KeyEvent.VK_ALT);
}
if(!numlockOn)
{
robot.keyPress(KeyEvent.VK_NUM_LOCK);
}
}
Comments
Try use this :
3 Comments
Use a GUI testing framework (even if you do not use it for testing). I recommend FEST. In FEST you can search for GUI elements and automate all kinds of user interactions including entering text.
For example once you have a text field fixture (the FEST term for a wrapper that lets you control the component), you can do
JTextComponentFixture fixture = ...;
fixture.enterText("Some text");
Comments
@JavaCoder-1337 Not exactly...
Although some switch-case (hard way?) is still needed to handle some (special) characters, most of the characters can be handled fairly easily.
How much you need depends on your target audience, but whatever the case, you can handle it through a combination of:
AWTKeyStroke.getAWTKeyStroke(char yourChar).getKeyCode();- Which handles the most basic ones;a-zA-Zare translated to they'r base(a-z)keyEvents, and a few other chars are also handled similarly(base key only, no modifiers thus no casing is applied).
As you can imagine, this method is particularly effective for simplifying English handling, since the language makes little use of accented letters compared to many others.
Normalizer.normalize(String textToNormalize, Form.NFD);- Which decomposes most composed (accented) characters, likeáàãâä,éèêë,íìîï,etc, and they'r uppercase equivalents, to they'r base elements. Example:á (224)becomesa (97)followed by´ [769].
If your send(String text) method is able to send accents, a simple swap of the accent (in the example it's VK_DEAD_ACUTE) and it's letter, so that they get to proper send order, and you will get the desired á output. Thus eliminating the need for an á filter.
Combined with the first simplification, for this example, that makes 1/3 [´] instead of 3/3 [a,á,´] switch-case needed!
These are only a few of many simplifications that can be done to shorten that dreadfully long switch-case method that is (unwisely) suggested by many fellow programmers.
For example, you can easily handle casing by detecting if the character to be sent is uppercase, and then detecting the current capslock state to invert the casing operation, if needed:
boolean useShift = Character.isUpperCase(c);
useShift = Toolkit.getDefaultToolkit().getLockingKeyState(KeyEvent.VK_CAPS_LOCK) ? !useShift : useShift;
if (useShift) {
keyPress(KeyEvent.VK_SHIFT);
sendChar(aChar);
keyRelease(KeyEvent.VK_SHIFT);
} else {
sendChar(aChar);
}
Another option (the one that I use), which is even simpler, is to simply code a macro in a tool/language that is (far) more suited for this kind of operation (I use and recommend AutoHotKey), and simply call it's execution from Java:
Runtime rt = Runtime.getRuntime();
//"Hello World!" is a command-line param, forwarded to the ahk script as it's text-to-send.
rt.exec(".../MyJavaBot/sendString.ahk \"Hello World!\"");