画面上のテキストフィールドを自動的に検索し、そのテキストフィールドに単語を繰り返し入力するプログラムを作成しようとしています。テキストフィールドを見つけることができるクラスはありますか?または、テキストフィールドを見つける方法はありますか?Robotクラスでテキストを入力できることがわかっているので、カーソルをテキストフィールドに移動して、mousePress()メソッドとmouseRelease()メソッドを使用する必要があります。
ありがとう
直接解決策を提供することはできませんが、いくつかのコードをいじって、正しい方向に向けることができるかもしれません.
おそらくご存じのとおり、Java は JVM で実行されます。これにより、あらゆる動作環境で実行できます。各オペレーティング環境 (Windows、Mac など) には、編集ボックスを処理し、適切なウィンドウなどにフォーカスを設定するための独自のシステムがあります。次のコード例は、Windows でのみ使用するように設計されており、Java 言語の精神に従っていません。Adriaan が指摘したように、この種の言語は他にもありますが、Java だけで (ある程度) 達成することは可能です。
Windows では、すべてのアクティブなウィンドウがどのように管理されているか、および表示されるすべて (編集ボックスを含む) が Windows OS によって「ウィンドウ」と見なされていることを理解する必要があります。内部の仕組みがよくわからないので、それ以上の情報を提供することはできません。C++ などのネイティブ言語では、目的を達成するために使用される Windows OS API によって提供される関数がいくつかあります。すなわち、EnumWindows()
、EnumChildWindows()
、GetClassName()
、およびSetForegroundWindow()
。MSDN ドキュメント ライブラリを検索すると、ネイティブ言語でこれらの関数を使用する方法に関するドキュメントを見つけることができます。
そうは言っても、これらの関数を Java から呼び出せるようにする必要があります。通常の状況では、これらのネイティブ メソッドを呼び出すことはできません。しかし、あなたを助けるために利用できるライブラリがあります: JNA ライブラリです。JNA は Java Native Access の略で、前述の輝かしい新機能を使用できます。
したがって、ネイティブ言語で目標を達成するには、通常EnumWindows()
、OS が認識しているすべての親ウィンドウのリストを返すために を呼び出すことから始めます。このリストには、親ウィンドウ (「MSN」、「Eclipse」、「Microsoft Office」などのタイトルのウィンドウ) のウィンドウ ハンドルが含まれます。これらの各ウィンドウには、親として子があります。探している「コントロール」が見つかるのは、この子のリストです。Edit
コントロール。現在、多くのアプリケーションがテキスト ボックスにさまざまなライブラリや非標準のものを使用しています。つまり、関連するコードをテストしたメッセージング アプリケーションである Pidgin には、「gdkWindowChild」という名前のすべてのコントロールがあり、どのコントロールが実際に EditBox であるか、またはどのコントロールであるかが正確にはわかりません。それ以外の場合は、テキストを入力できる場所です。それがあなたのアイデアの主な問題です。テキストを入力できるようにするために、どのコントロールにフォーカスしたいのかを常に正確に伝えることはできません。それにもかかわらず、私たちは続けます:
関連する親ウィンドウを で見つけた後EnumWindows()
、 を呼び出すとEnumChildWindows()
、親に属するすべてのサブウィンドウとその他の「コントロール」(潜在的な編集ボックスを含む) が得られます。EnumChildWindows()
見つかったサブウィンドウごとにコールバック関数を呼び出すため、子ウィンドウのリストを "検索" してGetClassName()
コントロールの名前を見つけるのは非常に簡単で、必要なコントロールの HWND (ウィンドウ ハンドル) を見つけることができます。 .
編集ボックスの正しい HWND を見つけたら (もちろん、質問の一般的な範囲を考えると難しい部分です)、単純な呼び出しSetForegroundWindow(targetHWND)
でコントロールを前面に移動し、カーソルを準備完了に設定する必要があります-タイプの編集ボックス。
ここに、作業を開始するために私が書いた実用的なコード例をいくつか示します。このコードは、使用中のすべてのウィンドウを繰り返し処理し、各親EnumWindows()
を呼び出しEnumChildWindows()
て、見つかったすべてのコントロールを出力します。このコードを実行するには JNA ライブラリが必要であることに注意してください。
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);
}
}
このコードによって提供される出力の抜粋を次に示します。
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()
、たとえば MalwareBytesButton
クラスに、プログラム自体でボタンの押下がトリガーされます。入力し。で遊ぶ楽しいもの:)
私が「親」、「子」、「コントロール」と言っている意味を視覚化したい場合は、次のプログラムが役立つかもしれません: Control Viewer。各コントロールを表示し、アプリケーション ウィンドウ内で強調表示することができます。非常に便利なツールです。
この投稿が Java が提供するコンフォート ゾーンを離れてしまった場合は申し訳ありませんが、このような一般的な範囲で目標を達成する方法は他にありません。
少なくとも、目標を達成するために何が必要かを示し、正しい方向に向けられたことを願っています。ネイティブ Windows API に関しては私は神ではないので、どこかで間違っているかもしれませんが、コードは機能します。幸運を :)
友よ、Robot クラスはテキストの書き込みをシミュレートできます。
private static void typeOut(String s,Robot bot)
{
try
{
char [] chars = s.toCharArray();
for (char c : chars)
{
bot.keyPress((int)c);
bot.keyRelease((int)c);
}
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
この方法は次の方法で使用できます。
Robot bot=new Robot();
typeOut("WWW.GOOGLE.COM", bot);
何らかの方法で、ブラウザのテキストフィールドにテキストを読み込んだり、テキストを書き込んだりしたい場合は、セレンを使用することをお勧めします。
このタイプの問題では、 AutoItは Java よりも簡単で用途が広いです。