windows C# WPF AspectRationWindow在一个项目中工作,但在另一个项目中不工作

polhcujo  于 2023-03-19  发布在  Windows
关注(0)|答案(1)|浏览(146)

我在WPF for .NET 6中有两个项目,在一个项目中,我在这里写下的类可以工作,但在另一个项目中却不行。
我有这样一个类,它应该保留我的窗口的AspectRatio:

namespace Bank.UI;

using System.Runtime.InteropServices;
using System.Windows.Interop;
using System;
using System.Windows;

public class AspectRatioWindow : Window
{
    private const int WM_SIZING = 0x0214;
    private const int WM_WINDOWPOSCHANGING = 0x0046;

    private const int WMSZ_LEFT = 1;
    private const int WMSZ_RIGHT = 2;
    private const int WMSZ_TOP = 3;
    private const int WMSZ_TOPLEFT = 4;
    private const int WMSZ_TOPRIGHT = 5;
    private const int WMSZ_BOTTOM = 6;
    private const int WMSZ_BOTTOMLEFT = 7;
    private const int WMSZ_BOTTOMRIGHT = 8;

    private IntPtr hWnd = IntPtr.Zero;
    private double xRatio = 1;
    private double yRatio = 1;
    private int sizingEdge = 0;

    private IntPtr DragHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handeled)
    {
        switch (msg)
        {
            case WM_SIZING: sizingEdge = wParam.ToInt32(); break;

            case WM_WINDOWPOSCHANGING:

                var position = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS))!;

                if (position.cx == Width && position.cy == Height) return IntPtr.Zero;

                switch (sizingEdge)
                {
                    case WMSZ_TOP or WMSZ_BOTTOM or WMSZ_TOPRIGHT:
                        position.cx = (int)(position.cy * xRatio);
                        break;

                    case WMSZ_LEFT or WMSZ_RIGHT or WMSZ_BOTTOMRIGHT or WMSZ_BOTTOMLEFT:
                        position.cy = (int)(position.cx * yRatio);
                        break;

                    case WMSZ_TOPLEFT:
                        position.cx = (int)(position.cy * xRatio);
                        position.x = (int)Left - (position.cx - (int)Width);
                        break;
                }

                Marshal.StructureToPtr(position, lParam, true);
                break;
        }

        return IntPtr.Zero;
    }

    public new void Show()
    {
        xRatio = Width / Height;
        yRatio = Height / Width;

        base.Show();

        if (hWnd == IntPtr.Zero)
        {
            var hWnd = new WindowInteropHelper(this).Handle;

            var source = HwndSource.FromHwnd(hWnd);
            source?.AddHook(DragHook);
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct WINDOWPOS
    {
        public IntPtr hwnd;
        public IntPtr hwndInsertAfter;
        public int x;
        public int y;
        public int cx;
        public int cy;
        public int flags;
    }
}

来自主窗口的C#代码:

namespace MyApp;

using System;
using System.ComponentModel;
using System.Windows;

public sealed partial class MainWindow : AspectRatioWindow
{
    public MainWindow()
    {
        InitializeComponent();
    }

    protected override async void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);

        await AppCore.OnStart();
    }

    protected override async void OnClosing(CancelEventArgs e)
    {
        base.OnClosing(e);

        await AppCore.OnStart();
    }
}

主窗口中的XAML代码:

<ui:AspectRatioWindow x:Class="MyApp.MainWindow"
                      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                      xmlns:ui="clr-namespace:MyApp.UI"
                      Title="MyApp"
                      MinHeight="500"
                      MinWidth="800"
                      Height="500"
                      Width="800"
                      WindowStyle="ThreeDBorderWindow"
                      WindowStartupLocation="CenterScreen"
                      ResizeMode="CanResize"
                      Background="{StaticResource BackgroundColor}">

    <Viewbox Stretch="Uniform">
        <StackPanel Orientation="Vertical" Margin="20,10,20,10" HorizontalAlignment="Center"/>

            ..Controls..

        </StackPanel>
    </Viewbox>
</ui:AspectRatioWindow>

如果你有任何关于项目的问题或只是评论。

ggazkfy8

ggazkfy81#

调用Window.Show方法时不会调用AspectRatioWindow.Show方法,因为它未被重写。这是基类和派生类之间的一般继承问题。
要确保Show方法中的逻辑始终执行,可以将其移到OnSourceInitialized方法中。

public class AspectRatioWindow : Window
{
    ...
    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);

        xRatio = Width / Height;
        yRatio = Height / Width;

        var hWnd = new WindowInteropHelper(this).Handle;
        var source = HwndSource.FromHwnd(hWnd);
        source?.AddHook(DragHook);
    }
    ...
}

顺便说一句,你在逻辑中检查hWnd字段,但它是没有意义的,因为你从来没有存储窗口句柄到该字段。

相关问题