我在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>
如果你有任何关于项目的问题或只是评论。
1条答案
按热度按时间ggazkfy81#
调用
Window.Show
方法时不会调用AspectRatioWindow.Show
方法,因为它未被重写。这是基类和派生类之间的一般继承问题。要确保
Show
方法中的逻辑始终执行,可以将其移到OnSourceInitialized
方法中。顺便说一句,你在逻辑中检查hWnd字段,但它是没有意义的,因为你从来没有存储窗口句柄到该字段。