没有从Java Access Bridge接收回调

Jam*_*mes 7 c++ java accessibility java-access-bridge

我正在尝试使用Java Access Bridge从C++应用程序中获取有关Swing组件的信息.但是,我注册的回调都没有被调用.我尝试在每个句柄上调用windows然后调用IsJavaWindow(),但它总是返回false.为什么它显然不起作用的任何想法?

我认为这是我的应用程序而不是桥接安装的问题,因为演示的Monkey和Ferret程序工作,initializeAccessBridge()返回true,调试器显示WindowsAccessBridge dll已加载.

我在Windows Vista上使用Java 6,更新13,我认为访问桥的版本2.0.1.

JavaAccess::JavaAccess(void)
{
   using namespace std;

   BOOL isInitialized = initializeAccessBridge();
   if(isInitialized)
   {
      cout << "Bridge Initialized!" << endl;
   }
   else
   {
      cout << "Initialization failed!" << endl;
      return;
   }

   EnumWindows((WNDENUMPROC)EnumWndProc, NULL);

   SetJavaShutdown(OnJavaShutdown);
   SetFocusGained(OnFocusGained);
   SetMouseClicked(OnMouseClicked);
}

JavaAccess::~JavaAccess(void)
{
   shutdownAccessBridge();
}

void JavaAccess::OnJavaShutdown( long vmID )
{
   using namespace std;
   cout << "Java shutdown!" << endl;
}

void JavaAccess::OnFocusGained( long vmID, FocusEvent event, AccessibleContext context )
{
   using namespace std;
   cout << "Focus Gained!" << endl;

   ReleaseJavaObject(vmID, event);
   ReleaseJavaObject(vmID, context);
}

void JavaAccess::OnMouseClicked( long vmID, jobject event, jobject source )
{
   std::cout << "Mouse clicked!" << std::endl;

   ReleaseJavaObject(vmID, event);
   ReleaseJavaObject(vmID, source);
}

BOOL CALLBACK JavaAccess::EnumWndProc( HWND hwnd, LPARAM lparam )
{
   if (IsJavaWindow(hwnd))
   {
      std::cout << "Found Java Window!" << std::endl;
      return FALSE;
   }
   else
   {
      std::cout << "Still looking" << std::endl;
      return TRUE;
   }
}
Run Code Online (Sandbox Code Playgroud)

所有回调都是静态函数.

Dar*_*ord 11

我也一直在和这个人打架,并且刚刚找到了一个真正有意义的解决方案.我最终不得不构建一个WindowsAccessBridge.dll的调试版本,并使用调试器进入它看看发生了什么.

  • 对'initializeAccessBridge'的调用要求您拥有一个活动的Windows消息泵.

在'initializeAccessBridge'中,它(最终)创建一个隐藏的对话窗口(使用CreateDialog).创建对话框后,它会执行带有注册消息的PostMessage.访问桥的JavaVM端响应此消息,并将另一条消息发回到已创建的对话框(它似乎是您的应用程序和Java VM之间的"hello"类型握手).因此,如果您的应用程序没有活动消息泵,则应用程序永远不会收到来自JavaVM的返回消息.

这很重要,因为在收到此消息之前,桥接器从未正确初始化,因此对"IsJavaWindow"的所有调用都会失败(在内部,桥接器在收到消息后初始化内部结构 - 因此,没有活动消息泵,没有初始化).我猜这就是你永远不会收到回调消息的原因.

不仅如此,您必须在消息泵可以处理消息之前调用initializeAccessBridge,然后才能调用IsJavaWindow.

这就是JavaFerret和JavaMonkey工作的原因 - 它们在启动时初始化,然后在桥接器通过消息泵收到初始化消息之后枚举响应菜单消息.

我能够在我的MFC对话框应用程序(以及我们基于MFC的应用程序)中解决此问题的方法是确保在某个点上调用'initializeAccessBridge',以便内置的MFC消息泵可以推送'hello'在使用它之前回复此隐藏对话框的消息.在简单的MFC对话框中,它意味着在OnInitDialog中调用initializeAccessBridge,并调用枚举过程以响应按钮调用(例如).如果希望在对话框出现后立即发生枚举,则可以在OnInitDialog完成后使用计时器触发(例如10ms)以允许处理初始化消息.

如果您计划在控制台应用程序中使用它,则需要编写自己的自定义消息泵来处理初始化消息.

无论如何,我希望这很清楚!虽然没有办法知道这是否是"正确的"方式(除了支付太阳工程师告诉我们的费用),它肯定解决了我的问题.

干杯 - 达伦.

哦.顺便说一下,我发现了一个不起眼的Sun页面,其中提到了一些只适用于基于awt的java应用程序的AccessBridge(但鉴于Sun自2004年以来没有更新任何文档,这可能已经改变).我不是一个java程序员 - 为了测试我抓了一些免费的Java应用程序(以及jdk附带的那些)并试用了我的测试应用程序.它适用于我尝试的所有 - YMMV.祝好运!