【问题标题】:How to read the physical screen size of OSX?如何读取 OSX 的物理屏幕尺寸?
【发布时间】:2012-09-17 08:08:38
【问题描述】:

我想知道 Mac OSX 下的物理屏幕尺寸。但是NSDeviceResolution总是报错值(72),所以分辨率/dpi的计算结果是错误的。

在“About This Mac”里面,有一个 Mac 型号字符串,我的是“15-inch, Early 2011”。所以我想知道是否有办法(可能在 obj-c 中)读取该字符串,然后我可以将其用作物理屏幕尺寸。

感谢任何帮助。

【问题讨论】:

    标签: objective-c macos screen dpi


    【解决方案1】:

    您可以使用CGDisplayScreenSize 获取屏幕的物理尺寸(以毫米为单位)。鉴于您已经知道分辨率,您可以从中计算 DPI。

    例如

    NSScreen *screen = [NSScreen mainScreen];
    NSDictionary *description = [screen deviceDescription];
    NSSize displayPixelSize = [[description objectForKey:NSDeviceSize] sizeValue];
    CGSize displayPhysicalSize = CGDisplayScreenSize(
                [[description objectForKey:@"NSScreenNumber"] unsignedIntValue]);
    
    NSLog(@"DPI is %0.2f", 
             (displayPixelSize.width / displayPhysicalSize.width) * 25.4f); 
             // there being 25.4 mm in an inch
    

    @"NSScreenNumber" 的东西看起来很狡猾,但它是从 NSScreen 获得 CGDirectDisplayIDexplicit documented means

    【讨论】:

    • 只有一句话 - NSDeviceSize 包含系统点的大小,而不是物理像素。在 Retina 显示器(例如 iMac 27 Retina 或新的 macbook pro)上,系统点通常为 2 个像素。所以你必须将 NSDeviceSize 乘以 [[NSScreen mainScreen] backingScaleFactor] 以获得物理像素。如果有人在 macOS 系统偏好设置->显示中设置“缩放”分辨率,那就更糟了
    【解决方案2】:

    上面 Tommy 的回答非常好 — 我已将其移植到 Swift(供我自己使用)并在此处发布作为参考,但 Tommy 的回答应该被认为是规范的。

    import Cocoa
    
    public extension NSScreen {
        var unitsPerInch: CGSize {
            let millimetersPerInch:CGFloat = 25.4
            let screenDescription = deviceDescription
            if let displayUnitSize = (screenDescription[NSDeviceDescriptionKey.size] as? NSValue)?.sizeValue,
                let screenNumber = (screenDescription[NSDeviceDescriptionKey("NSScreenNumber")] as? NSNumber)?.uint32Value {
                let displayPhysicalSize = CGDisplayScreenSize(screenNumber)
                return CGSize(width: millimetersPerInch * displayUnitSize.width / displayPhysicalSize.width,
                              height: millimetersPerInch * displayUnitSize.height / displayPhysicalSize.height)
            } else {
                return CGSize(width: 72.0, height: 72.0) // this is the same as what CoreGraphics assumes if no EDID data is available from the display device — https://developer.apple.com/documentation/coregraphics/1456599-cgdisplayscreensize?language=objc
            }
        }
    }
    
    if let screen = NSScreen.main {
        print("main screen units per inch \(screen.unitsPerInch)")
    }
    

    请注意,返回的值类似于,实际上是“每英寸点数”(但不是所有定义;见下文),几乎从来不是“每英寸像素数”——现代 Mac 具有每点的像素数取决于系统偏好设置中当前的“分辨率”设置和设备的固有分辨率(Retina 显示器有更多的像素)。

    知道返回值的是,如果你用类似的代码画一条线

    CGRect(origin: .zero, size: CGSize(width: 10, height: 1)).fill()
    

    如果你用一把非常精确的尺子对着你的屏幕进行测量,这条线的高度将是 1 / pointsPerInch.height 英寸和 1 / pointsPerInch.width 英寸宽。

    (长期以来,图形框架将“点”定义为“现实世界中的 1/72 英寸”也定义为“无论1 x 1 单位的框的宽度或高度最终会以当前分辨率显示在当前显示器上——这两个定义通常相互冲突。)

    所以对于这段代码,我使用“单位”这个词来表明我们不是在处理 1/72 英寸,也不是 1 个物理像素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-22
      • 2020-04-29
      • 1970-01-01
      • 1970-01-01
      • 2012-01-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多