Prevent window from snapping to screen edges
There's no direct way of doing this except you set ResizeMode="NoResize"
and implement the resize behavior manually or EXTREME SOLUTION could be (on an application basis) modifying a shortcut to your .exe, on the Compatibility tab, check "Disable desktop composition".
Is this the only way to teach a Java Frame something about the Aero Snap feature of Windows?
Is there a better way to let AeroSnap and Java Frames work together?
Not much better. Directly setting the extended state bypasses the OS's treatment of setting it.
If you take a look at the source code of JFrame#setExtendedState
you will see that it calls the FramePeer
's setState
method. The JDK's JFrame
implementation of the FramePeer
interface is the WFramePeer
class, which declares its setState
method as native
. So, you're out of luck until Oracle does something about it or you use native code (see below).
Fortunately, you don't necessarily have to go nuts with event listeners and caching bounds. Hiding and showing the frame is enough to "reset" the size to what it was before the minimization:
public class AeroResize extends JFrame {
public AeroResize(final String title) {
super(title);
initUI();
}
private void initUI() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new FlowLayout());
final JButton minimize = new JButton("Minimize");
final JButton maximize = new JButton("Maximize");
final JButton normal = new JButton("Normal");
add(normal);
add(minimize);
add(maximize);
pack();
minimize.addActionListener(e -> {
setVisible(false);
setExtendedState(getExtendedState() | JFrame.ICONIFIED);
setVisible(true);
// setLocation(getLocationOnScreen()); // Needed only for the preview. See comments section below.
});
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> new AeroResize("AeroSnap and the Frame State").setVisible(true));
}
}
Though this does have a side-effect of not giving a detailed preview of the frame's contents:
Solution using native code
If you'd care to use JNA, then you can completely mimic the native platform's minimization. You'll need to include jna.jar
and jna-platform.jar
in your build path.
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HWND;
public class AeroResize extends JFrame {
public AeroResize(final String title) {
super(title);
initUI();
}
private void initUI() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new FlowLayout());
final JButton minimize = new JButton("Minimize");
final JButton maximize = new JButton("Maximize");
final JButton normal = new JButton("Normal");
add(normal);
add(minimize);
add(maximize);
pack();
minimize.addActionListener(e -> {
HWND windowHandle = new HWND(Native.getComponentPointer(AeroResize.this));
User32.INSTANCE.CloseWindow(windowHandle);
});
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> new AeroResize("AeroSnap and the Frame State").setVisible(true));
}
}
It's pretty self explanatory. You get a pointer to the window and use the native CloseWindow
(which actually minimizes, go figure) on it. Note that the minimalistic way I wrote it will cause a small delay the first time the button is pressed because the User32
instance is loaded. You can load it on startup to avoid this first-time delay.
Credit goes to the accepted answer here.
Related Topics
Custom Sort Logic in Orderby Using Linq
Can't See Localhost from Uwp App
Httpwebrequest Times Out on Second Call
MVC 5 Dynamic Rows with Begincollectionitem
Multiple Fields Validation Using Remote Validation
What's the Best Way to Compare Double and Int
Extension Method on Enumeration, Not Instance of Enumeration
Accuracy of Textrenderer.Measuretext Results
Should Idisposable.Dispose() Be Made Safe to Call Multiple Times
Create Http Post Request and Receive Response Using C# Console Application
Reverse Sorted Dictionary in .Net