3

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

Dr Mido
  • 2,414
  • 4
  • 32
  • 72
Stefan S
  • 33
  • 3
  • Does this help? https://stackoverflow.com/questions/3965336/how-to-minimize-a-jframe-window-from-java – Abra Feb 11 '21 at 17:31
  • unable to reproduce the same behaviour (JDK1.8), JDialog is not shown. – RealHowTo Feb 11 '21 at 18:14
  • I can reproduce this behavior (Oracle JDK 15). JDialog is shown when previewing after close. I tested the code with the `invokeLater()` to run on EDT but same behavior. – Peter Alsen Feb 11 '21 at 19:44
  • @Abra that is not a feasible workaround. Minimizing and maximizing the main window is very noticeable to the user. – Stefan S Feb 12 '21 at 07:38
  • I should mention that I am using OpenJDK 11 (LTS). – Stefan S Feb 12 '21 at 07:39

1 Answers1

1

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 );
    }
}
Dan
  • 1,823
  • 16
  • 18
  • Can you provide a code example on how to do this in Java Swing? – Stefan S Feb 22 '22 at 12:11
  • 1
    @StefanS I added working code now. – Dan Feb 22 '22 at 19:01
  • Works on Win10 with JDK11. Thank you @Dan for spending time on this. Very much appreciated! I hope we can find a non-hacky solution in the future. Until then, I accept this answer. – Stefan S Feb 23 '22 at 13:26
  • That's great. I have not seen a bug with Win10 before, so I wonder what about JDK11 caused the problem. Perhaps JDK11 isn't really setting the window invisible... – Dan Feb 23 '22 at 19:32
  • @StefanS, re: Win11, it's surely a bug. I can reproduce in other toolchains, including MFC, that worked fine in Win10. – Dan Feb 24 '22 at 02:04