gpt4 book ai didi

How to maintain 16:9 aspect ratio of AppWindow when user resizes in Windows App SDK (WinUI 3)?(当用户在Windows App SDK(WinUI3)中调整大小时,如何保持AppWindow的16:9宽高比?)

转载 作者:bug小助手 更新时间:2023-10-25 22:03:51 28 4
gpt4 key购买 nike



When a user resizes the main window in a WinUI 3 Windows App SDK app I would like to force the window to maintain an aspect ratio of 16:9. I tried to accomplish it in the SizeChanged event handler ...

当用户在WinUI3 Windows App SDK应用程序中调整主窗口大小时,我希望强制窗口保持16:9的纵横比。我尝试在SizeChanged事件处理程序中完成此操作...


private void Window_SizeChanged(object sender, WindowSizeChangedEventArgs args)
{
var window = sender as MainWindow;
Windows.Graphics.SizeInt32 y;
y.Height = (int)args.Size.Height;
int adjustedWidth = y.Height * 16 / 9;
y.Width = adjustedWidth;
window.AppWindow.Resize(y);
}

更多回答
优秀答案推荐

One solution is to use the underlying Windows API, as Windows is sending the WM_SIZING message when a window is being resized.

一种解决方案是使用底层Windows API,因为Windows在调整窗口大小时发送WM_SIZING消息。


For that, you need to be able to handle window messages. Here is some sample code, with interop parts, that does that:

为此,您需要能够处理窗口消息。以下是一些带有互操作部分的示例代码,可以实现这一点:


public sealed partial class MainWindow : Window
{
private readonly WindowProcedureHook _hook;

public MainWindow()
{
this.InitializeComponent();

// hook the window procedure
_hook = new WindowProcedureHook(this, WndProc);
}

private IntPtr? WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam)
{
// handle the WM_SIZING message
const int WM_SIZING = 0x0214;
if (msg == WM_SIZING)
{
// get sizing rect
var rc = Marshal.PtrToStructure<RECT>(lParam);

// if coming from left/right only, we adjust height
const int WMSZ_LEFT = 1;
const int WMSZ_RIGHT = 2;
if (wParam.ToInt64() == WMSZ_LEFT || wParam.ToInt64() == WMSZ_RIGHT)
{
rc.height = rc.width * 9 / 16;
}
else
{
rc.width = rc.height * 16 / 9;
}

// put it back, say we handled it
Marshal.StructureToPtr(rc, lParam, false);
return new IntPtr(1);
}

return null; // unhandled, let Windows do the job
}

[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int left;
public int top;
public int right;
public int bottom;

public int width { get => right - left; set => right = left + value; }
public int height { get => bottom - top; set => bottom = top + value; }
}
}

// a utility class to hook window procedure and handle messages, or not
public sealed class WindowProcedureHook
{
private readonly IntPtr _prevProc;
private readonly WNDPROC _wndProc;
private readonly Func<IntPtr, int, IntPtr, IntPtr, IntPtr?> _callback;

public WindowProcedureHook(Window window, Func<IntPtr, int, IntPtr, IntPtr, IntPtr?> callback)
{
ArgumentNullException.ThrowIfNull(window);
ArgumentNullException.ThrowIfNull(callback);

_wndProc = WndProc;
var handle = WinRT.Interop.WindowNative.GetWindowHandle(window);
_callback = callback;

const int GWLP_WNDPROC = -4;
_prevProc = GetWindowLong(handle, GWLP_WNDPROC);
SetWindowLong(handle, GWLP_WNDPROC, Marshal.GetFunctionPointerForDelegate(_wndProc));
}

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam) => _callback(hwnd, msg, wParam, lParam) ?? CallWindowProc(_prevProc, hwnd, msg, wParam, lParam);
private delegate IntPtr WNDPROC(IntPtr handle, int msg, IntPtr wParam, IntPtr lParam);

private static IntPtr GetWindowLong(IntPtr handle, int index) =>
IntPtr.Size == 8 ? GetWindowLongPtrW(handle, index) : (IntPtr)GetWindowLongW(handle, index);

private static IntPtr SetWindowLong(IntPtr handle, int index, IntPtr newLong) =>
IntPtr.Size == 8 ? SetWindowLongPtrW(handle, index, newLong) : (IntPtr)SetWindowLongW(handle, index, newLong.ToInt32());

[DllImport("user32")]
private static extern IntPtr CallWindowProc(IntPtr prevWndProc, IntPtr handle, int msg, IntPtr wParam, IntPtr lParam);

// note: WinUI3 windows are unicode, so we only use the "W" versions

[DllImport("user32")]
private static extern IntPtr GetWindowLongPtrW(IntPtr hWnd, int nIndex);

[DllImport("user32")]
private static extern int GetWindowLongW(IntPtr hWnd, int nIndex);

[DllImport("user32")]
private static extern int SetWindowLongW(IntPtr hWnd, int nIndexn, int dwNewLong);

[DllImport("user32")]
private static extern IntPtr SetWindowLongPtrW(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
}


You need to set both Width and Height on SizeInt32. This works:

您需要在SizeInt32上同时设置宽度和高度。这是可行的:


MainWindow.xaml.cs

MainWindow.xaml.cs


using Microsoft.UI.Xaml;
using Windows.Graphics;

namespace WinUI3App1;

public sealed partial class MainWindow : Window
{
private double _currentWindowWidth = 0;

private double _currentWindowHeight = 0;

public MainWindow()
{
this.InitializeComponent();
this.SizeChanged += MainWindow_SizeChanged;
KeepWindowSizeAspectRatio();
}

public double WindowSizeAspectRatio { get; set; } = 16.0 / 9;

private void MainWindow_SizeChanged(object sender, WindowSizeChangedEventArgs args)
{
KeepWindowSizeAspectRatio();
}

private void KeepWindowSizeAspectRatio()
{
if (_currentWindowWidth is 0 ||
_currentWindowHeight is 0)
{
_currentWindowWidth = this.AppWindow.Size.Width;
_currentWindowHeight = this.AppWindow.Size.Height;
}

int newWidth = this.AppWindow.Size.Width;
int newHeight = this.AppWindow.Size.Height;

if (this.AppWindow.Size.Width != _currentWindowWidth)
{
newHeight = (int)(newWidth / WindowSizeAspectRatio);
_currentWindowWidth = this.AppWindow.Size.Width;
}

if (this.AppWindow.Size.Height != _currentWindowHeight)
{
newWidth = (int)(newHeight * WindowSizeAspectRatio);
_currentWindowHeight = this.AppWindow.Size.Height;
}

this.AppWindow.Resize(new SizeInt32(newWidth, newHeight));
}
}

更多回答

Works, but the window resize is not as smooth as with Simon's solution. Thanks!

工作,但窗口大小调整不像西蒙的解决方案那么顺利。谢谢!

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com