6

I have a WPF app using a custom Maximize/Restore button. In Windows 11, mouse hover on maximize/restore button does not pop up snap layout feature like below:

enter image description here

Does anyone have any idea fixing this issue? Kindly advise.

TIA!

vishal
  • 596
  • 2
  • 12
  • 31
  • 2
    "I have a WPF app using a custom Maximize/Restore button" - How about **not** using a custom maximize/restore button - nor any custom non-client printing, imo. – Dai Sep 08 '21 at 05:07
  • @Dai I'm also strictly against custom NC-areas, but it is still an interesting question if and how this could be achieved. Sometimes you have no chance against some so called "UX-experts" who want a customized very fancy "corporate identity"... – Steeeve Sep 08 '21 at 17:48
  • @Dai Right now it is a requirement from UX, If we could not find any way to support this then they might change their approach. – vishal Sep 09 '21 at 13:42
  • 1
    Does your custom window handle the WM_NCHITTEST message properly? See [Apply the Snap Layout Menu in desktop apps for Windows 11](https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/apply-snap-layout-menu) – Steeeve Sep 09 '21 at 16:49
  • @steeve thanks for the pointer. Will check this out. – vishal Sep 10 '21 at 01:40
  • @Dai how else would you emulate something like what Microsoft Visual Studio does with its window chrome? That is, if you want the eliminate the titlebar but retain the rest of the chrome. Also this is an approach that is so common that Microsoft even bothered to document it quite extensively https://learn.microsoft.com/en-us/dotnet/api/system.windows.shell.windowchrome?view=windowsdesktop-6.0 – Bent Rasmussen Dec 05 '21 at 15:37
  • @BentRasmussen “Eliminate the titlebar but retain the rest of the chrome” - eh? All versions of VS since VS2012 have completely eliminated all native window chrome. There’s no OS-provided titlebar, borders, not even the window’s drop-shadow is native. – Dai Dec 05 '21 at 23:05
  • @dai Sure the window may not be native but the chrome buttons behave as-if native :-) – Bent Rasmussen Dec 05 '21 at 23:18
  • 1
    @Steeeve may I ask for a reason why you're strictly against custom NC-areas? I would agree if Windows displays a dark titlebar when the dark theme is on, but no, the titlebar is always white. MS itself uses a custom NC-area even in their new Notepad in Windows 11. Without the custom dark titlebar any dark theme will look inconsistent. – Mar Apr 27 '22 at 06:56

1 Answers1

0

Here you can find an extensive discussion about this topic

https://github.com/dotnet/wpf/issues/4825

including some working code:

https://github.com/ghost1372/HandyControls/commit/41fce1df04b45ab9a7a8ebad33f3810a89a1ad13

However, in my opinion is too much processing for that snap menu which can be easily displayed by pressing Win + Z keys on your keyboard.

This is the solution that I came up with in XAML only. Instead of having a Border that holds the content of the button, I created a Path around the sign in the center. The area inside the sign will bring up the snap menu because it has no Fill set which means the mouse cursor will hit the WindowChrome over that area. Below is the style and the result. You get the idea. It is not perfect, but it is better than nothing.

<Style x:Key="TitleBarMaximizeButtonStyle" TargetType="Button">
    <Setter Property="Foreground" Value="{DynamicResource WindowTextBrush}"/>
    <Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True"/>
    <Setter Property="IsTabStop" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid>
                    <Path x:Name="p" Width="46" Height="32" ClipToBounds="True" StrokeThickness="0" Stretch="Uniform" Data="M 0,0 45,0 45,31 0,31 Z M 18,11 28,11 28,21 18,21 Z" Fill="Transparent"/>
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Focusable="False"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <DataTrigger Binding="{Binding IsActive, RelativeSource={RelativeSource AncestorType=Window}}" Value="False">
                        <Setter Property="Foreground" Value="{DynamicResource WindowTitleBarInactiveText}"/>
                    </DataTrigger>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="p" Property="Fill" Value="{DynamicResource MouseOverOverlayBackgroundBrush}"/>
                    </Trigger>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter TargetName="p" Property="Fill" Value="{DynamicResource MousePressedOverlayBackgroundBrush}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Snap menu WPF

Alexandru Dicu
  • 1,151
  • 1
  • 16
  • 24