UI: borderless window with custom chrome, default 1280x720

Window
------
- Default size 1280x720 (16:9 widescreen — matches the screenshot framing
  the user requested), MinWidth=980 MinHeight=600.
- WindowStyle=None + ResizeMode=CanResize: drop the OS title bar but
  keep edge resize.
- WindowChrome: CaptionHeight=56 makes the top bar Border the
  drag-handle for moving the window. ResizeBorderThickness=6 gives
  6px of grab area on each edge, GlassFrameThickness=0 disables Aero.

Custom chrome buttons
---------------------
Three new style keys in Theme.xaml:
- WindowControlButton: 46x32 transparent button, hovers at #FFFFFF22
  (semi-translucent white) — used for minimize and maximize/restore.
- WindowCloseButton: same shape, hovers at #E81123 (Win11 red).

Three handlers wired up: OnMinimizeClick, OnMaxRestoreClick, OnCloseClick.

Caption click-through
---------------------
WindowChrome reserves the caption area for window dragging by default —
buttons inside it would otherwise feel "dead". Each interactive control
in the top bar (Vérifier les MAJ / Dossier / License pill / Activer /
Paramètres / min / max / close) gets
shell:WindowChrome.IsHitTestVisibleInChrome="True" so clicks reach the
button instead of starting a drag. The text/logo region remains
draggable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-02 09:09:14 +02:00
parent dd4ee9bbaa
commit 74f48419e6
3 changed files with 94 additions and 4 deletions

View File

@@ -135,6 +135,50 @@
</Setter> </Setter>
</Style> </Style>
<!-- Boutons de chrome window (min / max / close), 46x40 façon Windows -->
<Style x:Key="WindowControlButton" TargetType="Button">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{StaticResource Brush.Text.Primary}" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Width" Value="46" />
<Setter Property="Height" Value="32" />
<Setter Property="Padding" Value="0" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="FontSize" Value="14" />
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="#FFFFFF22" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="WindowCloseButton" TargetType="Button" BasedOn="{StaticResource WindowControlButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="#E81123" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="IconButton" TargetType="Button"> <Style x:Key="IconButton" TargetType="Button">
<Setter Property="Background" Value="Transparent" /> <Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{StaticResource Brush.Text.Secondary}" /> <Setter Property="Foreground" Value="{StaticResource Brush.Text.Secondary}" />

View File

@@ -2,16 +2,28 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:PSLauncher.App.ViewModels" xmlns:vm="clr-namespace:PSLauncher.App.ViewModels"
xmlns:shell="clr-namespace:System.Windows.Shell;assembly=PresentationFramework"
Title="PROSERVE Launcher" Title="PROSERVE Launcher"
Background="Black" Background="Black"
Width="980" Height="780" Width="1280" Height="720"
MinWidth="780" MinHeight="500" MinWidth="980" MinHeight="600"
WindowStartupLocation="CenterScreen" WindowStartupLocation="CenterScreen"
WindowStyle="None"
ResizeMode="CanResize"
AllowsTransparency="False"
d:DataContext="{d:DesignInstance Type=vm:MainViewModel}" d:DataContext="{d:DesignInstance Type=vm:MainViewModel}"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" mc:Ignorable="d"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"> xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
<shell:WindowChrome.WindowChrome>
<shell:WindowChrome CaptionHeight="56"
GlassFrameThickness="0"
CornerRadius="0"
ResizeBorderThickness="6"
UseAeroCaptionButtons="False" />
</shell:WindowChrome.WindowChrome>
<Window.Resources> <Window.Resources>
<!-- =================== TEMPLATE : LIGNE COMPACTE (autres versions) =================== --> <!-- =================== TEMPLATE : LIGNE COMPACTE (autres versions) =================== -->
@@ -185,10 +197,12 @@
<Button Style="{StaticResource SecondaryButton}" <Button Style="{StaticResource SecondaryButton}"
Content="🔄 Vérifier les MAJ" Content="🔄 Vérifier les MAJ"
Command="{Binding CheckForUpdatesCommand}" Command="{Binding CheckForUpdatesCommand}"
shell:WindowChrome.IsHitTestVisibleInChrome="True"
Margin="0,0,8,0" /> Margin="0,0,8,0" />
<Button Style="{StaticResource SecondaryButton}" <Button Style="{StaticResource SecondaryButton}"
Content="📁 Dossier" Content="📁 Dossier"
Command="{Binding OpenInstallRootCommand}" Command="{Binding OpenInstallRootCommand}"
shell:WindowChrome.IsHitTestVisibleInChrome="True"
Margin="0,0,12,0" /> Margin="0,0,12,0" />
<!-- Badge license --> <!-- Badge license -->
<Border CornerRadius="14" Padding="10,4" <Border CornerRadius="14" Padding="10,4"
@@ -256,10 +270,27 @@
<Button Style="{StaticResource SecondaryButton}" <Button Style="{StaticResource SecondaryButton}"
Content="🔑 Activer / changer" Content="🔑 Activer / changer"
Command="{Binding ActivateLicenseCommand}" Command="{Binding ActivateLicenseCommand}"
shell:WindowChrome.IsHitTestVisibleInChrome="True"
Margin="0,0,8,0" /> Margin="0,0,8,0" />
<Button Style="{StaticResource SecondaryButton}" <Button Style="{StaticResource SecondaryButton}"
Content="⚙ Paramètres" Content="⚙ Paramètres"
Command="{Binding OpenSettingsCommand}" /> shell:WindowChrome.IsHitTestVisibleInChrome="True"
Command="{Binding OpenSettingsCommand}"
Margin="0,0,16,0" />
<!-- Window controls custom (style chrome dark) -->
<Button Style="{StaticResource WindowControlButton}"
Content="—" ToolTip="Réduire"
shell:WindowChrome.IsHitTestVisibleInChrome="True"
Click="OnMinimizeClick" />
<Button Style="{StaticResource WindowControlButton}"
Content="☐" ToolTip="Agrandir / Restaurer"
shell:WindowChrome.IsHitTestVisibleInChrome="True"
Click="OnMaxRestoreClick" />
<Button Style="{StaticResource WindowCloseButton}"
Content="✕" ToolTip="Fermer"
shell:WindowChrome.IsHitTestVisibleInChrome="True"
Click="OnCloseClick" />
</StackPanel> </StackPanel>
</Grid> </Grid>
</Border> </Border>

View File

@@ -12,7 +12,7 @@ public partial class MainWindow : Window
} }
/// <summary> /// <summary>
/// Le bouton "..." ouvre son ContextMenu sur clic gauche (par défaut, ContextMenu ne s'ouvre qu'au clic droit). /// Le bouton "..." ouvre son ContextMenu sur clic gauche.
/// </summary> /// </summary>
private void OnMoreMenuClick(object sender, RoutedEventArgs e) private void OnMoreMenuClick(object sender, RoutedEventArgs e)
{ {
@@ -23,4 +23,19 @@ public partial class MainWindow : Window
menu.IsOpen = true; menu.IsOpen = true;
} }
} }
private void OnMinimizeClick(object sender, RoutedEventArgs e)
{
WindowState = WindowState.Minimized;
}
private void OnMaxRestoreClick(object sender, RoutedEventArgs e)
{
WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
}
private void OnCloseClick(object sender, RoutedEventArgs e)
{
Close();
}
} }