Winforms 相同字体不';在高DPI监视器上看起来不一样

Winforms 相同字体不';在高DPI监视器上看起来不一样,winforms,dpi,Winforms,Dpi,我有一个WinForms应用程序,它在较旧的系统上运行得很好,但在4k监视器上看起来很好时遇到了问题。有多个问题,有很多关于这个主题的文章,但是这个问题集中在一个特定的问题上。我可以设置不同的控件来使用相同的字体,但是在高DPI系统上,控件看起来会有很大的不同。我怎样才能解决这个问题 很明显,我可以改变字体大小,移动控件等等。但是Windows给我的字体大小添加了一个神秘的因素。不知道Windows在做什么,我很难撤销它 在旧系统上,我的测试窗口看起来很完美: 在高DPI系统上,某些控件的字体

我有一个WinForms应用程序,它在较旧的系统上运行得很好,但在4k监视器上看起来很好时遇到了问题。有多个问题,有很多关于这个主题的文章,但是这个问题集中在一个特定的问题上。我可以设置不同的控件来使用相同的字体,但是在高DPI系统上,控件看起来会有很大的不同。我怎样才能解决这个问题

很明显,我可以改变字体大小,移动控件等等。但是Windows给我的字体大小添加了一个神秘的因素。不知道Windows在做什么,我很难撤销它

在旧系统上,我的测试窗口看起来很完美:

在高DPI系统上,某些控件的字体大小与其他控件不同:

我尝试过几种方法,包括在一些控件上手动设置字体,而不是从表单继承。如您所见,更改字体并没有解决问题:

搜索互联网后,我尝试了几种方法来解决此问题,包括:

  • 在PROCESS_DPI_UNAWARE、PROCESS_SYSTEM_DPI_AWARE和
  • 显式而不是使用表单的字体
  • 在旧系统上构建与在高DPI系统上构建
  • 在同一台计算机上构建设置为96 DPI/100%的监视器,而在同一台计算机上构建设置为192 DPI/200%的监视器
  • 在VisualStudio的designer中构建表单与在纯C代码中构建表单
  • .Net 4.0与.Net 4.6.1
  • Visual Studio 2010 vs Visual Studio 2015
我只发现一件事解决了我的问题。不幸的是,我必须在目标机器上完成,而不是在我正在构建的机器上。所以这不是一个实际的解决方案。有关更多详细信息,请参阅“重复步骤”下的第二项

重复的步骤:

  • 这种情况发生在许多窗体上的许多控件上。请参阅下面的代码示例,了解一个简单的小演示。我就是这样得到上面的截图的
  • 我可以通过一个系统设置使此问题出现或消失。如果将主监视器更改为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();
    }
    

这很疯狂,但它确实有效

我在互联网上看到的关于DPI虚拟化的所有信息都表明,默认情况下,Windows将自动设置一个进程来处理DPI。因此,除非您明确选择另外两个设置中的一个,否则您的应用程序在高分辨率监视器上应该看起来不错。它可能有点模糊,但看起来不应该像我上面展示的例子那样糟糕

显然那不是真的。默认值取决于计算机,也取决于日期。我的解决方案:显式地将应用程序设置为使用进程\u DPI\u。我在下面包含了一个代码示例

请注意,您应该能够使用清单处理此问题。一些消息来源说,这是首选的方式,而不是使用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测试人员发送修复程序

摘要

  • O/S为在高DPI系统上运行的旧程序提供兼容模式
  • WinForms和O/S提供了根据系统的DPI手动更改控件大小的工具 或当前监视器
  • 1号和2号都是严重的马车
  • 从一台计算机到下一台计算机,细节变化很大
  • 修理2号更合适 强大的选择,但据我所知,这是不可能的 解决这个问题
  • 相反,我修正了#1。这相当有效

  • 您是指文本框中的字体大小与HiDPI示例中的标签不同吗?是的,文本框和列表框有一个字体大小,按钮和标签的字体大小不同。它们都应该有相同的尺寸。