合格的双重未正确显示

时间:2016-05-27 15:02:46

标签: c# .net properties double

我正在尝试制作一些控件,其大小将使用限定的double设置,以便控件大小无论在哪个屏幕上显示都是相同的。

所以我有这个转换器将double转换为限定的double:

double effectiveValue = cm;
string qualifiedDouble = effectiveValue + "cm";
LengthConverter lc = new LengthConverter();
double converted = (double)lc.ConvertFrom(qualifiedDouble);

问题在于它对系统参数(例如分辨率或默认系统缩放)的效率不高(idk如何用英语调用)

enter image description here

您是否知道如何在任何分辨率,任何缩放设置等任何屏幕上显示相同的厘米数值。

由于

2 个答案:

答案 0 :(得分:3)

它应该(大部分)工作,我做了几次类似的事情,但你需要确保在你的桌面外观设置(和图形卡设置,演示文稿配置文件等 - 如果你有任何这样的软件)你禁用所有缩放(设置为100%正常,没有大字体等)。我相信"系统缩放"你提到过。

将其设置为100%后,所有WPF单位应在任何屏幕上显示相同的内容。因此,所有屏幕上的10x10rectangle(或10cmx10cm)应该看起来相同。如果您使用合格,那么它在任何分辨率上应该看起来相同。理论上,或者更确切地说,在OperatingSystem的观点。

问题是,即使操作系统100%确定一切都计算得好,仍有一些卡/显示器配置可以"谎言"关于他们的能力的操作系统。您无法从壁式投影仪获得实际的DPI。一些具有较大尺寸的显示器可以缩放图像并且会水平或垂直扭曲图像以填充整个屏幕,因此不会出现黑色边缘。你的显卡的软件驱动程序也可以在内部执行,因此操作系统不会知道它。 WPF的DPI,设备无关单元和合格长度都是关于系统知道什么以及与真实屏幕相关的方式。

但是,如果您确保禁用所有系统缩放,屏幕填充,16:9/4:3翻译等,那么您可以确保正确显示它。您无法让用户配置它。一旦他们这样做,他们就可以用一些简单的标尺来验证结果。您的应用将显示的屏幕。如果它仍然是错的,那么这主要归咎于硬件,你就会陷入困境。如果用户真的想让它运行,则需要进行更改。

顺便说一句。我没有找到任何方法来完全处理"系统缩放",这是OS显示的一个奇怪的部分。一开始看起来很简单,只需从注册表/等中读取设置并相应地按比例放大/缩小,但事实证明,在不同操作系统版本(例如winXP vs win7)上,缩放工作了一点点不同..也许你会找到一种方式,我没有。我刚要求用户设置为100%。或者更换硬件,因为当它们已经设置为非100%时,它几乎总是表明他们的gpu /显示器有奇怪的分辨率有一些"智能软件"这做了一些额外的缩放..

答案 1 :(得分:1)

所以我终于找到了一种方法,使用EDID,其中包含连接到计算机的显示器上的足够信息。 EDID存储在注册表中:

HKLM\SYSTEM\CurrentControlSet\Enum\\DISPLAY\ + displayId + registryId

以下是检索将cm转换为屏幕上像素的比率的代码

public static double GetCmToPixelRatio()
{
    var diagVector = GetActiveDisplayDiag();

    var width = System.Windows.SystemParameters.PrimaryScreenWidth;
    return width / diagVector.X;
}


public static int GetDPIX()
{
    var dpiXProperty = typeof(SystemParameters).GetProperty("DpiX", BindingFlags.NonPublic | BindingFlags.Static);

    return (int)dpiXProperty.GetValue(null, null);

}

private static Point GetActiveDisplayDiag()
{
    //get active display
    string wmiQuery = string.Format("Select * from Win32_DesktopMonitor");

    ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmiQuery);
    ManagementObjectCollection retObjectCollection = searcher.Get();

    foreach (ManagementObject retObject in retObjectCollection)
    {
        try
        {
            //get display id
            string regPath = (string)retObject.GetPropertyValue("PNPDeviceID");
            if (regPath != null)
            {
                var pathInfo = regPath.Split('\\');
                var displayId = pathInfo[1];
                RegistryKey reg = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum\\DISPLAY\\" + displayId);
                var firstSubReg = reg.GetSubKeyNames()[0];
                reg = reg.OpenSubKey(firstSubReg + "\\Device Parameters");
                var edid = (byte[])reg.GetValue("EDID");
                return new Point(edid[21], edid[22]);
            }
        }
        catch (Exception) { }
    }
    return new Point();
}

使用我创建了我的转换器:

public class CmToPixelConverter : IValueConverter
{
    double ratio = DisplayHelper.GetCmToPixelRatio();

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (double)value * ratio;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}