From baf4437efcc130c85c12538d54d6243a59e81ed6 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Tue, 23 Feb 2021 01:10:59 +0100 Subject: [PATCH] Native window decorations: show window system menu when right-clicking on caption --- .../FlatWindowsNativeWindowBorder.java | 93 ++++++++++++++++++- 1 file changed, 90 insertions(+), 3 deletions(-) diff --git a/flatlaf-native-jna/src/main/java/com/formdev/flatlaf/nativejna/windows/FlatWindowsNativeWindowBorder.java b/flatlaf-native-jna/src/main/java/com/formdev/flatlaf/nativejna/windows/FlatWindowsNativeWindowBorder.java index 4202064d..8612079f 100644 --- a/flatlaf-native-jna/src/main/java/com/formdev/flatlaf/nativejna/windows/FlatWindowsNativeWindowBorder.java +++ b/flatlaf-native-jna/src/main/java/com/formdev/flatlaf/nativejna/windows/FlatWindowsNativeWindowBorder.java @@ -38,8 +38,11 @@ import com.sun.jna.Pointer; import com.sun.jna.Structure; import com.sun.jna.Structure.FieldOrder; import com.sun.jna.platform.win32.BaseTSD; +import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR; import com.sun.jna.platform.win32.Shell32; import com.sun.jna.platform.win32.User32; +import com.sun.jna.platform.win32.WTypes.LPWSTR; +import com.sun.jna.platform.win32.WinDef.HMENU; import com.sun.jna.platform.win32.WinDef.HWND; import com.sun.jna.platform.win32.WinDef.LPARAM; import com.sun.jna.platform.win32.WinDef.LRESULT; @@ -163,6 +166,7 @@ public class FlatWindowsNativeWindowBorder private static final int WM_NCCALCSIZE = 0x0083; private static final int WM_NCHITTEST = 0x0084; + private static final int WM_NCRBUTTONUP = 0x00A5; // WM_NCHITTEST mouse position codes private static final int @@ -173,6 +177,21 @@ public class FlatWindowsNativeWindowBorder private static final int ABS_AUTOHIDE = 0x0000001; private static final int ABM_GETAUTOHIDEBAREX = 0x0000000b; + private static final int + SC_SIZE = 0xF000, + SC_MOVE = 0xF010, + SC_MINIMIZE = 0xF020, + SC_MAXIMIZE = 0xF030, + SC_CLOSE = 0xF060, + SC_RESTORE = 0xF120; + + private static final int + MIIM_STATE = 0x00000001, + MFT_STRING = 0x00000000, + MF_ENABLED = 0x00000000, + MF_DISABLED = 0x00000002, + TPM_RETURNCMD = 0x0100; + private Window window; private final HWND hwnd; private final BaseTSD.LONG_PTR defaultWndProc; @@ -222,12 +241,16 @@ public class FlatWindowsNativeWindowBorder case WM_NCHITTEST: return WmNcHitTest( hwnd, uMsg, wParam, lParam ); + case WM_NCRBUTTONUP: + if( wParam.longValue() == HTCAPTION ) + openSystemMenu( hwnd, GET_X_LPARAM( lParam ), GET_Y_LPARAM( lParam ) ); + break; + case WM_DESTROY: return WmDestroy( hwnd, uMsg, wParam, lParam ); - - default: - return User32Ex.INSTANCE.CallWindowProc( defaultWndProc, hwnd, uMsg, wParam, lParam ); } + + return User32Ex.INSTANCE.CallWindowProc( defaultWndProc, hwnd, uMsg, wParam, lParam ); } /** @@ -442,6 +465,44 @@ public class FlatWindowsNativeWindowBorder private int GET_Y_LPARAM( LPARAM lParam ) { return (short) ((lParam.longValue() >> 16) & 0xffff); } + + /** + * Opens the window's system menu. + * The system menu is the menu that opens when the user presses Alt+Space or + * right clicks on the title bar + */ + private void openSystemMenu( HWND hwnd, int x, int y ) { + // get system menu + HMENU systemMenu = User32Ex.INSTANCE.GetSystemMenu( hwnd, false ); + + // update system menu + boolean isMaximized = User32Ex.INSTANCE.IsZoomed( hwnd ); + setMenuItemState( systemMenu, SC_RESTORE, isMaximized ); + setMenuItemState( systemMenu, SC_MOVE, !isMaximized ); + setMenuItemState( systemMenu, SC_SIZE, !isMaximized ); + setMenuItemState( systemMenu, SC_MINIMIZE, true ); + setMenuItemState( systemMenu, SC_MAXIMIZE, !isMaximized ); + setMenuItemState( systemMenu, SC_CLOSE, true ); + + // make "Close" item the default to be consistent with the system menu shown + // when pressing Alt+Space + User32Ex.INSTANCE.SetMenuDefaultItem( systemMenu, SC_CLOSE, 0 ); + + // show system menu + int ret = User32Ex.INSTANCE.TrackPopupMenu( systemMenu, TPM_RETURNCMD, + x, y, 0, hwnd, null ).intValue(); + if( ret != 0 ) + User32Ex.INSTANCE.PostMessage( hwnd, WM_SYSCOMMAND, new WPARAM( ret ), null ); + } + + private void setMenuItemState( HMENU systemMenu, int item, boolean enabled ) { + MENUITEMINFO mii = new MENUITEMINFO(); + mii.cbSize = new UINT( mii.size() ); + mii.fMask = new UINT( MIIM_STATE ); + mii.fType = new UINT( MFT_STRING ); + mii.fState = new UINT( enabled ? MF_ENABLED : MF_DISABLED ); + User32Ex.INSTANCE.SetMenuItemInfo( systemMenu, item, false, mii ); + } } //---- interface User32Ex ------------------------------------------------- @@ -460,6 +521,11 @@ public class FlatWindowsNativeWindowBorder boolean IsZoomed( HWND hWnd ); HANDLE GetProp( HWND hWnd, String lpString ); + + HMENU GetSystemMenu( HWND hWnd, boolean bRevert ); + boolean SetMenuItemInfo( HMENU hmenu, int item, boolean fByPositon, MENUITEMINFO lpmii ); + boolean SetMenuDefaultItem( HMENU hMenu, int uItem, int fByPos ); + BOOL TrackPopupMenu( HMENU hMenu, int uFlags, int x, int y, int nReserved, HWND hWnd, RECT prcRect ); } //---- class NCCALCSIZE_PARAMS -------------------------------------------- @@ -477,4 +543,25 @@ public class FlatWindowsNativeWindowBorder read(); } } + + //---- class MENUITEMINFO ------------------------------------------------- + + @FieldOrder( { "cbSize", "fMask", "fType", "fState", "wID", "hSubMenu", + "hbmpChecked", "hbmpUnchecked", "dwItemData", "dwTypeData", "cch", "hbmpItem" } ) + public static class MENUITEMINFO + extends Structure + { + public UINT cbSize; + public UINT fMask; + public UINT fType; + public UINT fState; + public UINT wID; + public HMENU hSubMenu; + public HBITMAP hbmpChecked; + public HBITMAP hbmpUnchecked; + public ULONG_PTR dwItemData; + public LPWSTR dwTypeData; + public UINT cch; + public HBITMAP hbmpItem; + } }