Java 模拟键盘

发布于 2024-12-13 23:46:51 字数 132 浏览 0 评论 0原文

如何通过 Java 类将文本发送到计算机(如键盘)? 我考虑过使用 Robot 类来按下和释放每个键,但这会很乏味,而且无法从 char 获取 KeyCode代码>.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

遇到 2024-12-20 23:46:51

不,还有一种软方法(嗯,在 Windows 上至少可以工作;-)):

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);
    }       
}

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);
    }       
}
风渺 2024-12-20 23:46:51

使用 GUI 测试框架(即使您不使用它进行测试)。我推荐FEST。在 FEST 中,您可以搜索 GUI 元素并自动执行各种用户交互,包括输入文本。

例如,一旦您有了一个文本字段固定装置(FEST 术语,表示允许您控制组件的包装器),您可以执行以下操作:

JTextComponentFixture fixture =  ...;
fixture.enterText("Some text");

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");
情绪 2024-12-20 23:46:51

@JavaCoder-1337 不完全是...

尽管仍然需要一些 switch-case (很难?) 来处理一些(特殊)字符,但大多数字符都可以处理起来相当容易。

您需要多少取决于您的目标受众,但无论如何,您都可以通过以下组合来处理:

  • AWTKeyStroke.getAWTKeyStroke(char yourChar).getKeyCode(); - 哪个
    处理最基本的问题; a-zA-Z 被翻译成它们的基础
    (az) keyEvents 和其他一些字符也以类似方式处理(仅基本键,没有修饰符,因此不应用大小写)

正如您可以想象的那样,这种方法对于简化英语处理特别有效,因为与许多其他语言相比,该语言很少使用重音字母。

  • Normalizer.normalize(String textToNormalize, Form.NFD); - 分解大多数组合(重音)字符,例如 áàãâä,éèêë,íìîï,etc,并且它们是大写的等价物,它们是基本元素。示例:á (224) 变为 a (97),后跟 ´ [769]

如果您的 send(String text) 方法能够发送重音符号,则只需对重音符号进行简单的交换(在示例中为 VK_DEAD_ACUTE)即可信,以便它们达到正确的发送顺序,您将获得所需的 á 输出。从而消除了对 á 过滤器的需要。

结合第一个简化,对于本示例,将 1/3 [´] 而不是 3/3 [a,á,´] switch-case需要!

这些只是许多简化方法中的一小部分,可以用来缩短许多程序员同事(不明智地)建议的冗长的 switch-case 方法。

例如,您可以通过检测要发送的字符是否为大写来轻松处理大小写,然后检测当前的大写锁定状态以反转大小写操作(如果需要):

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);
}

另一种选项(我使用的那个)更简单,就是简单地用更适合这种操作的工具/语言编写宏(我使用并推荐 AutoHotKey),然后只需调用它是从 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!\"");

@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-Z are 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) becomes a (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!\"");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文