【问题标题】:Hidden JDialog still visible in Windows 10 taskbar peek preview隐藏的 JDialog 在 Windows 10 任务栏预览中仍然可见
【发布时间】:2021-02-11 17:12:37
【问题描述】:

使用HIDE_ON_CLOSE 配置的JDialog 在关闭后变得不可见。但它在 Windows 任务栏的预览预览中仍然可见。只有在主窗口被最小化和再次最大化后,预览才会被纠正。当然可以处理对话框而不是隐藏它,但这不是我的目标。

  • 这是 Java Swing 错误吗?
  • 是否可以强制刷新任务栏预览?
  • 还有其他解决方法吗?

代码示例:

    public static void main( String[] args ) throws Exception {
        JFrame frame = new JFrame();
        frame.setTitle( "frame" );
        frame.setSize( 700, 700 );
        frame.setVisible( true );
        frame.setDefaultCloseOperation( JDialog.EXIT_ON_CLOSE );
    
        JDialog d = new JDialog( frame ); // modeless dialog
        d.setTitle( "dialog" );
        d.setSize( 300, 300 );
        d.setDefaultCloseOperation( JDialog.HIDE_ON_CLOSE );
        d.setVisible( true );
    }

【问题讨论】:

  • 无法重现相同的行为(JDK1.8),不显示JDialog。
  • 我可以重现这种行为(Oracle JDK 15)。关闭后预览时显示 JDialog。我使用invokeLater() 测试了代码以在 EDT 上运行,但行为相同。
  • @Abra 这不是一个可行的解决方法。最小化和最大化主窗口对用户来说非常明显。
  • 我应该提到我正在使用 OpenJDK 11 (LTS)。

标签: java windows swing user-interface jdialog


【解决方案1】:

请在隐藏之前尝试直接在对话框上设置 WS_EX_TOOLWINDOW 样式。然后立即将其移除(这样不会影响后续节目的渲染)。

任务栏上不允许使用工具栏窗口,因此不能预览。这是一个 hack,但它适用于 Windows 11 中的类似问题。

这是在 Windows 11 上为我工作的代码。我能够使用 JDK17 在 Windows 11 上重现该错误。

你需要https://github.com/java-native-access/jnajna.jarplatform.jar)。如果没有它,我找不到设置 win32 窗口样式的方法。

javac -cp .;./jna.jar;./platform.jar jdtest.java

import javax.swing.JFrame;
import javax.swing.JDialog;
import java.awt.event.*;

import com.sun.jna.Native;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinUser;
public class jdtest
{
    
    public static int WS_EX_TOOLWINDOW = 0x00000080;
    public static void changeStyle(HWND hwnd, boolean hiding) {
        int exStyle = User32.INSTANCE.GetWindowLong(hwnd, WinUser.GWL_EXSTYLE);
        if (hiding) {
            User32.INSTANCE.SetWindowLong(hwnd, WinUser.GWL_EXSTYLE, exStyle | WS_EX_TOOLWINDOW);
        } else {
            User32.INSTANCE.SetWindowLong(hwnd, WinUser.GWL_EXSTYLE, exStyle & ~WS_EX_TOOLWINDOW);
        }
    }
    
    private static HWND getHWnd(JDialog d) {
        HWND hwnd = new HWND();
        hwnd.setPointer(Native.getWindowPointer(d));
        return hwnd;
    }

    public static void main( String[] args ) throws Exception {
        JFrame frame = new JFrame();
        frame.setTitle( "frame" );
        frame.setSize( 700, 700 );
        frame.setVisible( true );
        frame.setDefaultCloseOperation( JDialog.EXIT_ON_CLOSE );

        JDialog d = new JDialog( frame ); // modeless dialog
        d.setTitle( "dialog" );
        d.setSize( 300, 300 );
        d.setDefaultCloseOperation( JDialog.HIDE_ON_CLOSE );

        d.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                changeStyle(getHWnd(d), true);
            }
        });
        d.addWindowListener(new WindowAdapter() {
            public void windowOpening(WindowEvent e) {
                changeStyle(getHWnd(d), false);
            }
        });

        d.setVisible( true );
    }
}

【讨论】:

  • 您能否提供一个代码示例,说明如何在 Java Swing 中执行此操作?
  • @StefanS 我现在添加了工作代码。
  • 在带有 JDK11 的 Win10 上工作。感谢@Dan 花时间在这上面。非常感谢!我希望我们将来能找到一个非hacky的解决方案。在那之前,我接受这个答案。
  • 太好了。我之前没有看到过Win10的bug,所以我想知道JDK11是什么导致了这个问题。也许JDK11并没有真正将窗口设置为不可见......
  • @StefanS,回复:Win11,这肯定是一个错误。我可以在其他工具链中重现,包括 MFC,在 Win10 中运行良好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-09
  • 2013-10-26
  • 1970-01-01
  • 1970-01-01
  • 2011-12-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多