【问题标题】:Windows Forms window changes its size when I create a WPF window当我创建 WPF 窗口时,Windows 窗体窗口会更改其大小
【发布时间】:2015-11-21 10:58:39
【问题描述】:

我有一个System.Window.Forms.Form 来处理每个按钮的点击。当我收到第一个事件时,我会创建一个新的 WPF System.Windows.Window 对象。

class WPF_Window : Window
{
}


public partial class Form1 : Form
{
    WPF_Window wnd = null;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_MouseClick(object sender, MouseEventArgs e)
    {
        if (wnd == null)
        {
            wnd = new WPF_Window();
        }
    }
}

在我的计算机上,此代码按预期工作,但如果我在另一台计算机(均为 Windows 10)上运行它,当我单击 Windows 窗体窗口时会更改其大小(减小其尺寸)。

这怎么可能?如何避免这种行为?

【问题讨论】:

  • 两台电脑的 DPI 一样吗?
  • 这与 DPI 有关。当您第一次使用 WPF 中的程序集时,Windows 窗体应用程序会随机调整大小。我的猜测是您需要在清单中声明应用程序不支持 DPI。
  • @AnkurTripathi 实际上这些计算具有不同的 DPI,将两者都设置为 100% 可以使应用程序正常工作。但是如何在不更改 DPI 的情况下避免这种行为?
  • @ghord 该应用程序是一个 WinForms 应用程序,我在哪里设置它不是 DPI 感知的精确度?怎么样?
  • 你必须根据 DPI 设置每个宽度和高度等我写一些代码给你..

标签: c# wpf winforms resize interop


【解决方案1】:

您发现 WPF 调用 SetProcessDPIAware()。它发生在 PresentationCore 的模块初始化程序中。这在形式上是非法的,必须始终在应用程序创建任何可能缓存 DPI 值的窗口或加载 DLL 之前调用它。或者换句话说,这可能会出错的很多方法,你还只是发现了它的温和版本。在纯 WPF 应用程序中通常不会出现问题,因为在创建任何窗口之前总是需要加载 PresentationCore。

他们确实留下了一个后门来禁用这种行为。复制/粘贴此代码,最好在您的 EXE 项目的 AssemblyInfo.cs 源文件中:

   [assembly: System.Windows.Media.DisableDpiAwareness]

但这当然不是真正的解决方案,DPI 虚拟化现在始终为您的所有窗口启用。通过在其清单中声明您的应用程序 dpi-aware 来取得成功,这样 PresentationCore 就不会搞砸了。但是由于不可避免的副作用,您现在会发现需要修复 Winforms UI。只有当您更改 Form.AutoScaleMode 属性或执行一些不明智的操作(如硬编码窗口大小)时,它才会变小。该属性是 Q&D 修复。

【讨论】:

    【解决方案2】:

    正如其他回复中所述,这是由于DPI 意识。为使用 VB.NET 的用户关闭它的快速修复:

    打开app.manifest

    然后取消注释这部分并将DPI感知设置为false

    请注意,这可能会导致您的应用程序的字体在更高 DPI 设备上看起来更模糊。

    【讨论】:

      【解决方案3】:

      这些是您可以使用的一些方法。设置窗口的宽高:

      public static Graphics graphics = Graphics.FromHwnd(IntPtr.Zero);
      public static double GetDIPIndependent(double value, double DPI)
      {
          value = value * (graphics.DpiX / DPI);
          return value;
      }
      public static double GetDIPDependent(double value, double DPI)
      {
          value = value * (DPI / graphics.DpiX);
          return value;
      }
      public static double GetDIPIndependent(double value)
      {
          value = value * (graphics.DpiX / 96.0);
          return value;
      }
      
      public static double GetDIPDependent(double value)
      {
          value = value * (96.0 / graphics.DpiX);
          return value;
      }
      

      示例:

      如果 DPI 独立

      this.Width = GetDIPIndependent(this.Width)
      this.Height = GetDIPIndependent(this.Height)
      

      如果依赖 DPI

      this.Width = GetDIPDependent(this.Width)
      this.Height = GetDIPDependent(this.Height)
      

      它对我有用...

      【讨论】:

      • 宽高是Form属性吗?我应该什么时候设置它们?一旦启动?
      • 是的,宽度和高度是表单属性..,,,, 并且可以在窗口的加载方法 this.Loaded += Window_Loaded();
      • 它对我不起作用,无论是使用 GetDIPIndependent 还是 GetDIPDependent... DPI 设置为 150% 的计算机上的窗口仍会自行调整大小。
      • 如果计算机是 100% 并且您想设置宽度 800 而不是看起来像 800 ...但是如果计算机是 150% 您想设置宽度 800 而不是看起来像 512 (DIPDependent) 告诉我您设置宽度和高度的代码,并可以显示图像发生了什么..
      • 我在 InitializeComponent() 之后设置了宽度和高度(代码与我的问题相同)
      猜你喜欢
      • 1970-01-01
      • 2013-11-19
      • 2012-05-31
      • 1970-01-01
      • 2011-07-14
      • 2016-07-07
      • 2011-01-05
      • 2011-01-22
      • 1970-01-01
      相关资源
      最近更新 更多