# Tastatur simulieren



## minime (10. Mai 2009)

Hallo,
ich möchte gerne eine Tastatureingabe simulieren. Ich weiß, wie das mit java.awt.Robot geht, allerdings ist das ganz schön mühsam. Gibt es da eine bessere Methode, die das ganze einfacher macht? Allein schon die Eingabe "http://www.java-forum-org" wären ja schon 20 Methodenaufrufe... Hab auch schon mal gegooglet, aber wenn man nicht weiß, wie so eine Klasse heißt, ist Google recht sparsam mit Antworten.


----------



## Lexi (10. Mai 2009)

Möchtest du, dass dein Programm "http://www.java-forum-org" in die Adresszeile eines Browsers eingeben kann, oder soll das einfach nur in einem Textfeld in deinem Programm erscheinen ?


----------



## Marco13 (10. Mai 2009)

Im Zweifelsfall kann man sich (mit Hilfe von Robot) eine kleine Utility-Klasse bauen: Man übergibt ihr mit
utility.type(someString);
einen String, und in der "type"-Methode geht man den String zeichenweise durch, und läßt den Robot jedes einzelne Zeichen eintippen.


----------



## minime (10. Mai 2009)

Ich möchte allgemein, wenn ich einen Text schreiben lasse, dass das Programm hunderte Zeilen lang wird, nur weil pro Zeile ein Buchtabe gedrückt wird (fürs Loslassen ja nochmal eine Zeile). Das mit dem utility sieht gut aus, werd ich mal später in Angriff nehmen. Ich würde halt gerne einen String schreiben lassen.


```
Robot r = new Robot();
r.keyPress(KeyEvent.VK_H);
r.keyRelease(KeyEvent.VK_H);
r.keyPress(KeyEvent.VK_A;
r.keyRelease(KeyEvent.VK_A);
r.keyPress(KeyEvent.VK_L);
r.keyRelease(KeyEvent.VK_L);
r.keyPress(KeyEvent.VK_L);
r.keyRelease(KeyEvent.VK_L);
r.keyPress(KeyEvent.VK_O);
r.keyRelease(KeyEvent.VK_OH);
```

ist ja schon riesig, nur für ein simples "hallo". ich hätte halt gerne sowas wie



```
String s = "hallo";
Robot r = new Robot();
r.methodeDieStringSchreibt(s);
```

sondertasten wie STRG, Enter etc. müssen da ja gar nicht dabei sein.


(Ich weiß, dass bei den Codeschnipseln einiges fehlt, war nur zur Veranschaulichung)


----------



## sparrow (10. Mai 2009)

minime hat gesagt.:


> ist ja schon riesig, nur für ein simples "hallo". ich hätte halt gerne sowas wie


Und was spricht jetzt dagegen, dass du dir so eine winzig kleine Methode schreibst die genau das macht was du willst?


----------



## Illuvatar (10. Mai 2009)

Wobei ich zugeben muss, dass ich jetzt auch erstmal nicht wüsste, wie man ein char in einen keyCode-int konvertiert. Ansonsten sollte das aber tatsächlich kein Problem sein.

Man könnte z.B. mal überprüfen, ob die Integer-Werte der keyCodes gerade den ASCII-Werten der Chars entsprechen, dann wäre das ganz einfach.


----------



## minime (10. Mai 2009)

Ich wollte einfach wissen, ob das nicht schon jemanden vor mir so dermaßen genervt hat, dass er sich das gebastelt hat oder sogar bei Sun arbeitet und in irgendeinem Paket in awt schon sowas vorgefertigt reingepackt hat. Ich bin selbst noch Anfänger und wurde in den Robot durch die Ausbildung reingeworfen. Ich finds einfach umständlich, pro Tastendruck 2 zeilen Code zu erstellen. Aber wenns sowas noch nicht gibt, werd ichs wohl selbst schreiben müssen.


----------



## SebiB90 (10. Mai 2009)

Illuvatar hat gesagt.:


> Wobei ich zugeben muss, dass ich jetzt auch erstmal nicht wüsste, wie man ein char in einen keyCode-int konvertiert. Ansonsten sollte das aber tatsächlich kein Problem sein.
> 
> Man könnte z.B. mal überprüfen, ob die Integer-Werte der keyCodes gerade den ASCII-Werten der Chars entsprechen, dann wäre das ganz einfach.




```
KeyStroke.getKeyStroke(dasChar).getKeyCode()
```


----------



## sparrow (10. Mai 2009)

minime hat gesagt.:


> ch finds einfach umständlich, pro Tastendruck 2 zeilen Code zu erstellen. Aber wenns sowas noch nicht gibt, werd ichs wohl selbst schreiben müssen.



Musst du wohl. Diese Methode die genau 4 Zeilen enthält


----------



## minime (14. Mai 2009)

So, ich hab jetzt rumgebastelt und gesucht, die Doku rauf und runter gelesen. Ich finde einfach keine Methode, die einen char (oder byte) als Parameter will und mir dafür den int des KeyEvents gibt. Klar könnte ich nen risen case machen, allerdings wären das so 100-150 Fälle und das muss doch einfach anders gehn. Ich habe versucht, einfach in bytes aufzusplitten und die auszugeben, aber das klappt nicht. Auch mit chars kommt etwas komisches.

,/514.55 soll eigentlich notepad heißen


----------



## Schandro (14. Mai 2009)

Funktioniert das hier nicht? :


> KeyStroke.getKeyStroke(dasChar).getKeyCode()


Wurde bereits weiter oben gepostet


----------



## minime (14. Mai 2009)

Also das will trotzdem nicht so ganz. Ich würde gerne alles in AWT machen, die Klasse heißt damit AWTKeyStroke, das sollte aber nicht das Problem sein. hier mal mein Code mit Output der Sachen. An sich passt das alles.


```
import java.awt.*;

public class StringRobot
{
  public static void write(String s)
  {
    try
    {
      Robot r = new Robot();
      int i = 0;
      while (i<s.length())
      {
        AWTKeyStroke v = AWTKeyStroke.getAWTKeyStroke(s.charAt(i));
        int j = AWTKeyStroke.getAWTKeyStroke(s.charAt(i)).getKeyCode();
        System.out.println("KeyEvent ist: "+j + " ,ausführlich: " + v);
        r.keyPress(j);
        r.keyRelease(j);
        i++;
      }
    }
    catch(AWTException e)
    {
      System.err.println(e);
    }

  }
}
```


Ausgabe ist:




> Starte D:\Java\StringRobot\StrinRobotTest.java
> 
> KeyEvent ist: 0 ,ausführlich: typed n
> 
> ...



Testprogramm ist:


```
import java.awt.*;
import java.awt.event.*;

public class StrinRobotTest
{
   public static void main(String[]args) throws AWTException, InterruptedException
   {
     Robot r = new Robot();
     r.keyPress(KeyEvent.VK_CONTROL);
     r.keyPress(KeyEvent.VK_ESCAPE);
     r.keyRelease(KeyEvent.VK_ESCAPE);
     r.keyRelease(KeyEvent.VK_CONTROL);
     StringRobot.write("notepad.exe");
     r.wait(1000);
   }
}
```

Wo ist mein Fehler? Ich will ja nix fertiges hingeklatscht kriegen, nur sagt mir einer, warum das nicht geht? Der schreibt jetzt nicht ein Zeichen mehr. Also ich hab Vista und der sollte unten ins Startmenü reinschreiben. War mir die schnellste Methode, ein Textfeld zu kriegen(STRG+ESC).


----------



## Illuminatus0301 (14. Mai 2009)

ich weiß jetzt nicht, wo der Fehler liegt, aber ich würde statt

```
r.keyPress(j);
r.keyRelease(j);
```
eher

```
synchronized(r) {
r.keyPress(j);
r.keyRelease(j);
}
```
damit der Thread nicht im falschen moment unterbrochen wird und der mehrere male den Buchstaben registriert, da ja die Taste so lange festgehalten wird (wird zwar nicht häufig vorkommen, aber man sollte ja alles so gründlich machen wie es geht)


----------



## minime (14. Mai 2009)

Hmm ja ok danke, sind aber mehr Schönheitskorrekturen. Der macht nen int mit dem Wert 0 (er erzeugt wirklich einen, hab einen auf 2 initialisiert, er gibt trotzdem 0 aus), obwohl er das typed n erkannt hat. Warum?

Edit: Ach ja, das sind übrigens die int-Werte zu den Tasten:

Constant Field Values (Java 2 Platform SE v1.4.2)

Noch ein Edit: beim genaueren Schauen könnten das tatsächlich ASCII/Unicode Werte sein, allerdings ist die Frage, wie ich die Großbuchstaben dann machen soll...

Dritter Edit: Er erkennt, ob ich ein großes oder ein kleines N schreiben will.


----------



## minime (15. Mai 2009)

Hier mein aktueller Code. die Methode schreibt Großbuchstaben, Kleinbuchstaben und alle Zeichen, die den gleichen KeyEvent-int-Wert haben wie ASCII-Wert, z.B. den Punkt.
Jetzt brauch ich nur noch ne Idee für die restlichen Sonderzeichen, z.B. das Ausrufezeichen geht noch nicht.


```
import java.awt.*;
import java.awt.event.*;

public class StringRobot
{
  public static void write(String s)
  {
    try
    {
      Robot r = new Robot();
      int i = 0;
      char[] buchstaben = s.toCharArray();
      while (i<s.length())
      {
        System.out.println("KeyEvent ist: "+ buchstaben[i]);
        if(Character.isUpperCase(buchstaben[i]))
        {
           r.keyPress(KeyEvent.VK_SHIFT);
        }
        synchronized(r)
        {
          r.keyPress(Character.toUpperCase(buchstaben[i]));
          r.delay(500);
          r.keyRelease(Character.toUpperCase(buchstaben[i]));
        }
        if(Character.isUpperCase(buchstaben[i]))
        {
           r.keyRelease(KeyEvent.VK_SHIFT);
        }
        i++;
      }
    }
    catch(AWTException e)
    {
      System.err.println(e);
    }
  }
}
```


----------



## StephanK (15. Jul 2009)

Hi,

hast Du inzwischen eine elegante Lösung gefunden? Ich hänge an genau dem gleichen Problem und würde gerne meine Routine entsprechend verbessern. Aktuell sende ich nämlich Sonderzeichen wie bspw. "!" als VK_SHIFT + VK_1 und Umlaute wie bspw. "ä" als VK_ALT + VK_NUMPAD1 + VK_NUMPAD3 + VK_NUMPAD2.

Das ist natürlich genau das Gegenteil von elegant.

Beste Grüße

Stephan


----------



## minime (15. Jul 2009)

Sorry, hab das gar nicht weiterverfolgt. Aber kannst deine Klasse ja mal reinstellen.


----------



## Ebenius (15. Jul 2009)

StephanK hat gesagt.:


> [...]und Umlaute wie bspw. "ä" als VK_ALT + VK_NUMPAD1 + VK_NUMPAD3 + VK_NUMPAD2.
> 
> Das ist natürlich genau das Gegenteil von elegant.


... und dürfte zudem nur unter Windows funktionieren.

Ich glaube fast, dieses Problem ist nicht lösbar.

Ebenius


----------



## minime (15. Jul 2009)

Klar geht das, mit einem riesigen case-Statement(in Java Switch). Aber darauf hatte ich noch keine Lust...


----------



## madboy (15. Jul 2009)

minime hat gesagt.:


> Klar geht das, mit einem riesigen case-Statement(in Java Switch). Aber darauf hatte ich noch keine Lust...


Spätestens beim Fragezeichen wirst du Probleme bekommen... Da gibt's nämlich keinen keycode dafür


----------



## Ebenius (16. Jul 2009)

minime hat gesagt.:


> Klar geht das, mit einem riesigen case-Statement(in Java Switch). Aber darauf hatte ich noch keine Lust...


Nein, es geht nicht. Ich habe keine Möglichkeit gefunden, einen keyPressed-Event für eine Ä-Taste abzufangen oder zu erzeugen. Der KeyCode ist immer [c]0[/c]. Die Kombination aus ALT+Code-Sequenz gibt's -- soweit ich weiß -- nur unter Windows. Zeig doch mal, wie Du sonst ein 'Ä' per Robot sendest; ich kenne keinen Weg.

Ebenius


----------

