如何才能在WPF窗口中允许统一调整大小?

Mar*_*ter 17 .net c# wpf resize aspect-ratio

我不希望我的窗口"仅水平"或"仅垂直"调整大小.我可以在我的窗口上设置一个可以强制执行此操作的属性,还是有一个可以使用的漂亮的代码隐藏技巧?

Gan*_*ant 13

您可以使用WPF的ViewBox保留内容的宽高比,并使用固定宽度和高度的控件.

让我们试一试.您可以更改ViewBox的"Stretch"属性以体验不同的结果.

这是我的screeen镜头: 在此输入图像描述

<Window x:Class="TestWPF.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">

    <Viewbox Stretch="Uniform">
        <StackPanel Background="Azure" Height="400" Width="300" Name="stackPanel1" VerticalAlignment="Top">
            <Button Name="testBtn" Width="200" Height="50">
                <TextBlock>Test</TextBlock>
            </Button>
        </StackPanel>
    </Viewbox>

</Window>
Run Code Online (Sandbox Code Playgroud)

  • 这将导致窗口的*content*统一调整大小,而不是窗口本身... (8认同)
  • @Frank Krueger:在Win32中并不是那么简单,唯一的区别是你已经知道了怪癖和预期的行为.一旦你了解WPF中的那些,就可以轻松地做任何你想做的事情. (7认同)
  • "让我们试一试" - 对WPF的完美描述 - 它会起作用吗?没有人知道!我们试试吧.我会坚持使用Win32,我只告诉操作系统:这是我的大小,处理它. (3认同)

Nir*_*Nir 11

您始终可以处理WM_WINDOWPOSCHANGING消息,这可以让您在调整大小过程中控制窗口大小和位置(而不是在用户完成大小调整后修复内容).

以下是您在WPF中的操作方法,我将这些代码与多个来源相结合,因此可能会出现一些语法错误.

internal enum WM
{
   WINDOWPOSCHANGING = 0x0046,
}

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

private void Window_SourceInitialized(object sender, EventArgs ea)
{
   HwndSource hwndSource = (HwndSource)HwndSource.FromVisual((Window)sender);
   hwndSource.AddHook(DragHook);
}

private static IntPtr DragHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handeled)
{
   switch ((WM)msg)
   {
      case WM.WINDOWPOSCHANGING:
      {
          WINDOWPOS pos = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS));
          if ((pos.flags & (int)SWP.NOMOVE) != 0)
          {
              return IntPtr.Zero;
          }

          Window wnd = (Window)HwndSource.FromHwnd(hwnd).RootVisual;
          if (wnd == null)
          {
             return IntPtr.Zero;
          }

          bool changedPos = false;

          // ***********************
          // Here you check the values inside the pos structure
          // if you want to override tehm just change the pos
          // structure and set changedPos to true
          // ***********************

          if (!changedPos)
          {
             return IntPtr.Zero;
          }

          Marshal.StructureToPtr(pos, lParam, true);
          handeled = true;
       }
       break;
   }

   return IntPtr.Zero;
}
Run Code Online (Sandbox Code Playgroud)


Ben*_*err 8

这就是我的解决方案.

您需要将其添加到控件/窗口标记中:

Loaded="Window_Loaded"
Run Code Online (Sandbox Code Playgroud)

你需要将它放在你的代码中:

private double aspectRatio = 0.0;

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    aspectRatio = this.ActualWidth / this.ActualHeight;
}

protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
    if (sizeInfo.WidthChanged)
    {
        this.Width = sizeInfo.NewSize.Height * aspectRatio;
    }
    else
    {
        this.Height = sizeInfo.NewSize.Width * aspectRatio;
    }
}
Run Code Online (Sandbox Code Playgroud)

我尝试了Viewbox技巧,但我不喜欢它.我想将窗口边框锁定到特定大小.这是在窗口控件上测试的,但我认为它也适用于边框.

  • 这种方法有效,但是在调整大小操作期间窗口边框闪烁(缺少更好的单词)的缺点是 - 首先将大小设置为用户可以自由调整大小的大小,然后将边框调整为被覆盖的尺寸. (2认同)

End*_*ssa 1

您可以尝试复制我经常在 Flash 视频网站上看到的效果。它们允许您以任何您喜欢的方式扩展浏览器窗口,但仅拉伸演示区域,使其适合高度或宽度中的最小值。

例如,如果您垂直拉伸窗口,您的应用程序将不会调整大小。它可以简单地在显示区域的顶部和底部添加黑条并保持垂直居中。

这对于 WPF 来说可能可行,也可能不可能;我不知道。