Improve Window controls

This commit is contained in:
Raphire
2026-04-04 14:43:15 +02:00
parent fbdc5740db
commit d372b00072
2 changed files with 83 additions and 24 deletions

View File

@@ -529,18 +529,17 @@
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="32"/> <RowDefinition Height="32"/>
<RowDefinition Height="*"/> <RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- Resize Borders --> <!-- Resize Borders -->
<Rectangle x:Name="ResizeLeft" Width="5" HorizontalAlignment="Left" Fill="Transparent" Cursor="SizeWE" Grid.Row="0" Grid.RowSpan="3" Panel.ZIndex="100" Visibility="Collapsed" IsHitTestVisible="False"/> <Rectangle x:Name="ResizeLeft" Width="5" HorizontalAlignment="Left" Fill="Transparent" Cursor="SizeWE" Grid.Row="0" Grid.RowSpan="2" Panel.ZIndex="100" Visibility="Collapsed" IsHitTestVisible="False"/>
<Rectangle x:Name="ResizeRight" Width="5" HorizontalAlignment="Right" Fill="Transparent" Cursor="SizeWE" Grid.Row="0" Grid.RowSpan="3" Panel.ZIndex="100" Visibility="Collapsed" IsHitTestVisible="False"/> <Rectangle x:Name="ResizeRight" Width="5" HorizontalAlignment="Right" Fill="Transparent" Cursor="SizeWE" Grid.Row="0" Grid.RowSpan="2" Panel.ZIndex="100" Visibility="Collapsed" IsHitTestVisible="False"/>
<Rectangle x:Name="ResizeTop" Height="5" VerticalAlignment="Top" Fill="Transparent" Cursor="SizeNS" Grid.Row="0" Panel.ZIndex="100" Visibility="Collapsed" IsHitTestVisible="False"/> <Rectangle x:Name="ResizeTop" Height="5" VerticalAlignment="Top" Fill="Transparent" Cursor="SizeNS" Grid.Row="0" Panel.ZIndex="100" Visibility="Collapsed" IsHitTestVisible="False"/>
<Rectangle x:Name="ResizeBottom" Height="5" VerticalAlignment="Bottom" Fill="Transparent" Cursor="SizeNS" Grid.Row="2" Panel.ZIndex="100" Visibility="Collapsed" IsHitTestVisible="False"/> <Rectangle x:Name="ResizeBottom" Height="5" VerticalAlignment="Bottom" Fill="Transparent" Cursor="SizeNS" Grid.Row="1" Panel.ZIndex="100" Visibility="Collapsed" IsHitTestVisible="False"/>
<Rectangle x:Name="ResizeTopLeft" Width="8" Height="8" HorizontalAlignment="Left" VerticalAlignment="Top" Fill="Transparent" Cursor="SizeNWSE" Grid.Row="0" Panel.ZIndex="101" Visibility="Collapsed" IsHitTestVisible="False"/> <Rectangle x:Name="ResizeTopLeft" Width="8" Height="8" HorizontalAlignment="Left" VerticalAlignment="Top" Fill="Transparent" Cursor="SizeNWSE" Grid.Row="0" Panel.ZIndex="101" Visibility="Collapsed" IsHitTestVisible="False"/>
<Rectangle x:Name="ResizeTopRight" Width="8" Height="8" HorizontalAlignment="Right" VerticalAlignment="Top" Fill="Transparent" Cursor="SizeNESW" Grid.Row="0" Panel.ZIndex="101" Visibility="Collapsed" IsHitTestVisible="False"/> <Rectangle x:Name="ResizeTopRight" Width="8" Height="8" HorizontalAlignment="Right" VerticalAlignment="Top" Fill="Transparent" Cursor="SizeNESW" Grid.Row="0" Panel.ZIndex="101" Visibility="Collapsed" IsHitTestVisible="False"/>
<Rectangle x:Name="ResizeBottomLeft" Width="8" Height="8" HorizontalAlignment="Left" VerticalAlignment="Bottom" Fill="Transparent" Cursor="SizeNESW" Grid.Row="2" Panel.ZIndex="101" Visibility="Collapsed" IsHitTestVisible="False"/> <Rectangle x:Name="ResizeBottomLeft" Width="8" Height="8" HorizontalAlignment="Left" VerticalAlignment="Bottom" Fill="Transparent" Cursor="SizeNESW" Grid.Row="1" Panel.ZIndex="101" Visibility="Collapsed" IsHitTestVisible="False"/>
<Rectangle x:Name="ResizeBottomRight" Width="8" Height="8" HorizontalAlignment="Right" VerticalAlignment="Bottom" Fill="Transparent" Cursor="SizeNWSE" Grid.Row="2" Panel.ZIndex="101" Visibility="Collapsed" IsHitTestVisible="False"/> <Rectangle x:Name="ResizeBottomRight" Width="8" Height="8" HorizontalAlignment="Right" VerticalAlignment="Bottom" Fill="Transparent" Cursor="SizeNWSE" Grid.Row="1" Panel.ZIndex="101" Visibility="Collapsed" IsHitTestVisible="False"/>
<!-- Custom Title Bar --> <!-- Custom Title Bar -->
<Grid Grid.Row="0" x:Name="TitleBar"> <Grid Grid.Row="0" x:Name="TitleBar">
@@ -614,7 +613,13 @@
</Grid> </Grid>
<!-- Main Content with Tabs --> <!-- Main Content with Tabs -->
<TabControl Grid.Row="1" Background="Transparent" BorderThickness="0" Margin="0" Padding="0" Name="MainTabControl"> <Grid Grid.Row="1" x:Name="ContentGrid">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TabControl Grid.Row="0" Background="Transparent" BorderThickness="0" Margin="0" Padding="0" Name="MainTabControl">
<TabControl.Resources> <TabControl.Resources>
<Style TargetType="TabItem"> <Style TargetType="TabItem">
<Setter Property="Template"> <Setter Property="Template">
@@ -1103,7 +1108,7 @@
</TabControl> </TabControl>
<!-- Bottom Navigation Buttons --> <!-- Bottom Navigation Buttons -->
<Grid Grid.Row="2" Height="56" x:Name="BottomNavGrid"> <Grid Grid.Row="1" Height="56" x:Name="BottomNavGrid">
<Grid Margin="20,0"> <Grid Margin="20,0">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/>
@@ -1134,10 +1139,11 @@
<Ellipse x:Name="ProgressIndicator3" Width="10" Height="10" Margin="4,0" Fill="#808080" ToolTip="Deployment Settings"/> <Ellipse x:Name="ProgressIndicator3" Width="10" Height="10" Margin="4,0" Fill="#808080" ToolTip="Deployment Settings"/>
</StackPanel> </StackPanel>
</Grid> </Grid>
</Grid>
<!-- Modal Overlay for MessageBoxes --> <!-- Modal Overlay for MessageBoxes -->
<Rectangle x:Name="ModalOverlay" <Rectangle x:Name="ModalOverlay"
Grid.RowSpan="3" Grid.RowSpan="2"
Fill="#80000000" Fill="#80000000"
Visibility="Collapsed" Visibility="Collapsed"
Panel.ZIndex="1000" Panel.ZIndex="1000"

View File

@@ -1,6 +1,37 @@
function Show-MainWindow { function Show-MainWindow {
Add-Type -AssemblyName PresentationFramework,PresentationCore,WindowsBase,System.Windows.Forms | Out-Null Add-Type -AssemblyName PresentationFramework,PresentationCore,WindowsBase,System.Windows.Forms | Out-Null
# Helper to constrain the maximized window to the monitor working area (respects taskbar).
# Required for WindowStyle=None windows — without this the window extends behind the taskbar.
if (-not ([System.Management.Automation.PSTypeName]'Win11Debloat.MaximizedWindowHelper').Type) {
Add-Type -Namespace Win11Debloat -Name MaximizedWindowHelper `
-ReferencedAssemblies 'PresentationFramework','System.Windows.Forms','System.Drawing' `
-MemberDefinition @'
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
private struct MINMAXINFO {
public POINT ptReserved, ptMaxSize, ptMaxPosition, ptMinTrackSize, ptMaxTrackSize;
}
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
private struct POINT { public int x, y; }
public static System.IntPtr WmGetMinMaxInfoHook(
System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) {
if (msg == 0x0024) { // WM_GETMINMAXINFO
var wa = System.Windows.Forms.Screen.FromHandle(hwnd).WorkingArea;
var mmi = (MINMAXINFO)System.Runtime.InteropServices.Marshal.PtrToStructure(
lParam, typeof(MINMAXINFO));
mmi.ptMaxPosition.x = wa.Left;
mmi.ptMaxPosition.y = wa.Top;
mmi.ptMaxSize.x = wa.Width;
mmi.ptMaxSize.y = wa.Height;
System.Runtime.InteropServices.Marshal.StructureToPtr(mmi, lParam, true);
handled = true;
}
return System.IntPtr.Zero;
}
'@
}
# Get current Windows build version # Get current Windows build version
$WinVersion = Get-ItemPropertyValue 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' CurrentBuild $WinVersion = Get-ItemPropertyValue 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' CurrentBuild
@@ -34,8 +65,6 @@ function Show-MainWindow {
$windowStateNormal = [System.Windows.WindowState]::Normal $windowStateNormal = [System.Windows.WindowState]::Normal
$windowStateMaximized = [System.Windows.WindowState]::Maximized $windowStateMaximized = [System.Windows.WindowState]::Maximized
$normalWindowShadow = $mainBorder.Effect $normalWindowShadow = $mainBorder.Effect
$windowResizeBorder = [System.Windows.SystemParameters]::WindowResizeBorderThickness
$maximizedChromeInset = [System.Windows.Thickness]::new($windowResizeBorder.Left, $windowResizeBorder.Top, $windowResizeBorder.Right, 0)
$initialNormalMaxWidth = 1400.0 $initialNormalMaxWidth = 1400.0
$convertScreenPixelsToDip = { $convertScreenPixelsToDip = {
@@ -64,12 +93,15 @@ function Show-MainWindow {
} }
$updateWindowChrome = { $updateWindowChrome = {
$chrome = [System.Windows.Shell.WindowChrome]::GetWindowChrome($window)
if ($window.WindowState -eq $windowStateMaximized) { if ($window.WindowState -eq $windowStateMaximized) {
$mainBorder.Margin = $maximizedChromeInset $mainBorder.Margin = [System.Windows.Thickness]::new(0)
$mainBorder.BorderThickness = [System.Windows.Thickness]::new(1) $mainBorder.BorderThickness = [System.Windows.Thickness]::new(0)
$mainBorder.CornerRadius = [System.Windows.CornerRadius]::new(0) $mainBorder.CornerRadius = [System.Windows.CornerRadius]::new(0)
$mainBorder.Effect = $null $mainBorder.Effect = $null
$titleBarBackground.CornerRadius = [System.Windows.CornerRadius]::new(0) $titleBarBackground.CornerRadius = [System.Windows.CornerRadius]::new(0)
# Zero out resize borders when maximized so the entire title bar row is draggable
if ($chrome) { $chrome.ResizeBorderThickness = [System.Windows.Thickness]::new(0) }
} }
else { else {
$mainBorder.Margin = [System.Windows.Thickness]::new(0) $mainBorder.Margin = [System.Windows.Thickness]::new(0)
@@ -77,13 +109,10 @@ function Show-MainWindow {
$mainBorder.CornerRadius = [System.Windows.CornerRadius]::new(8) $mainBorder.CornerRadius = [System.Windows.CornerRadius]::new(8)
$mainBorder.Effect = $normalWindowShadow $mainBorder.Effect = $normalWindowShadow
$titleBarBackground.CornerRadius = [System.Windows.CornerRadius]::new(8, 8, 0, 0) $titleBarBackground.CornerRadius = [System.Windows.CornerRadius]::new(8, 8, 0, 0)
if ($chrome) { $chrome.ResizeBorderThickness = [System.Windows.Thickness]::new(5) }
} }
} }
$updateMaximizedBounds = {
& $updateWindowChrome
}
$applyInitialWindowSize = { $applyInitialWindowSize = {
if ($window.WindowState -ne $windowStateNormal) { if ($window.WindowState -ne $windowStateNormal) {
return return
@@ -101,16 +130,40 @@ function Show-MainWindow {
$window.Add_SourceInitialized({ $window.Add_SourceInitialized({
& $applyInitialWindowSize & $applyInitialWindowSize
& $updateMaximizedBounds & $updateWindowChrome
# Register WM_GETMINMAXINFO hook so maximizing respects the working area (taskbar)
$hwndHelper = New-Object System.Windows.Interop.WindowInteropHelper($window)
$hwndSource = [System.Windows.Interop.HwndSource]::FromHwnd($hwndHelper.Handle)
$hookMethod = [Win11Debloat.MaximizedWindowHelper].GetMethod('WmGetMinMaxInfoHook')
$hook = [System.Delegate]::CreateDelegate([System.Windows.Interop.HwndSourceHook], $hookMethod)
$hwndSource.AddHook($hook)
}) })
$contentGrid = $window.FindName('ContentGrid')
$maxContentWidth = 1600.0
$updateContentMargin = {
$w = $window.ActualWidth
if ($w -gt $maxContentWidth) {
$gutter = [Math]::Floor(($w - $maxContentWidth) / 2)
$contentGrid.Margin = [System.Windows.Thickness]::new($gutter, 0, $gutter, 0)
} else {
$contentGrid.Margin = [System.Windows.Thickness]::new(0)
}
}
$window.Add_SizeChanged({ & $updateContentMargin })
$window.Add_StateChanged({ $window.Add_StateChanged({
& $updateMaximizedBounds & $updateWindowChrome
}) })
$window.Add_LocationChanged({ $window.Add_LocationChanged({
if ($window.WindowState -eq $windowStateMaximized) { # Nudge the popup offset to force WPF to recalculate its screen position
& $updateMaximizedBounds if ($script:BubblePopup -and $script:BubblePopup.IsOpen) {
$script:BubblePopup.HorizontalOffset += 1
$script:BubblePopup.HorizontalOffset -= 1
} }
}) })