我有一个在旧系统上运行良好的WinForms应用程序,但是我在4k显示器上看起来很难看。有很多问题,并且有很多关于这个问题的文章,但这个问题集中在一个特定问题上。我可以设置不同的控件来使用相同的字体,但在高DPI系统上,控件看起来会有很大不同。我该如何解决这个问题?
显然我可以改变字体大小,移动控件等等。但是Windows在我的字体大小中添加了一个神秘的因素。不知道Windows正在做什么,我很难撤消它!
在较旧的系统上,我的测试窗口看起来很完美:
在高DPI系统上,某些控件的字体大小与其他控件不同:
我尝试了几种方法,包括在某些控件上手动设置字体而不是从表单继承。如您所见,更改字体无法解决问题:
在搜索互联网后,我尝试了几件事来解决这个问题,包括:
我只找到了解决问题的一件事。不幸的是,我必须在目标机器上进行,而不是在我正在构建它的机器上。所以这不是一个实用的解决方案。有关详细信息,请参阅“重复步骤”下的第二项。
重复步骤:
我可以通过一个系统设置使此问题出现或消失。如果您将主显示器更改为96 DPI / 100%缩放,然后重新启动,您将获得所有字体都符合要求的良好结果。如果您将主显示器更改为其他DPI设置,然后重新启动,您将看到不良结果。
private void newFormButton_Click(object sender, EventArgs e)
{
Font copyOfFont = new Font(Font, FontStyle.Strikeout);
Form form = new Form();
form.Font = Font;
string sample = "Abc 123 :)";
int padding = 6;
Label label = new Label();
label.Text = sample;
label.Top = padding;
label.Left = padding;
label.Font = copyOfFont;
label.Parent = form;
Button button = new Button();
button.Text = sample;
button.Top = label.Bottom + padding;
button.Left = padding;
button.Width = label.Width + padding * 2;
button.Height = label.Height + padding * 2;
button.Parent = form;
TextBox textBox = new TextBox();
textBox.Text = sample;
textBox.Size = button.Size;
textBox.Top = button.Bottom + padding;
textBox.Left = padding;
textBox.Parent = form;
ListBox listBox = new ListBox();
listBox.Items.Add(sample);
listBox.Items.Add(sample);
listBox.Width = button.Width;
listBox.Height = button.Height * 2;
listBox.Top = textBox.Bottom + padding;
listBox.Left = padding;
listBox.Font = copyOfFont;
listBox.Parent = form;
form.Show();
}
答案 0 :(得分:0)
这很疯狂,但确实有效。
我在互联网上看到的关于DPI虚拟化的一切都说默认情况下Windows会自动将进程设置为PROCESS_DPI_UNAWARE。因此,除非您明确选择其他两个设置中的一个,否则您的应用程序应该在高分辨率显示器上看起来不错。它可能有点模糊,但它看起来不应该像我上面给出的例子那样糟糕。
显然不为真。默认值取决于计算机,它取决于当天。我的解决方案:显式将应用程序设置为使用PROCESS_DPI_UNAWARE。我在下面提供了一个代码示例。
请注意,您应该能够使用清单来处理此问题。一些消息来源说这是首选方式,而不是使用C#代码。我们的结果好坏参半。 C#代码选项似乎更可靠。
[DllImport("shcore.dll")]
static extern int SetProcessDpiAwareness(_Process_DPI_Awareness value);
enum _Process_DPI_Awareness
{
Process_DPI_Unaware = 0,
Process_System_DPI_Aware = 1,
Process_Per_Monitor_DPI_Aware = 2
}
public MainForm()
{
//int result = SetProcessDpiAwareness(_Process_DPI_Awareness.Process_System_DPI_Aware);
//int result = SetProcessDpiAwareness(_Process_DPI_Awareness.Process_Per_Monitor_DPI_Aware);
int result = SetProcessDpiAwareness(_Process_DPI_Awareness.Process_DPI_Unaware);
System.Diagnostics.Debug.Assert(result == 0);
这适用于许多不同的开发人员计算机。我们即将开始向beta测试人员发送修复程序。
<强>摘要强>