在 WPF 应用程序中支持 Windows 11 Snap Layout

Support Windows 11 Snap Layout in WPF app

我想为WPF启用SnapLayout,因为我使用自定义Window,根据documentation,我必须自己做。

For Win32 apps, make sure you are responding appropriately to WM_NCHITTEST (with a return value of HTMAXBUTTON for the maximize/restore button).

我使用了下面的代码

private const int HTMAXBUTTON = 9;
private IntPtr HwndSourceHook(IntPtr hwnd, int msg, IntPtr wparam,
    IntPtr lparam, ref bool handled)
{
    switch (msg)
    {
        case InteropValues.WM_NCHITTEST:
        try
        {
            int x = lparam.ToInt32() & 0xffff;
            int y = lparam.ToInt32() >> 16;
            var rect = new Rect(_ButtonMax.PointToScreen(
                new Point()),
                new Size(_ButtonMax.Width, _ButtonMax.Height));
            if (rect.Contains(new Point(x, y)))
            {
                handled = true;
            }
            return new IntPtr(HTMAXBUTTON);
        }
        catch (OverflowException)
        {
            handled = true;
        }
        break;
    }
    return IntPtr.Zero;
}

SnapLayout 显示良好但是最大化按钮不起作用,如果我点击它,旁边会创建一个按钮。我该如何解决这个问题?

更新: 这是完整的代码并且工作正常(没有任何问题(鼠标悬停、单击、...))

private const double DPI_SCALE = 1.5;
private const int HTMAXBUTTON = 9;

private IntPtr HwndSourceHook(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled)
{
    switch (msg)
    {
        
        case 0x0084:
            try
            {
                int x = lparam.ToInt32() & 0xffff;
                    int y = lparam.ToInt32() >> 16;
                    Button _button;
                    if (WindowState == WindowState.Maximized)
                    {
                        _button = _ButtonRestore;
                    }
                    else
                    {
                        _button = _ButtonMax;
                    }
                    var rect = new Rect(_button.PointToScreen(
                        new Point()),
                        new Size(_button.Width * DPI_SCALE, _button.Height * DPI_SCALE));
                    if (rect.Contains(new Point(x, y)))
                    {
                        handled = true;
                        _button.Background = OtherButtonHoverBackground;
                    }
                    else
                    {
                        _button.Background = OtherButtonBackground;
                    }
                    return new IntPtr(HTMAXBUTTON);
            }
            catch (OverflowException)
            {
                handled = true;
            }
            break;
        case 0x00A1:
                int x = lparam.ToInt32() & 0xffff;
                int y = lparam.ToInt32() >> 16;
                Button _button;
                if (WindowState == WindowState.Maximized)
                {
                    _button = _ButtonRestore;
                }
                else
                {
                    _button = _ButtonMax;
                }
                var rect = new Rect(_button.PointToScreen(
                    new Point()),
                    new Size(_button.Width * DPI_SCALE, _button.Height * DPI_SCALE));
                if (rect.Contains(new Point(x, y)))
                {
                    handled = true;
                    IInvokeProvider invokeProv = new ButtonAutomationPeer(_button).GetPattern(PatternInterface.Invoke) as IInvokeProvider;
                    invokeProv?.Invoke();
                }
            break;
        default:
            handled = false;
            break;
    }

    return IntPtr.Zero;
}

您需要定义 OtherButtonHoverBackgroundOtherButtonBackground 或替换为 SolidColorBrush。