打开 WPF 用户控件 Winform 窗口会缩小父 Winform 窗口。

14

我有一个像这样的 WPF 用户控件...

namespace WpfApplication1
{
    public partial class MyControl : UserControl
    {
    ......
    }
}

我也有一个 Windows 窗体来包含这个 WPF 用户控件...

namespace WindowsFormsApplication4
{
public partial class Form1 : Form
{

    public Form1()
    {

        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        ElementHost ctrlHost = new ElementHost();
        ctrlHost.Dock = DockStyle.Fill;
        WpfApplication1.MyControl win = new WpfApplication1.MyControl();
        ctrlHost.Child = win;
        this.Controls.Add(ctrlHost);
    }
}
}

我有一个父窗体,其中包含一个按钮。点击该按钮将打开包含ElementHost的Form1。

namespace WindowsFormsApplication4
{
    public partial class Parent : Form
    {
        public Parent()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form1 form1 = new Form1();
            form1.Show();

        }
    }
}

默认情况下,我的应用程序运行父窗体...

Application.Run(new Parent());

我面临的问题很奇怪。当我运行应用程序时,父窗体打开,在单击按钮后,包含WPF控件的子窗体也会打开。但问题是,一旦WPF控件窗体弹出,父窗体窗口的大小会自动缩小(窗口会位移、恢复并且其中的控件和字体变得更小)。如果我注释掉“Form1_Load”函数的内容,则父窗口不会缩小。为了检查最坏情况,我注释掉了“Form1_Load”中除...之外的所有内容。

ElementHost ctrlHost = new ElementHost();

这行。仅仅是它的存在就会像我之前提到的那样使父表单收缩。我尝试在互联网上广泛搜索这个问题。但我没有找到解决方案。请帮我回答。我很累了....


请查看此链接:http://www.codeproject.com/Tips/130414/Host-Windows-Form-Controls-in-WPF。我认为您需要提供窗体的特定宽度和高度,然后尝试加载子用户控件。由于添加了子内容,因此会将其添加到您的表单中,并且会发现需要更多空间,这就是为什么它会缩小的原因。 - Ashok Rathod
感谢您的评论,Ashok。我尝试为父窗口设置宽度和高度。但问题仍然存在... - balaji
这个问题有进展了吗?我也遇到了完全相同的问题。 - user958578
有同样的问题。有什么想法吗? - dten
我也遇到了同样的问题。一个带有空ElementHost的Windows窗体会导致父窗口缩小。 - iCode
1个回答

15

我之前评论过我遇到了同样的问题,并已经解决。我在这里记录下我的更改,以供其他人参考。

正如上面所观察到的,每当在WinForms应用程序中使用Windows UI缩放并且Just In Time (JIT)编译器处理来自WPF库的任何内容时,这种行为似乎会发生。在我的情况下,进入包含打开WPF版本MessageBox代码的方法将引起此问题。 通常,Windows会为您处理基本缩放,将其渲染到屏幕外位图,然后放大绘制到屏幕上。但是,当WPF加载时,它似乎接管了这一功能,好像在对Windows说:“嘿...我处理这个...”。之后,Windows停止为您缩放WinForms,并且您最终得到1x比例版本和通常会混淆控件。不过,WPF部分正在处理自己的缩放,并且看起来很好。

因此,我解决问题的方法是告诉Windows我将处理WinForms缩放。要启用它,您必须将以下内容添加到应用程序清单中(dll清单被忽略):

<asmv3:application>
  <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
    <dpiAware>true</dpiAware>
  </asmv3:windowsSettings>
</asmv3:application>

如果已经存在,请取消注释以下部分:

<application xmlns="urn:schemas-microsoft-com:asm.v3">
  <windowsSettings>
    <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
  </windowsSettings>
</application>

您可以添加一个清单文件:

右键单击应用程序项目 -> 添加 -> 新建项... -> 应用程序清单文件

然后在...

应用程序项目 -> 属性 -> 应用程序 -> 资源

确保“清单”设置为app.manifest

现在您可以找到该文件并将上述XML添加到根<asmv1:assembly>元素中。

如果您使用默认的应用程序清单并添加了该元素,则可能看起来像这样

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2"  xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <applicationRequestMinimum>
        <defaultAssemblyRequest permissionSetReference="Custom" />
        <PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" />
      </applicationRequestMinimum>
    </security>
  </trustInfo>
  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
</asmv1:assembly>

现在,当您启动WinForms应用程序时,您会注意到它的清晰度更高,因为它以高dpi渲染,而不是96dpi然后缩放以填充空间。

您可能会注意到许多图像已经缩小了! 在我的情况下,按钮、MenuStripItems和ToolStripItems没有按预期缩放。

我发现大多数控件都有一个可以重写的方法,如下所示:

protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
{
    base.ScaleControl(factor, specified);
}

这是在应用程序启动时调用的,从主窗体筛选控件。我的Windows设置为200%,我的主窗体缩放模式设置为DPI,并且所有窗体都以100%比例(96dpi)设计。我在第一次尝试解决问题时改变了所有继承缩放模式的内容,这就是对我有用的方法,如果你使用字体或无则会产生同样的效果,但我还没有尝试过。

当此方法被调用时,我的UI缩放为200%,因此factor简单地是{2.0, 2.0},然后我用它来重新创建一个缩放的ImageButton中,并将每个MenuStripToolStripItemsImageScalingSize增加,因为它们不接收ScaleControl调用。如果您从未添加过上面的XML,则仍会调用此方法,但因素仅为{1.0,1.0},这并没有什么帮助。

请注意:如果您正在使用图像列表,则不要在DesignMode下动态设置图像,否则ImageList将取消设置,保存时什么都不会设置。

还要注意,因素是相对于当前的因素。您会注意到,如果将应用程序移动到不同的dpi监视器之间,您将获得2.0,然后是0.5,然后是2.0,然后是0.5等。

现在我的WinForms应用程序看起来非常清晰,可以调用WPF UI元素而不会发疯!哎呀!

希望这能对某些人有所帮助


非常感谢!在我的情况下,我必须关闭它,以便让Windows处理所有缩放 :) - Jerther
谢谢。这很有帮助。 - Spongebob Comrade

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接