gpt4 book ai didi

java - 未收到来自 Java Access Bridge 的回调

转载 作者:可可西里 更新时间:2023-11-01 18:27:00 28 4
gpt4 key购买 nike

我正在尝试使用 Java Access Bridge 从 C++ 应用程序内部获取有关 Swing 组件的信息。但是,我注册的回调都没有被调用过。我尝试枚举窗口,然后在每个句柄上调用 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;
}
}

所有回调都是静态函数。

最佳答案

我也一直在与这个问题作斗争,并且刚刚找到了一个真正有意义的解决方案。我最终不得不构建 WindowsAccessBridge.dll 的调试版本,并使用调试器进入它以观察发生了什么。

  • 调用“initializeAccessBridge”需要您有一个 Activity 的 Windows 消息泵。

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

这很重要,因为在收到此消息之前,桥永远不会正确初始化,因此所有对“IsJavaWindow”的调用都会失败(在内部,一旦收到消息,桥就会初始化一个内部结构——因此,没有 Activity 的消息泵,没有初始化)。我猜这就是为什么您也永远不会收到回调消息的原因。

不仅如此,您还必须在消息泵可以处理消息的位置调用 initializeAccessBridge,然后才能调用 IsJavaWindow。

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

我能够在我的 MFC 对话框应用程序(以及我们基于 MFC 的应用程序)中解决这个问题的方法是确保您在某个点调用“initializeAccessBridge”,以便内置 MFC 消息泵可以推送在使用它之前,将“你好”消息返回到这个隐藏的对话框。在简单的 MFC 对话框情况下,这意味着调用 OnInitDialog 中的 initializeAccessBridge,并调用枚举过程以响应按钮调用(例如)。如果您希望枚举在对话框出现时立即发生,您可以使用计时器在 OnInitDialog 完成后触发(例如 10 毫秒)以允许处理初始化消息。

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

无论如何,我希望这已经足够清楚了!虽然没有办法知道这是否是“正确”的方法(除了花钱请 Sun 工程师告诉我们),但它确实解决了我的问题。

干杯——达伦。

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

关于java - 未收到来自 Java Access Bridge 的回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1161142/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com