我正在尝试使用java辅助功能实用程序与一个java swing应用程序交互。java可访问性指南指出
要使辅助技术与Java应用程序一起工作,将其加载到与其提供访问的Java应用程序相同的JVM中。这是通过使用assistive_technologies属性完成的。
和
Monkey类位于此版本的Java辅助工具附带的示例/Monkey目录中。在运行它之前,需要按照以下说明适当地设置您的环境: 将jaccess.jar和jaccess-examples.jar复制到JDKHOME/jre/lib/ext目录下的JDK1.2或更高版本的安装中。修改$JDKHOME/jre/lib/create sibility.properties文件(如果不存在的话创建一个),以包含以下行: assistive_technologies=Monkey 按照上面的说明,任何时候启动Java应用程序时都会自动启动Monkey。例如,您可以运行作为Swing演示应用程序的一部分的SwingSet演示。
我已经将jaccess-examples.jar复制到我的jre文件夹(C:\ProgramFiles\Java\jre1.8.0_221\lib\ext)中,jaccess.jar已经在那里,添加到了(C:\ProgramFiles\Java\jre1.8.0_221\lib)行assistive_technologies=Monkey中的accessibility.properties文件中,但是在启动launching应用程序时什么也不会发生。我怎么才能让它起作用?
要注意的是,如果Monkey在与它需要访问的应用程序相同的JVM中启动,即使不修改accessibility.properties文件,它实际上也能工作。
发布于 2021-11-14 18:52:16
//load WindowsAccessBridge-64.dll
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.ptr.PointerByReference;
public interface WindowsAccessBridge extends Library {
//Load the .dll using JNA
WindowsAccessBridge INSTANCE = Native.load("windowsaccessbridge-64", WindowsAccessBridge.class);
//declare some functions from the .dll
void Windows_run();
boolean isJavaWindow(WinDef.HWND window);
boolean getAccessibleContextFromHWND(WinDef.HWND target, WinDef.LONGByReference vmID, PointerByReference accessibleContext);
boolean getAccessibleContextInfo(WinDef.LONG vmID, Pointer accessibleContext, ABPackages.AccessibleContextInfo.ByReference info);
}
//load custom user32.dll, the user32 provided by JNA does not have the ChangeWindowMessageFilter function
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinUser.WNDENUMPROC;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.platform.win32.WinDef.HWND;
public interface UUser32 extends StdCallLibrary {
UUser32 INSTANCE = Native.load("user32", UUser32.class);
boolean ChangeWindowMessageFilter(int message, int flag);
}
//to get window messages you need a message pump
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinUser;
import static com.sun.jna.platform.win32.WinUser.WM_COPYDATA;
import static com.sun.jna.platform.win32.WinUser.WM_USER;
public class WindowMessagePump extends Thread {
//get a WAB instance
private final WindowsAccessBridge wab = WindowsAccessBridge.INSTANCE;
//get a custom user32 instance
private final UUser32 uUser32 = UUser32.INSTANCE;
// the user32 provided by JNA
private final User32 user32 = User32.INSTANCE;
@Override
public void run() {
uUser32.ChangeWindowMessageFilter(WM_COPYDATA, 1);
for (int i = WM_USER + 1; i < 0xfff; i++) {
uUser32.ChangeWindowMessageFilter(i, 1);
}
wab.Windows_run();
WinUser.MSG msg = new WinUser.MSG();
while (user32.GetMessage(msg, null, 0, 0) > 0) {
user32.TranslateMessage(msg);
user32.DispatchMessage(msg);
}
}
}
//you also need some structures to get the needed information
import com.sun.jna.Structure;
public class ABPackages {
static final int MAX_STRING_SIZE = 1024;
static final int SHORT_STRING_SIZE = 256;
@Structure.FieldOrder({"name", "description", "role", "role_en_US", "states", "states_en_US", "indexInParent",
"childrenCount", "x", "y", "width", "height", "accessibleComponent", "accessibleAction",
"accessibleSelection", "accessibleText", "accessibleInterfaces"})
public static class AccessibleContextInfo extends Structure {
public char[] name = new char[MAX_STRING_SIZE]; // the AccessibleName of the object
public char[] description = new char[MAX_STRING_SIZE]; // the AccessibleDescription of the object
public char[] role = new char[SHORT_STRING_SIZE]; // localized AccesibleRole string
public char[] role_en_US = new char[SHORT_STRING_SIZE];
public char[] states = new char[SHORT_STRING_SIZE]; // localized AccesibleStateSet string (comma separated)
public char[] states_en_US = new char[SHORT_STRING_SIZE];
public int indexInParent; // index of object in parent
public int childrenCount; // # of children, if any
public int x; // screen x-axis co-ordinate in pixels
public int y; // screen y-axis co-ordinate in pixels
public int width; // pixel width of object
public int height; // pixel height of object
public int accessibleComponent; // flags for various additional
public int accessibleAction; // Java Accessibility interfaces
public int accessibleSelection; // FALSE if this object doesn't
public int accessibleText; // implement the additional interface
public int accessibleInterfaces; // new bitfield containing additional interface flags
public static class ByReference extends AccessibleContextInfo implements Structure.ByReference {
}
public static class ByValue extends AccessibleContextInfo implements Structure.ByValue {
}
}
}
//and now for the implementation
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.DesktopWindow;
import com.sun.jna.platform.WindowUtils;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.ptr.PointerByReference;
public static void main(String[] args) throws InterruptedException {
//start the message pump
WindowMessagePump messagePump = new WindowMessagePump();
messagePump.setDaemon(true);
messagePump.start();
//wait a few seconds for the pump to start just in case
Thread.sleep(2000);
//get an instance of windows access bridge
WindowsAccessBridge accessBridge = WindowsAccessBridge.INSTANCE;
//get a list of active windows
List<DesktopWindow> list = WindowUtils.getAllWindows(true);
for (DesktopWindow window : list) {
if (window.getFilePath().contains("the name of the window you are looking for")) {
WinDef.HWND handle = window.getHWND();
//check if its a java window
if (accessBridge.isJavaWindow(handle)) {
WinDef.LONGByReference vmID = new WinDef.LONGByReference();
PointerByReference accessibleContext = new PointerByReference();
boolean getAccessibleContextSuccess = accessBridge.getAccessibleContextFromHWND(handle, vmID, accessibleContext);
if(getAccessibleContextSuccess) {
ABPackages.AccessibleContextInfo.ByReference contextInfo = new ABPackages.AccessibleContextInfo.ByReference();
boolean getContextInfoSuccess = accessBridge.getAccessibleContextInfo(vmID.getValue(), accessibleContext.getValue(), contextInfo);
System.out.println("getContextInfoSuccess: " + getContextInfoSuccess);
}
break;
}
}
}
}https://stackoverflow.com/questions/68194608
复制相似问题