GetSystemMetrics()在.NET 4.5和.NET 4.0中返回不同的结果。

7

在进行从.NET 4.0到.NET 4.5应用程序迁移的过程中,我发现了一个非常奇怪的行为。我已经能够将此问题跟踪到以下简短的代码段:

class Program
{
    [System.Runtime.InteropServices.DllImport("user32.dll")]
    public static extern int GetSystemMetrics(int nIndex);

    static void Main(string[] args)
    {
        const int CXFRAME = 0x20;
        const int CYFRAME = 0x21;

        var dx = GetSystemMetrics(CXFRAME);
        var dy = GetSystemMetrics(CYFRAME);

        Console.WriteLine("{0}x{1}", dx, dy);
        Console.ReadKey();
    }
}

当使用Target Framework = 4.0编译(也适用于2.0、3.0、3.5),输出结果为8x8

当使用Target Framework = 4.5编译,输出结果为4x4

使用MSVS2012调试器运行此示例时,无论目标框架如何,都始终输出4x4

其他选项(目标框架配置文件、目标平台、启用/禁用Aero)不会影响结果,唯一改变输出的是目标框架和在调试器中运行。我已经在三台电脑上重现了这个问题,但它们在已安装软件方面几乎相同:

  • Windows 7 Ultmate SP1(俄语,已安装所有更新)与MSVS2012(英语/俄语)Update 1
  • Windows 8(虚拟机上)

目前,我正在考虑修补一些.NET类(例如SystemParameters),这些类使用反射调用GetSystemMetrics(),但我不确定如何获取正确的度量值。

问题:

  • 是否遗漏了什么?GetSystemMetrics()如何受到目标框架的影响?
  • 是否有任何方法可以从.NET 4.5应用程序中调用GetSystemMetrics()并获得正确结果?

我愿意听取任何有关解决此问题的建议。此外,如果您无法重现此问题,请在评论中留下简短的系统说明。

2个回答

6
所以,这实际上是一种设计行为,如果有人遇到类似的问题,这里是总是输出相同结果的代码:
const int CXFRAME = 0x20;
const int CYFRAME = 0x21;
const int CXPADDEDBORDER = 92;

var dx = GetSystemMetrics(CXFRAME);
var dy = GetSystemMetrics(CYFRAME);
var d  = GetSystemMetrics(CXPADDEDBORDER);
dx += d;
dy += d;

Console.WriteLine("{0}x{1}", dx, dy);
Console.ReadKey();

需要注意的是,RibbonWindow WPF控件使用了WindowChrome。现在它已经作为.NET 4.5的一部分提供。然而,它不知道这些变化,并且显示出混乱的窗口边框(幸运的是,我认为可以通过修改样式来解决)。


非常有用的笔记,谢谢。最初它并不是按设计来的,后来确认是一个Windows的bug。关于WindowsChrome问题,请查看此答案:https://dev59.com/KnA85IYBdhLWcg3wCfHm#61299269,如果您正在尝试修复最大化窗口,则可以帮助解决问题。 - astef

3

谢谢,那解释了一切。 - max
真遗憾那些链接失效了。我想知道是否还有人保存了那里给出的解释。 - Ray

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