Swing JFrame 响应本机窗口关闭事件

发布于 2024-09-29 17:26:11 字数 774 浏览 7 评论 0原文

我有一个 Swing 应用程序,其中包含一个设置为 Always On Top 的 JFrame。

在Windows下运行时,我使用以下代码分别打开本机默认电子邮件客户端和浏览器:

Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + Utils.formatMailtoUrl(to, subject, body));
Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url);

因为JFrame设置为Always On Top,而典型的默认浏览器或电子邮件客户端(我们客户的IE和Outlook)未打开正如Always On Top,前者阻碍了后者。

我们当前的“解决方案”是在打开本机窗口的同时最小化 JFrame。但事实证明这是一个 508 合规性问题,我们被要求:

  1. 不要最小化 JFrame。
  2. 浏览器或电子邮件客户端关闭后将焦点返回到 JFrame

我想到的策略是“关闭”JFrame 的 Always On Top 状态,并使用某种回调或事件侦听器来通知 JFrame 该电子邮件或者浏览器窗口已关闭,然后将 JFrame 切换回 Always On Top 状态并设置焦点。

因为这是一个 Java 应用程序,所以我担心这几乎是不可能的,因为我们正在谈论本机互操作。我的策略可行吗?有更好的可行策略吗?最重要的是,如何才能做到?!

提前致谢!

I have a Swing application which consists of a single JFrame set to Always On Top.

When running under Windows, I use the following code to open the the native default email client and browser respectively:

Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + Utils.formatMailtoUrl(to, subject, body));
Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url);

Because the JFrame is set to Always On Top while the typical default browser or email client(IE and Outlook for our customer) does not open as Always On Top, the former obstructs the later.

Our current "solution" is to minimize the JFrame at the same time the native windows are opened. But this turns out to be a 508 compliance issue, and we are being asked to:

  1. Not minimize the JFrame.
  2. Return focus to the JFrame after either the browser or email client are closed

The strategy I have in mind is to "turn off" the Always On Top state of the JFrame and have some kind of callback or event listener which will notify the JFrame that email or browser windows have been closed and then switch the JFrame back to the Always On Top state and set focus.

Because this is a Java app, I am worried this is next to impossible because we are talking about native interop. Is my strategy doable, is there a better doable strategy, and, most importantly, how can it be done?!

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绻影浮沉 2024-10-06 17:26:11

我不确定是否有本地方法可以执行此操作,但您可以运行 tasklist.exe 或 vb 脚本,捕获结果并从那里确定 Outlook 或 IExplore 是否正在运行。这需要您以合理的时间间隔运行检查,而不是等待事件。

Process p = Runtime.getRuntime().exec("tasklist.exe /FO CSV /FI eq outlook.exe");
BufferedReader input = new BufferedReader (new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
    look for a line containing outlook.exe
}
input.close();

您必须分别检查 Outlook.exe 和 iexplorer.exe,因为我认为您无法在这个或那个上过滤任务列表。

我确信这可以推广到查找您原始调用打开的任何内容。

编辑:既然我已经写了所有这些,我突然想到你原来的调用返回一个进程并且可以使用。因此,可以尝试一下,启动一个新线程,在该线程中打开默认电子邮件程序或浏览器,删除“始终在最前面”条件并在返回的进程上调用 waitfor 。调用后,设置“始终位于最前面”条件。该线程将等待进程结束,而不会锁定您的 gui 或其他程序功能。

I am not sure if there is a native way to do this, but you can run tasklist.exe or a vb script, capture the results and from there determine if Outlook or IExplore is running. This would require that you run a check at some reasonable interval instead of waiting on an event.

Process p = Runtime.getRuntime().exec("tasklist.exe /FO CSV /FI eq outlook.exe");
BufferedReader input = new BufferedReader (new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
    look for a line containing outlook.exe
}
input.close();

You will have to check for outlook.exe and iexplorer.exe separately since I don't think you can filter tasklist on this OR that.

I'm sure that this can be generalized to look for whatever is opened by your original call.

Edit: Now that I have written all this, it occurs to me that your original call returns a process and that can be used. So something to try, start a new thread, open the default email program or browser in that thread, remove the "always on top" condition and call waitfor on the process that is returned. After that call, set the "always on top" condition. That thread will wait for the process to end without locking up your gui or other program functions.

鱼忆七猫命九 2024-10-06 17:26:11

我在以下方面取得了一些成功:

  1. 当触发打开浏览器的操作(例如)时,关闭 JFrame Always On Top 设置。
  2. 进行窗口焦点操作,以打开 JFrame Always On Top 设置。
  3. 如果用户没有导航到浏览器之外的任何其他窗口,那么当浏览器关闭时,JFrame 将自动重新获得焦点,从而设置回“Always On Top”

。我认为这种方法有两个缺点。第一个是用户可能在关闭浏览器窗口之前手动返回 JFrame 窗口,导致 JFrame 重新获得焦点并陷入 Always On Top 模式。但这也许是可以接受的。第二个问题是,JAWS 版本 9 屏幕阅读器会变得疯狂,一旦 JFrame 重新获得焦点,就会重新读取最后聚焦的组件至少 3 次。

I am having some success with the following:

  1. When the action for opening the browser (for example) is fired, turn off the JFrame Always On Top setting.
  2. Have a on window focus action which turns on the JFrame Always On Top setting.
  3. If the user does not navigate to any other windows besides the browser, then when the browser closes the JFrame will automatically regain focus and thus be set back to Always On Top

There are two drawbacks I see with this approach. The first is that the user might manually go back to the JFrame window before closing the browser window causing the JFrame to regain focus and get stuck in Always On Top mode. But this might be acceptable. The second issue is that the JAWS version 9 screen reader goes crazy and re-reads the last focused component at least 3 times once the JFrame regains focus.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文