当我创建 WPF 窗口时,Windows 窗体窗口会更改其大小

Posted

技术标签:

【中文标题】当我创建 WPF 窗口时,Windows 窗体窗口会更改其大小【英文标题】:Windows Forms window changes its size when I create a WPF window 【发布时间】: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 设置每个宽度和高度等我写一些代码给你.. 【参考方案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() 之后设置了宽度和高度(代码与我的问题相同)

以上是关于当我创建 WPF 窗口时,Windows 窗体窗口会更改其大小的主要内容,如果未能解决你的问题,请参考以下文章

wpf窗体中如何调用windows窗口?

WPF编程怎么激活指定窗口?

如何在鼠标位置打开具有 Windows 窗体父级的 WPF 窗口?

从 WindowsFormsHost 中的 Windows 窗体控件获取 WPF 窗口

如何将窗体窗口的所有者设置为 WPF 窗口?

wpf window窗口中嵌入一个window窗口