Java的搜索屏幕上的文本字段 [英] Java search for on-screen text field

查看:456
本文介绍了Java的搜索屏幕上的文本字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个程序,可以自动将文本字段重复搜索屏幕和类型就一个字到该文本字段。有没有能找到一个文本字段的任何类?或者有没有在其中的文本字段,可以找到什么办法?因为我知道,机器人类可以输入文字,我只需要要么得到光标移到文本字段并用鼠标$ P $(PSS)和mouseRelease()方法。

I am trying to create a program that automatically searches for a text field on the screen and types a word repetitively into that text field. Is there any class that can find a text field? Or is there any way in which a text field can be found? Because I know that the Robot class can type text, I just need to either get the cursor onto the text field and use the mousePress() and mouseRelease() methods.

感谢

推荐答案

我不能直接给你一个解决方案,但我有一些code搞砸周围,也许能为你指明正确的方向。

I can't directly give you a solution, but I messed around with some code and may be able to point you in the right direction.

Java的,正如你可能知道,运行在JVM。这使得它可以在任何操作环境中执行。每个操作环境(Windows,MAC等)都有自己的处理编辑框和焦点设置在右边的窗口和诸如此类的东西体系。下面的例子code设计为只能在Windows使用,不遵循Java语言的精神。正如阿德里安指出,还有其他语言的这样的事情,但有可能(在某种程度上)单独的Java实现。

Java, as you probably know, runs in the JVM. This allows it to execute in any operating environment. Each operating environment (windows, mac, etc) has its own system for handling edit boxes and setting focus to the right window and whatnot. The following example code is designed for use on windows only, which does not follow the spirit of the Java language. As Adriaan pointed out, there are other languages for this sort of thing, but it IS possible (to an extent) to accomplish with Java alone.

在Windows中,您必须了解所有活动窗口中进行管理,你会看到(包括编辑框),一切都在考虑一个窗口,由Windows操作系统。我并不真正了解事物的引擎盖下是如何工作的,所以我不能提供比这更多的信息。在本地语言,如C ++,也有通过将用于实现自己的目标的Windows操作系统API提供了一些功能。也就是说, EnumWindows的() EnumChildWindows() GetClassName() SetForegroundWindow()。你可以找到如何通过搜索MSDN文档库使用本国语言中这些功能的文档。

In windows, you must understand how all of the active windows are managed and that everything you see (including edit boxes) are considering a "window" by the Windows OS. I don't truly understand how things work under the hood, so I can't provide much more information than that. In a native language such as C++, there are a few functions provided by the Windows OS API that would be used to accomplish your goal. Namely, EnumWindows(), EnumChildWindows(), GetClassName(), and SetForegroundWindow(). You can find documentation on how to use these functions within a native language by searching the MSDN documentation library.

因此​​,既然说,你需要能够从Java调用这些函数。在正常情况下,要求这些本地方法是不可能的。但是,可以帮助你从图书馆:在JNA库。 JNA代表Java本地接入,让你与我前面提到的闪亮的新职能的工作。

So with that said, you NEED to be able to call these functions from Java. Under normal circumstances, calling these native methods is not possible. However, there is a library available to help you out: the JNA library. JNA stands for Java Native Access and lets you work with the shiny new functions I mentioned earlier.

因此​​,要实现本地语言你的目标,通常人们会一起 EnumWindows的调用()开始恢复所有的父窗口的操作系统是列表意识到。该列表将包含其父窗口的窗口句柄 - 标题为MSN,日蚀,微​​软的Office窗等这些窗口,作为父母,有孩子。这是孩子们,你会发现控制,你正在寻找此列表:一个修改控制。现在,许多应用程序使用不同的库和非标准的东西文本框 - 即洋泾浜,我测试了一些相关的code有消息应用程序,每一个都有一个名为gdkWindowChild控制,不正是告诉我们这控制实际上是一个编辑框或一个地方,可以让我们输入文字。那是你的想法的主要问题;你不能总是告诉正是控制你想拥有的,这样你可以输入文本焦点。不管,我们将继续:

So, to accomplish your goal in a native language, normally one would begin with a call toEnumWindows() to return a list of all Parent windows that the OS is aware of. This list will contain window handles of parent windows - windows titled "MSN", "Eclipse", "Microsoft Office", etc. Each of these windows, as a Parent, has children. It is in this list of children that you will find the "control" that you are looking for: an Edit control. Now, many applications use different libraries and non-standard things for text boxes - i.e Pidgin, a messaging application I tested some relevant code with, has every control named "gdkWindowChild" which doesn't exactly tell us which control is actually an EditBox or otherwise a place that allows us to enter text. That's the main problem with your idea; you can't always tell exactly what control you wish to have focus of so that you may enter text. Regardless of that, we'll continue:

EnumWindows的(),到 EnumChildWindows()的调用将给我们所有人找到相关的父窗口之后那属于母公司的子窗口和其他控制(包括潜在的编辑盒)。 EnumChildWindows()呼吁为它找到的每个子窗口的回调函数,所以它是pretty容易通过子窗口列表搜索 - 使用 GetClassName()来找到一个控件的名称 - 潜在的找到你想要控制的HWND(窗口句柄)

After finding the relevant Parent window with EnumWindows(), a call to EnumChildWindows() will give us all of the sub-windows and other "controls" (including potential edit-boxes) that belong to the Parent. EnumChildWindows() calls a callback function for each sub-window it finds, so it's pretty easy to "search" through the list of child windows - using GetClassName() to find the name of a control - to potentially find the HWND (window handle) of the control you want.

一旦你找到编辑框的正确HWND(即,当然,正在困难的部分给你的问题​​的一般范围)一个简单的调用 SetForegroundWindow(targetHWND)应把控制权交给前方并设置光标一个现成的类型编辑框。

Once you have found the correct HWND of the edit box (that, of course, being the difficult part given the general scope of your question) a simple call to SetForegroundWindow(targetHWND) ought to bring the control to the front and set your cursor in a ready-to-type edit box.

下面是一些工作的例子code,我写,让你开始。这code将通过全部使用 EnumWindows的()的活动窗口中的迭代,然后调用 EnumChildWindows()上每个父母,打印出所有找到的控件。请注意,这code要求JNA库运行。

Here is some working example code I've written to get you started. This code will iterate through all of the active windows using EnumWindows() and then call EnumChildWindows() on each parent, printing out all of the controls that it finds. Note that this code requires the JNA library to run.

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.examples.win32.W32API.HWND;
import com.sun.jna.examples.win32.W32API.LPARAM;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;


public class IterateChildWindows {
    public interface User32 extends StdCallLibrary {
        User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class, W32APIOptions.DEFAULT_OPTIONS);

        HWND FindWindow(String lpClassName, String lpWindowName);
        int GetWindowRect(HWND handle, int[] rect);
        int SendMessage(HWND hWnd, int msg, int wParam, byte[] lParam); 
        HWND FindWindowEx(HWND parent, HWND child, String className, String window);

        boolean EnumWindows(WNDENUMPROC lpEnumFunc, Pointer arg);
        boolean EnumChildWindows(HWND parent, WNDENUMPROC callback, LPARAM info);

        interface WNDENUMPROC extends StdCallCallback {
            boolean callback(HWND hWnd, Pointer arg);
        }

        int GetWindowTextA(HWND hWnd, byte[] lpString, int nMaxCount);
        long GetWindowLong(HWND hWnd, int index);
        boolean SetForegroundWindow(HWND in);
        int GetClassNameA(HWND in, byte[] lpString, int size);
    }

    public static void main(String[] args) {        
        User32.INSTANCE.EnumWindows(new User32.WNDENUMPROC() {
            public boolean callback(HWND hWnd, Pointer userData) { // this will be called for each parent window found by EnumWindows(). the hWnd parameter is the HWND of the window that was found.
                byte[] textBuffer = new byte[512];
                User32.INSTANCE.GetWindowTextA(hWnd, textBuffer, 512);
                String wText = Native.toString(textBuffer);
                System.out.println("Window found: " + wText);

                // now call EnumChildWindows() giving the previously found parent window as the first parameter
                User32.INSTANCE.EnumChildWindows(hWnd, new User32.WNDENUMPROC() {
                    public boolean callback(HWND hWnd, Pointer userData) { // this is called for each child window that EnumChildWindows() finds - just like before with EnumWindows().
                        byte[] textBuffer = new byte[512];
                        User32.INSTANCE.GetClassNameA(hWnd, textBuffer, 512);
                        System.out.println(" - Found sub window / control class: " + new String(textBuffer).trim());
                        return true;
                    }
                }, null);
                return true;
            }
        }, null);
    }
}

下面是此code提供的输出的摘录:

Here is an excerpt of output provided by this code:

Window found: Pidgin
 - Found sub window / control class: gdkWindowChild
 - Found sub window / control class: gdkWindowChild
 - Found sub window / control class: gdkWindowChild
 - Found sub window / control class: gdkWindowChild
Window found: Malwarebytes Anti-Malware
 - Found sub window / control class: Static
 - Found sub window / control class: Static
 - Found sub window / control class: Button
 - Found sub window / control class: Button
 - Found sub window / control class: Button

通过直接将消息发送到控件的HWND PostMessage的()的SendMessage(),例如向的Malwarebytes 按钮类,将触发程序本身,到SetForegroundWindow()应该如何把一个编辑框式控制到前面给你非常similarl按钮preSS的能力的类型。有趣的东西一起玩:)

Sending messages directly to the HWND of controls via PostMessage() and SendMessage(), for example to the MalwareBytes Button class, will trigger a button press in the program itself, very similarl to how SetForegroundWindow() should bring an edit-box style control to the front giving you the ability to type. Fun stuff to play with :)

如果您希望可视化我的意思,当我说家长和孩子和控制,你会发现这个程序有帮助的:的控制浏览器。它可以告诉你每一个控制和应用程序窗口中选中它,更多的 - 非常有用的工具。

If you wish to visualize what I mean when I am saying "Parent" and "children" and "control", you may find this program helpful: Control Viewer. It can show you each control and highlight it within an applications window and much more - very useful tool.

很抱歉,如果此帖离开舒适区Java提供的,但真的没有其他的方式来完成这种一般性的范围你的目标。

Sorry if this post left the comfort-zone that java provides, but there's really no other way to accomplish your goal in such a general scope.

我希望我已经至少向你展示什么是必要的实现自己的目标,并指出你在正确的方向。我不是神,当涉及到本地的Windows API的,所以我可能会在一些地方是错误的,然而code不工作。祝你好运:)

I hope I have at least shown you what is necessary to accomplish your goal and pointed you in the right direction. I am no god when it comes to native windows API's, so I may be wrong in some place, however the code does work. Good luck :)

这篇关于Java的搜索屏幕上的文本字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆