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

问题描述 投票:0回答:2

我想为WPF启用

SnapLayout
,因为我使用自定义窗口,根据文档,我必须自己做。

对于 Win32 应用程序,请确保您正确响应 WM_NCHITTEST(返回值为 HTMAXBUTTON 最大化/恢复按钮)。

我使用了以下代码

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
显示良好,但最大化按钮不起作用,如果我单击它,旁边会创建一个按钮。我该如何解决这个问题?

c# wpf wndproc
2个回答
1
投票

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

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。


0
投票

我建议使用ControlzEx WindowChromeBehavior,它就像一个魅力,完全支持对齐布局。

我还创建了一个基于 ControlzEx 的完全工作的自定义窗口标题栏示例。 代码示例

© www.soinside.com 2019 - 2024. All rights reserved.