Windows 表单 window 在我创建 WPF 时更改其大小 window
Windows Forms window changes its size when I create a WPF window
我有一个 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 表单 window更改其大小(减小其尺寸)。
怎么可能?我怎样才能避免这种行为?
这些是您可以使用的一些方法。设置window的宽高:
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)
对我有用...
您发现 WPF 调用 SetProcessDPIAware()。它发生在 PresentationCore 的模块初始值设定项中。这在形式上是非法的,必须始终在应用程序创建任何 windows 或加载可能缓存 DPI 值的 DLL 之前调用它。或者换句话说,这可能会出错的方式有很多,您目前只发现了它的温和版本。在纯 WPF 应用程序中通常不是问题,因为在创建任何 window 之前始终需要加载 PresentationCore。
他们确实留下了后门来禁用此行为。 Copy/paste 这段代码,最好放在你的 EXE 项目的 AssemblyInfo.cs 源文件中:
[assembly: System.Windows.Media.DisableDpiAwareness]
但这当然不是真正的解决方法,现在始终为您的所有 windows 启用 DPI 虚拟化。通过在其清单中声明您的应用程序 dpi-aware 来取得成功,这样 PresentationCore 就不会搞砸了。但是由于不可避免的副作用,您现在会发现您需要修复 Winforms UI。它只能在您更改 Form.AutoScaleMode 属性 或做一些不明智的事情时变小,例如硬编码 window 大小。该属性是 Q&D 修复。
如其他回复所述,这是因为 DPI 意识。为那些使用 VB.NET:
的人关闭它的快速修复
打开app.manifest
然后取消注释这部分并将DPI感知设置为false:
请注意,这可能会导致您的应用程序字体在更高 DPI 设备上看起来更加模糊。
我有一个 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 表单 window更改其大小(减小其尺寸)。
怎么可能?我怎样才能避免这种行为?
这些是您可以使用的一些方法。设置window的宽高:
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)
对我有用...
您发现 WPF 调用 SetProcessDPIAware()。它发生在 PresentationCore 的模块初始值设定项中。这在形式上是非法的,必须始终在应用程序创建任何 windows 或加载可能缓存 DPI 值的 DLL 之前调用它。或者换句话说,这可能会出错的方式有很多,您目前只发现了它的温和版本。在纯 WPF 应用程序中通常不是问题,因为在创建任何 window 之前始终需要加载 PresentationCore。
他们确实留下了后门来禁用此行为。 Copy/paste 这段代码,最好放在你的 EXE 项目的 AssemblyInfo.cs 源文件中:
[assembly: System.Windows.Media.DisableDpiAwareness]
但这当然不是真正的解决方法,现在始终为您的所有 windows 启用 DPI 虚拟化。通过在其清单中声明您的应用程序 dpi-aware 来取得成功,这样 PresentationCore 就不会搞砸了。但是由于不可避免的副作用,您现在会发现您需要修复 Winforms UI。它只能在您更改 Form.AutoScaleMode 属性 或做一些不明智的事情时变小,例如硬编码 window 大小。该属性是 Q&D 修复。
如其他回复所述,这是因为 DPI 意识。为那些使用 VB.NET:
的人关闭它的快速修复打开app.manifest
然后取消注释这部分并将DPI感知设置为false:
请注意,这可能会导致您的应用程序字体在更高 DPI 设备上看起来更加模糊。