Search code examples
javawindowsswinguser-interfacejdialog

Hidden JDialog still visible in Windows 10 taskbar peek preview


A JDialog configured with HIDE_ON_CLOSE becomes invisible after closing it. But it is still visible in the peek preview of the Windows taskbar. The preview is corrected only after the main window is minimized and maximized again. Of course one could dispose the dialog instead of hiding it, but that's not what I am aiming for.

  • Is this a Java Swing bug?
  • Is it possible to force a refresh of the taskbar preview?
  • Any other workaround?

Code sample:

    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 );
    }

GIF describing the problem


Solution

  • Please try setting WS_EX_TOOLWINDOW style on the dialog directly before hiding it. Then remove it immediately (so it won't affect rendering on subsequent shows).

    Toolbar windows are not allowed on the Taskbar and thus should not be able to be previewed. It's a hack, but it worked for me for a similar problem in Windows 11.

    Here's code that worked for me on Windows 11. I was able to reproduce the error on Windows 11 with JDK17.

    You need https://github.com/java-native-access/jna (jna.jar and platform.jar). I couldn't find a way to set win32 window styles without it.

    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 );
        }
    }