[PARCIALMENTE RESOLVIDO] "Apertar" Teclas

Olá pessoal.
Gostaria de saber se o Java dispõe alguma função que ajude-me em “apertar” teclas.

Por exemplo, que o próprio programa-console faça alguma seqüencia de teclas. Por exemplo:

if(fazer_Sequencia("Ctrl", "Arrow Up")){
System.Out.Printf("O sistema fez a sequencia de teclas: Control e Flecha p/ Cima!");
}

Ou que ele faça um texto sozinho.
Por exemplo:

if(apertar("O", "L", "Á") { System.out.Prinft("O sistema escreveu \"Olá\" no Bloco de Notas!"); }

Obrigado desde já,
Mijuaho.

Veja a classe Robot.

Vou pesquisar sobre essa classe.

Obrigado por comentar!

Eu estava mexendo com um projetinho que usa um pouco disso… na verdade o que vou colocar aqui é justamente a parte que visa tornar mais inteligível o funcionamento da classe Robot.

package robot;

import static java.awt.event.KeyEvent.VK_AMPERSAND;
import static java.awt.event.KeyEvent.VK_ASTERISK;
import static java.awt.event.KeyEvent.VK_AT;
import static java.awt.event.KeyEvent.VK_BACK_SLASH;
import static java.awt.event.KeyEvent.VK_CIRCUMFLEX;
import static java.awt.event.KeyEvent.VK_CLOSE_BRACKET;
import static java.awt.event.KeyEvent.VK_COLON;
import static java.awt.event.KeyEvent.VK_COMMA;
import static java.awt.event.KeyEvent.VK_DEAD_TILDE;
import static java.awt.event.KeyEvent.VK_DOLLAR;
import static java.awt.event.KeyEvent.VK_EQUALS;
import static java.awt.event.KeyEvent.VK_EXCLAMATION_MARK;
import static java.awt.event.KeyEvent.VK_LEFT_PARENTHESIS;
import static java.awt.event.KeyEvent.VK_MINUS;
import static java.awt.event.KeyEvent.VK_NUMBER_SIGN;
import static java.awt.event.KeyEvent.VK_OPEN_BRACKET;
import static java.awt.event.KeyEvent.VK_PERIOD;
import static java.awt.event.KeyEvent.VK_PLUS;
import static java.awt.event.KeyEvent.VK_QUOTEDBL;
import static java.awt.event.KeyEvent.VK_RIGHT_PARENTHESIS;
import static java.awt.event.KeyEvent.VK_SEMICOLON;
import static java.awt.event.KeyEvent.VK_SLASH;
import static java.awt.event.KeyEvent.VK_SPACE;
import static java.awt.event.KeyEvent.VK_UNDERSCORE;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public final class KeyMapper {

	public static final Map<Character, Integer> KEYS;

	static {
		Map<Character, Integer> map = new HashMap<Character, Integer>();
		for (char c = 'A'; c <= 'Z'; c++) {
			map.put(c, (int) c);
		}
		for (char c = '0'; c <= '9'; c++) {
			map.put(c, (int) c);
		}
		for (char c = '\b'; c <= '\n'; c++) {
			map.put(c, (int) c);
		}
		map.put(' ', VK_SPACE);
		map.put(',', VK_COMMA);
		map.put('.', VK_PERIOD);
		map.put('!', VK_EXCLAMATION_MARK);
		map.put('\', VK_BACK_SLASH);
		map.put('|', VK_BACK_SLASH);
		map.put(':', VK_COLON);
		map.put('$', VK_DOLLAR);
		map.put('_', VK_UNDERSCORE);
		map.put(';', VK_SEMICOLON);
		map.put(':', VK_SEMICOLON);
		map.put('-', VK_MINUS);
		map.put('*', VK_ASTERISK);
		map.put('+', VK_PLUS);
		map.put('/', VK_SLASH);
		map.put('?', VK_SLASH);
		map.put('=', VK_EQUALS);
		map.put('@', VK_AT);
		map.put('^', VK_CIRCUMFLEX);
		map.put('(', VK_LEFT_PARENTHESIS);
		map.put(')', VK_RIGHT_PARENTHESIS);
		map.put('#', VK_NUMBER_SIGN);
		map.put('[', VK_OPEN_BRACKET);
		map.put(']', VK_CLOSE_BRACKET);
		map.put('{', VK_OPEN_BRACKET);
		map.put('}', VK_CLOSE_BRACKET);
		map.put('&', VK_AMPERSAND);
		map.put('
[code]
package robot;

import static java.awt.event.InputEvent.*;
import static robot.KeyMapper.*;
import static java.awt.event.KeyEvent.*;

import java.awt.Robot;

public final class RobotManager {

	private Robot robot;

	public RobotManager(Robot robot) throws NullPointerException {
		if (robot == null) {
			throw new NullPointerException();
		}
		this.robot = robot;
	}

	public void click(int x, int y) {
		robot.mouseMove(x, y);
		robot.mousePress(BUTTON1_MASK);
	}

	public void rightClick(int x, int y) {
		robot.mouseMove(x, y);
		robot.mousePress(BUTTON2_MASK);
	}

	public void type(int key) {
		robot.keyPress(key);
		robot.keyRelease(key);
	}

	public void typeSequence(int... keys) {
		for (int i = 0; i < keys.length; i++) {
			robot.keyPress(keys[i]);
		}
		for (int i = keys.length - 1; i >= 0; i--) {
			robot.keyRelease(keys[i]);
		}
	}

	public void type(String string) {
		for (char c : string.toCharArray()) {
			if (Character.isUpperCase(c) || mustPressShift(c)) {
				robot.keyPress(VK_SHIFT);
			}
			Integer i = KEYS.get(Character.toUpperCase(c));
			if (i == null) {
				i = VK_NUMBER_SIGN;
			}
			type(i);
			if (Character.isUpperCase(c) || mustPressShift(c)) {
				robot.keyRelease(VK_SHIFT);
			}
		}
	}

	private boolean mustPressShift(char c) {
		return c == '!' || c == '@' || c == '#' || c == '$' || c == '%'
				|| c == '&' || c == '*' || c == '(' || c == ')' || c == '`'
				|| c == '{' || c == '}' || c == '^' || c == '?' || c == ':'
				|| c == '>' || c == '<' || c == '|' || c == '\"';
	}

}
[/code]
E um pequeno exemplo que no Eclipse cria e executa uma classe:
[code]
package robot;

import static java.awt.event.KeyEvent.VK_A;
import static java.awt.event.KeyEvent.VK_CONTROL;
import static java.awt.event.KeyEvent.VK_DOWN;
import static java.awt.event.KeyEvent.VK_F;
import static java.awt.event.KeyEvent.VK_F11;
import static java.awt.event.KeyEvent.VK_N;
import static java.awt.event.KeyEvent.VK_S;
import static java.awt.event.KeyEvent.VK_SHIFT;

import java.awt.Robot;

public class RobotTest {

	public static void main(String[] args) throws Exception {
		Robot robot = new Robot();
		robot.setAutoDelay(50);
		robot.setAutoWaitForIdle(true);
		robot.delay(1000);
		RobotManager manager = new RobotManager(robot);
		// Ctrl + N (New)
		manager.typeSequence(VK_CONTROL, VK_N);
		robot.delay(500);
		// new class
		manager.type("class\n\n");
		robot.delay(500);
		// class name: HelloRobot
		manager.type("HelloRobot\n");
		robot.delay(2000);
		// Ctrl + A (Select all)
		manager.typeSequence(VK_CONTROL, VK_A);
		// type class code
		manager.type("package robot;\n\npublic class HelloRobot {\n\n");
		manager.type("public static void main(String[] args) {\n");
		manager.type("System.out.println(\"Hello from a robot!\");");
		manager.type(VK_DOWN);
		manager.type('\n');
		// Ctrl + Shift + F (Format)
		manager.typeSequence(VK_CONTROL, VK_SHIFT, VK_F);
		robot.delay(500);
		// Ctrl + S (Save)
		manager.typeSequence(VK_CONTROL, VK_S);
		robot.delay(1000);
		// Ctrl + F11 (Run)
		manager.typeSequence(VK_CONTROL, VK_F11);
	}

}
[/code]
Note que está bem longe de ser uma solução para todos os problemas (até porque o suporte a caracteres acentuados simplesmente não existe), mas é um começo.', VK_QUOTEDBL);
		map.put('\"', VK_QUOTEDBL);
		map.put('<', VK_COMMA);
		map.put('>', VK_PERIOD);
		map.put('&', VK_AMPERSAND);
		map.put('~', VK_DEAD_TILDE);
		map.put('^', VK_DEAD_TILDE);
		KEYS = Collections.unmodifiableMap(map);
	}

	private KeyMapper() {
		// can not instantiate
	}

}
package robot;

import static java.awt.event.InputEvent.*;
import static robot.KeyMapper.*;
import static java.awt.event.KeyEvent.*;

import java.awt.Robot;

public final class RobotManager {

	private Robot robot;

	public RobotManager(Robot robot) throws NullPointerException {
		if (robot == null) {
			throw new NullPointerException();
		}
		this.robot = robot;
	}

	public void click(int x, int y) {
		robot.mouseMove(x, y);
		robot.mousePress(BUTTON1_MASK);
	}

	public void rightClick(int x, int y) {
		robot.mouseMove(x, y);
		robot.mousePress(BUTTON2_MASK);
	}

	public void type(int key) {
		robot.keyPress(key);
		robot.keyRelease(key);
	}

	public void typeSequence(int... keys) {
		for (int i = 0; i < keys.length; i++) {
			robot.keyPress(keys[i]);
		}
		for (int i = keys.length - 1; i >= 0; i--) {
			robot.keyRelease(keys[i]);
		}
	}

	public void type(String string) {
		for (char c : string.toCharArray()) {
			if (Character.isUpperCase(c) || mustPressShift(c)) {
				robot.keyPress(VK_SHIFT);
			}
			Integer i = KEYS.get(Character.toUpperCase(c));
			if (i == null) {
				i = VK_NUMBER_SIGN;
			}
			type(i);
			if (Character.isUpperCase(c) || mustPressShift(c)) {
				robot.keyRelease(VK_SHIFT);
			}
		}
	}

	private boolean mustPressShift(char c) {
		return c == '!' || c == '@' || c == '#' || c == '$' || c == '%'
				|| c == '&' || c == '*' || c == '(' || c == ')' || c == '`'
				|| c == '{' || c == '}' || c == '^' || c == '?' || c == ':'
				|| c == '>' || c == '<' || c == '|' || c == '\"';
	}

}

E um pequeno exemplo que no Eclipse cria e executa uma classe:

package robot;

import static java.awt.event.KeyEvent.VK_A;
import static java.awt.event.KeyEvent.VK_CONTROL;
import static java.awt.event.KeyEvent.VK_DOWN;
import static java.awt.event.KeyEvent.VK_F;
import static java.awt.event.KeyEvent.VK_F11;
import static java.awt.event.KeyEvent.VK_N;
import static java.awt.event.KeyEvent.VK_S;
import static java.awt.event.KeyEvent.VK_SHIFT;

import java.awt.Robot;

public class RobotTest {

	public static void main(String[] args) throws Exception {
		Robot robot = new Robot();
		robot.setAutoDelay(50);
		robot.setAutoWaitForIdle(true);
		robot.delay(1000);
		RobotManager manager = new RobotManager(robot);
		// Ctrl + N (New)
		manager.typeSequence(VK_CONTROL, VK_N);
		robot.delay(500);
		// new class
		manager.type("class\n\n");
		robot.delay(500);
		// class name: HelloRobot
		manager.type("HelloRobot\n");
		robot.delay(2000);
		// Ctrl + A (Select all)
		manager.typeSequence(VK_CONTROL, VK_A);
		// type class code
		manager.type("package robot;\n\npublic class HelloRobot {\n\n");
		manager.type("public static void main(String[] args) {\n");
		manager.type("System.out.println(\"Hello from a robot!\");");
		manager.type(VK_DOWN);
		manager.type('\n');
		// Ctrl + Shift + F (Format)
		manager.typeSequence(VK_CONTROL, VK_SHIFT, VK_F);
		robot.delay(500);
		// Ctrl + S (Save)
		manager.typeSequence(VK_CONTROL, VK_S);
		robot.delay(1000);
		// Ctrl + F11 (Run)
		manager.typeSequence(VK_CONTROL, VK_F11);
	}

}

Note que está bem longe de ser uma solução para todos os problemas (até porque o suporte a caracteres acentuados simplesmente não existe), mas é um começo.

Consigo mexer agora no Robot não tão dificilmente, mas…
Eu já fiz as ações de teclas, mas o bot simplesmente não “aperta as teclas”.

Eu tenho que fazer com que o robot aperte a seqüencia em “outra janela”.
Até agora parece que não houve efeito. Eu fiz um thread.sleep, para que dê tempo do usuário mudar de janela,
então fui testar e deixei a janela do NotePad aberta e ativa [primeiro plano].

Mas parece que a seqüencia não funcionou. Como se fizesse efeito somente no Console.

Qual a solução?

OBS: Código do programa (na parte do bot) basicamente é:

Robot gc_bot = new Robot(); gc_bot.delay(3500); gc_bot.keyPress(KeyEvent.VK_F9); gc_bot.keyRelease(KeyEvent.VK_F9); System.out.println("\n * Voce entrou na sala com sucesso!"); try {Thread.sleep(15000);} catch (InterruptedException e) { } walk_to_Portal(1); // Vai para o Stage 1!
Agradeço desde já,
Mijuaho.

Para o robô esperar use o método delay da classe Robot, e não Thread.sleep.

Esse código que você colocou acima aguarda 3 segundos e meio e pressiona F9. Ele não está fazendo isso?

[quote=marcobiscaro2112]Para o robô esperar use o método delay da classe Robot, e não Thread.sleep.

Esse código que você colocou acima aguarda 3 segundos e meio e pressiona F9. Ele não está fazendo isso?[/quote]

Removi o thread.sleep que estava antes deste código que postei.

Mas ainda sim, o robô espera três segundos, não acontece nada e ele pula para a outra parte do código. (que faz re-iniciar a função).
E aí fica um “loop” de fazer nada.

Eu preciso de que o robô faça o F9 em outro programa.
Já deixei a janela do outro programa ativa, e o console em back-ground não-ativo.
Mas mesmo assim, não dá em nada.

Ah, resolvi!

Eu precisei fazer com que o próprio Java abrisse o programa. (por algum motivo. lol)

  Runtime.getRuntime().exec("open_game.install.exe");

Mas, o arquivo que eu quero abrir, exige um delay extremamente alto.
(uns 5minutos).

Pois ele é muito pesado e etc.
Pois bem, tentei iniciar, mas o Java tem um limite de 60.000 milisegundos de Delay. Tem como eu aumentar isso?
(no Console apareceu vários erros no Java e fechou em menos de um segundo. Então abri denovo, tirei ScreenShot, botei no paint e vi que o Java não pode exceder 60.000miliseconds)
Caso não, como devo proceder? Fazer o thread dormir?