Browse Source

Fix Win32 system menu behavior in extended client area and fullscreen

pull/21630/head
Yoyo 4 months ago
parent
commit
cc51afe99e
  1. 7
      src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
  2. 25
      src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs
  3. 6
      src/Windows/Avalonia.Win32/WindowImpl.cs

7
src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs

@ -235,14 +235,14 @@ namespace Avalonia.Win32
break;
case WindowsMessage.WM_SYSCOMMAND:
if ((SysCommands)wParam == SysCommands.SC_KEYMENU &&
if (GetSysCommand(wParam) == SysCommands.SC_KEYMENU &&
ToInt32(lParam) == (int)VirtualKeyStates.VK_SPACE) // Open system menu.
{
break;
}
// Disable system handling of Alt/F10 menu keys.
if ((SysCommands)wParam == SysCommands.SC_KEYMENU && HighWord(ToInt32(lParam)) <= 0)
if (GetSysCommand(wParam) == SysCommands.SC_KEYMENU && HighWord(ToInt32(lParam)) <= 0)
return IntPtr.Zero;
break;
@ -1424,6 +1424,9 @@ namespace Avalonia.Win32
private static int HighWord(int param) => param >> 16;
private static SysCommands GetSysCommand(IntPtr wParam)
=> (SysCommands)(ToInt32(wParam) & 0xfff0);
private Point DipFromLParam(IntPtr lParam)
{
return new Point((short)(ToInt32(lParam) & 0xffff), (short)(ToInt32(lParam) >> 16)) / RenderScaling;

25
src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs

@ -123,7 +123,7 @@ namespace Avalonia.Win32
break;
case WindowsMessage.WM_NCRBUTTONUP
when (HitTestValues)ToInt32(wParam) == HitTestValues.HTCAPTION:
when (HitTestValues)ToInt32(wParam) == HitTestValues.HTCAPTION && IsCaptionHitForSystemMenu(hWnd, lParam):
ShowSystemMenu(PointFromLParam(lParam));
callDwp = false;
return IntPtr.Zero;
@ -301,19 +301,17 @@ namespace Avalonia.Win32
private bool IsCaptionHitForSystemMenu(IntPtr hWnd, IntPtr lParam)
{
if (!_isClientAreaExtended || WindowState == WindowState.FullScreen)
if (!_isClientAreaExtended)
{
return false;
}
if (HitTestNCA(hWnd, IntPtr.Zero, lParam) != HitTestValues.HTCAPTION)
if (HitTestNCA(hWnd, IntPtr.Zero, lParam) is not HitTestValues.HTCAPTION and not HitTestValues.HTNOWHERE)
{
return false;
}
return HitTestVisual(lParam)
is HitTestValues.HTNOWHERE
or HitTestValues.HTCAPTION;
return HitTestVisual(lParam) is HitTestValues.HTCAPTION or HitTestValues.HTNOWHERE;
}
private void ShowSystemMenu(PixelPoint screenPoint)
@ -324,7 +322,7 @@ namespace Avalonia.Win32
return;
}
// SetForegroundWindow(_hwnd);
SetForegroundWindow(_hwnd);
SendMessage(_hwnd, (int)WindowsMessage.WM_INITMENU, menu, IntPtr.Zero);
UpdateSystemMenu(menu);
@ -341,7 +339,14 @@ namespace Avalonia.Win32
if (command != 0)
{
SendMessage(_hwnd, (int)WindowsMessage.WM_SYSCOMMAND, (IntPtr)command, MakeLParam(screenPoint));
if ((SysCommands)command == SysCommands.SC_RESTORE && WindowState == WindowState.FullScreen)
{
WindowState = WindowState.Normal;
}
else
{
SendMessage(_hwnd, (int)WindowsMessage.WM_SYSCOMMAND, (IntPtr)command, MakeLParam(screenPoint));
}
}
}
@ -353,8 +358,8 @@ namespace Avalonia.Win32
var isFullScreen = state == WindowState.FullScreen;
var isNormal = state == WindowState.Normal;
SetSystemMenuItemEnabled(menu, SysCommands.SC_RESTORE, isMinimized || isMaximized);
SetSystemMenuItemEnabled(menu, SysCommands.SC_MOVE, isNormal);
SetSystemMenuItemEnabled(menu, SysCommands.SC_RESTORE, isMinimized || isMaximized || isFullScreen);
SetSystemMenuItemEnabled(menu, SysCommands.SC_MOVE, isNormal || isFullScreen);
SetSystemMenuItemEnabled(menu, SysCommands.SC_SIZE, isNormal && _windowProperties.IsResizable);
SetSystemMenuItemEnabled(menu, SysCommands.SC_MINIMIZE, !isMinimized && !isFullScreen && _windowProperties.IsMinimizable);
SetSystemMenuItemEnabled(menu, SysCommands.SC_MAXIMIZE, !isMaximized && !isFullScreen && _windowProperties.IsMaximizable);

6
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -1102,6 +1102,12 @@ namespace Avalonia.Win32
_savedWindowInfo.Style = current;
_savedWindowInfo.ExStyle = currentEx;
if (current.HasAllFlags(WindowStyles.WS_SYSMENU))
{
// Create the system menu copy before fullscreen removes WS_SYSMENU.
GetSystemMenu(_hwnd, false);
}
// Set new window style and size.
SetStyle(current & ~WindowStyles.WS_OVERLAPPEDWINDOW, false);
SetExtendedStyle(currentEx & ~(WindowStyles.WS_EX_DLGMODALFRAME | WindowStyles.WS_EX_WINDOWEDGE | WindowStyles.WS_EX_CLIENTEDGE | WindowStyles.WS_EX_STATICEDGE), false);

Loading…
Cancel
Save