如何在 Mac OS X 中获取显示名称和显示 ID?

发布于 2024-07-30 04:59:36 字数 850 浏览 6 评论 0原文

我想知道您是否可以帮助我弄清楚如何在 Mac OS X (10.5) 中使用显示器的显示 ID 编号以编程方式获取显示器的显示名称? 一个要求是,如果我向函数提供显示 ID,它将提供显示名称作为回报(反之亦然)。

显示名称如下所示:“Color LCD”、“SAMSUNG”

显示 ID 如下所示:“69671872”、“893830283”

Cocoa (Obj-C) 中的 NSScreenCGGetActiveDisplayList 在 Quartz (C) 中,允许您获取显示器的显示 ID 号。 两者似乎都没有获取显示名称的方法。 不好了! 以下是 NSScreen 获取显示器 ID 的代码:

NSArray *screenArray = [NSScreen screens];
NSDictionary *screenDescription = [[screenArray objectAtIndex:0] deviceDescription];
NSLog(@"Device ID: %@", [screenDescription objectForKey:@"NSScreenNumber"]);

系统分析器,以及系统偏好设置下的显示器,参考显示器按显示名称,而不是显示 ID。

我这样问是因为我想运行 AppleScript,它需要显示名称而不是显示 ID。 任何帮助深表感谢! :)

I was wondering if you could help me figure out how to progmatically get the Display Name for a monitor by using its Display ID number in Mac OS X (10.5)? A requirement is if I give a function the Display ID, it'll provide the Display Name in return (or vice versa).

Display Name looks something like this: "Color LCD", "SAMSUNG"

Display ID looks something like this: "69671872", "893830283"

NSScreen in Cocoa (Obj-C), or CGGetActiveDisplayList in Quartz (C), allow you to get the Display ID number for a monitor. Neither appear to have a method to get the Display Name. Oh no! Here's the code for NSScreen to get the Display ID:

NSArray *screenArray = [NSScreen screens];
NSDictionary *screenDescription = [[screenArray objectAtIndex:0] deviceDescription];
NSLog(@"Device ID: %@", [screenDescription objectForKey:@"NSScreenNumber"]);

System Profiler, and Displays under System Preferences, reference displays by Display Name, not Display ID.

I'm asking as I want to run an AppleScript, and it requires a Display Name rather than a Display ID. Any help is MUCH appreciated! :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

谁的新欢旧爱 2024-08-06 04:59:37

这将为您提供本地化的显示名称:

static void KeyArrayCallback(const void* key, const void* value, void* context) { CFArrayAppendValue(context, key);  }

- (NSString*)localizedDisplayProductName
{
    NSDictionary* screenDictionary = [[NSScreen mainScreen] deviceDescription];
    NSNumber* screenID = [screenDictionary objectForKey:@"NSScreenNumber"];
    CGDirectDisplayID aID = [screenID unsignedIntValue];            
    CFStringRef localName = NULL;
    io_connect_t displayPort = CGDisplayIOServicePort(aID);
    CFDictionaryRef dict = (CFDictionaryRef)IODisplayCreateInfoDictionary(displayPort, 0);
    CFDictionaryRef names = CFDictionaryGetValue(dict, CFSTR(kDisplayProductName));
    if(names)
    {
        CFArrayRef langKeys = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
        CFDictionaryApplyFunction(names, KeyArrayCallback, (void*)langKeys);
        CFArrayRef orderLangKeys = CFBundleCopyPreferredLocalizationsFromArray(langKeys);
        CFRelease(langKeys);
        if(orderLangKeys && CFArrayGetCount(orderLangKeys))
        {
            CFStringRef langKey = CFArrayGetValueAtIndex(orderLangKeys, 0);
            localName = CFDictionaryGetValue(names, langKey);
            CFRetain(localName);
        }
        CFRelease(orderLangKeys);
    }
    CFRelease(dict);
    return [(NSString*)localName autorelease];
}

This gives you the localized display name:

static void KeyArrayCallback(const void* key, const void* value, void* context) { CFArrayAppendValue(context, key);  }

- (NSString*)localizedDisplayProductName
{
    NSDictionary* screenDictionary = [[NSScreen mainScreen] deviceDescription];
    NSNumber* screenID = [screenDictionary objectForKey:@"NSScreenNumber"];
    CGDirectDisplayID aID = [screenID unsignedIntValue];            
    CFStringRef localName = NULL;
    io_connect_t displayPort = CGDisplayIOServicePort(aID);
    CFDictionaryRef dict = (CFDictionaryRef)IODisplayCreateInfoDictionary(displayPort, 0);
    CFDictionaryRef names = CFDictionaryGetValue(dict, CFSTR(kDisplayProductName));
    if(names)
    {
        CFArrayRef langKeys = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
        CFDictionaryApplyFunction(names, KeyArrayCallback, (void*)langKeys);
        CFArrayRef orderLangKeys = CFBundleCopyPreferredLocalizationsFromArray(langKeys);
        CFRelease(langKeys);
        if(orderLangKeys && CFArrayGetCount(orderLangKeys))
        {
            CFStringRef langKey = CFArrayGetValueAtIndex(orderLangKeys, 0);
            localName = CFDictionaryGetValue(names, langKey);
            CFRetain(localName);
        }
        CFRelease(orderLangKeys);
    }
    CFRelease(dict);
    return [(NSString*)localName autorelease];
}
惜醉颜 2024-08-06 04:59:37

或者,如果您不想弄乱首选本地化数组,请将 kIODisplayOnlyPreferredName 标志传递给 IODisplayCreateInfoDictionary()

这是一个更少的 CoreFoundation、更多的 Cocoa 和稍微简化的代码,会做同样的事情:

#import <Foundation/Foundation.h>
#import <IOKit/graphics/IOGraphicsLib.h>

NSString* _Nullable ScreenNameForDisplay(CGDirectDisplayID displayID)
{
    NSString *screenName = nil;
    
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
    NSDictionary *deviceInfo = CFBridgingRelease(IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID), kIODisplayOnlyPreferredName));
#pragma clang diagnostic pop
    
    NSDictionary *localizedNames = deviceInfo[@(kDisplayProductName)];
    
    if (localizedNames.count > 0) {
        return localizedNames[localizedNames.allKeys[0]];
    }
    
    return nil;
}

int main(int argc, char *argv[])
{
    @autoreleasepool
    {
        NSLog(@"Main Display: %@", ScreenNameForDisplay(CGMainDisplayID()));
    }
}

注意:必须链接 CoreGraphics 框架 (-framework CoreGraphics)

Or if you don't want to mess with the preferred localization array, pass the kIODisplayOnlyPreferredName flag to IODisplayCreateInfoDictionary()

Here is a less CoreFoundation, more Cocoa and somewhat reduced code that will do the same thing:

#import <Foundation/Foundation.h>
#import <IOKit/graphics/IOGraphicsLib.h>

NSString* _Nullable ScreenNameForDisplay(CGDirectDisplayID displayID)
{
    NSString *screenName = nil;
    
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
    NSDictionary *deviceInfo = CFBridgingRelease(IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID), kIODisplayOnlyPreferredName));
#pragma clang diagnostic pop
    
    NSDictionary *localizedNames = deviceInfo[@(kDisplayProductName)];
    
    if (localizedNames.count > 0) {
        return localizedNames[localizedNames.allKeys[0]];
    }
    
    return nil;
}

int main(int argc, char *argv[])
{
    @autoreleasepool
    {
        NSLog(@"Main Display: %@", ScreenNameForDisplay(CGMainDisplayID()));
    }
}

Note: the CoreGraphics framework must be linked (-framework CoreGraphics)

丑丑阿 2024-08-06 04:59:37

分类规则z =)

NSArray *screens = [NSScreen screens];

for (NSScreen *screen in screens) {
    NSLog([NSString stringWithFormat:@"%@", [screen displayID]]);
    NSLog([NSString stringWithFormat:@"%@", [screen displayName]]);
}  

NSScreen+DisplayInfo.h

#import <Cocoa/Cocoa.h>

@interface NSScreen (DisplayInfo)

-(NSString*) displayName;
-(NSNumber*) displayID;

@end

NSScreen+DisplayInfo.m

#import "NSScreen+DisplayInfo.h"   
#import <IOKit/graphics/IOGraphicsLib.h>

@implementation NSScreen (DisplayInfo)

-(NSString*) displayName
{
    CGDirectDisplayID displayID = [[self displayID] intValue];

    NSString *screenName = nil;

    NSDictionary *deviceInfo = (NSDictionary *)CFBridgingRelease(IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID), kIODisplayOnlyPreferredName));
    NSDictionary *localizedNames = [deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];

    if ([localizedNames count] > 0) {
        screenName = [localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]];
    }

    return screenName;
}

-(NSNumber*) displayID
{
    return [[self deviceDescription] valueForKey:@"NSScreenNumber"];
}
@end

Categories rulez =)

NSArray *screens = [NSScreen screens];

for (NSScreen *screen in screens) {
    NSLog([NSString stringWithFormat:@"%@", [screen displayID]]);
    NSLog([NSString stringWithFormat:@"%@", [screen displayName]]);
}  

NSScreen+DisplayInfo.h

#import <Cocoa/Cocoa.h>

@interface NSScreen (DisplayInfo)

-(NSString*) displayName;
-(NSNumber*) displayID;

@end

NSScreen+DisplayInfo.m

#import "NSScreen+DisplayInfo.h"   
#import <IOKit/graphics/IOGraphicsLib.h>

@implementation NSScreen (DisplayInfo)

-(NSString*) displayName
{
    CGDirectDisplayID displayID = [[self displayID] intValue];

    NSString *screenName = nil;

    NSDictionary *deviceInfo = (NSDictionary *)CFBridgingRelease(IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID), kIODisplayOnlyPreferredName));
    NSDictionary *localizedNames = [deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];

    if ([localizedNames count] > 0) {
        screenName = [localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]];
    }

    return screenName;
}

-(NSNumber*) displayID
{
    return [[self deviceDescription] valueForKey:@"NSScreenNumber"];
}
@end
捂风挽笑 2024-08-06 04:59:37

这是一个将其组合在一起的完整应用程序(http://cl.ly/40Hw):

/* 
 DisplayID.m
 Author: Robert Harder, [email protected]
 with help from http://stackoverflow.com/questions/1236498/how-to-get-the-display-name-with-the-display-id-in-mac-os-x

 Returns a list of display names and display IDs.
 Add the flag -v for more information on the screens.

 Compile from the command line:
   cc DisplayID.m -o DisplayID \
     -framework AppKit -framework Foundation -framework IOKit \
     -arch x86_64 -arch i386 -arch ppc7400

 Examples:

   $ DisplayID
   Color LCD : 69675202

   $ DisplayID -v
   Color LCD : 69675202
   {
       NSDeviceBitsPerSample = 8;
       NSDeviceColorSpaceName = NSCalibratedRGBColorSpace;
       NSDeviceIsScreen = YES;
       NSDeviceResolution = "NSSize: {72, 72}";
       NSDeviceSize = "NSSize: {1440, 900}";
       NSScreenNumber = 69675202;
   }
 */

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <IOKit/graphics/IOGraphicsLib.h>

#define str_eq(s1,s2)  (!strcmp ((s1),(s2)))

NSString* screenNameForDisplay(CGDirectDisplayID displayID )
{
    NSString *screenName = nil;

    NSDictionary *deviceInfo = (NSDictionary *)IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID), kIODisplayOnlyPreferredName);
    NSDictionary *localizedNames = [deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];

    if ([localizedNames count] > 0) {
        screenName = [[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] retain];
    }

    [deviceInfo release];
    return [screenName autorelease];
}


int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    BOOL verbose = NO;
    BOOL extraVerbose = NO;

    if( argc >= 2 ){
        if( str_eq( "-v",argv[1]) ){
            verbose = YES;
        } else if( str_eq( "-vv", argv[1] ) ){
            verbose = YES;
            extraVerbose = YES;
        } else {
            printf("USAGE: %s [-v[v]]\n", argv[0]);
            printf("Prints a list of names and numeric IDs for attached displays.\n");
            printf("  -v    Verbose mode. Prints more information about each display.\n");
            printf("  -vv   Extra verbose. Prints even more information.\n");
            return argc;
        }
    }

    NSArray *screenArray = [NSScreen screens];
    for( NSScreen *screen in screenArray ){

        NSDictionary *screenDescription = [screen deviceDescription];

        NSNumber *displayID = [screenDescription objectForKey:@"NSScreenNumber"];
        NSString *displayName =screenNameForDisplay([displayID intValue]);


        printf( "%s : %d\n", [displayName UTF8String], [displayID intValue]);       
        if( verbose ){
            printf( "%s\n", [[screenDescription description] UTF8String] );         
        }
        if( extraVerbose ){ 
            NSDictionary *deviceInfo = (NSDictionary *)IODisplayCreateInfoDictionary(CGDisplayIOServicePort([displayID intValue]), kIODisplayOnlyPreferredName);
            printf( "%s\n", [[deviceInfo description] UTF8String] );
        }

    }   // end for:


    [pool drain];
    return 0;
}

And here's a whole app that puts it together (http://cl.ly/40Hw):

/* 
 DisplayID.m
 Author: Robert Harder, [email protected]
 with help from http://stackoverflow.com/questions/1236498/how-to-get-the-display-name-with-the-display-id-in-mac-os-x

 Returns a list of display names and display IDs.
 Add the flag -v for more information on the screens.

 Compile from the command line:
   cc DisplayID.m -o DisplayID \
     -framework AppKit -framework Foundation -framework IOKit \
     -arch x86_64 -arch i386 -arch ppc7400

 Examples:

   $ DisplayID
   Color LCD : 69675202

   $ DisplayID -v
   Color LCD : 69675202
   {
       NSDeviceBitsPerSample = 8;
       NSDeviceColorSpaceName = NSCalibratedRGBColorSpace;
       NSDeviceIsScreen = YES;
       NSDeviceResolution = "NSSize: {72, 72}";
       NSDeviceSize = "NSSize: {1440, 900}";
       NSScreenNumber = 69675202;
   }
 */

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <IOKit/graphics/IOGraphicsLib.h>

#define str_eq(s1,s2)  (!strcmp ((s1),(s2)))

NSString* screenNameForDisplay(CGDirectDisplayID displayID )
{
    NSString *screenName = nil;

    NSDictionary *deviceInfo = (NSDictionary *)IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID), kIODisplayOnlyPreferredName);
    NSDictionary *localizedNames = [deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];

    if ([localizedNames count] > 0) {
        screenName = [[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] retain];
    }

    [deviceInfo release];
    return [screenName autorelease];
}


int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    BOOL verbose = NO;
    BOOL extraVerbose = NO;

    if( argc >= 2 ){
        if( str_eq( "-v",argv[1]) ){
            verbose = YES;
        } else if( str_eq( "-vv", argv[1] ) ){
            verbose = YES;
            extraVerbose = YES;
        } else {
            printf("USAGE: %s [-v[v]]\n", argv[0]);
            printf("Prints a list of names and numeric IDs for attached displays.\n");
            printf("  -v    Verbose mode. Prints more information about each display.\n");
            printf("  -vv   Extra verbose. Prints even more information.\n");
            return argc;
        }
    }

    NSArray *screenArray = [NSScreen screens];
    for( NSScreen *screen in screenArray ){

        NSDictionary *screenDescription = [screen deviceDescription];

        NSNumber *displayID = [screenDescription objectForKey:@"NSScreenNumber"];
        NSString *displayName =screenNameForDisplay([displayID intValue]);


        printf( "%s : %d\n", [displayName UTF8String], [displayID intValue]);       
        if( verbose ){
            printf( "%s\n", [[screenDescription description] UTF8String] );         
        }
        if( extraVerbose ){ 
            NSDictionary *deviceInfo = (NSDictionary *)IODisplayCreateInfoDictionary(CGDisplayIOServicePort([displayID intValue]), kIODisplayOnlyPreferredName);
            printf( "%s\n", [[deviceInfo description] UTF8String] );
        }

    }   // end for:


    [pool drain];
    return 0;
}
朮生 2024-08-06 04:59:37

其他答案使用 CGDisplayIOServicePort 其中已被弃用。

从 macOS 10.15 开始 -[NSScreen localizedName]可用:

NSLog(@"Name of main display is %@", NSScreen.mainScreen.localizedName);

对于显示 ID,您仍然可以使用 -[NSScreen deviceDescription]

NSLog(@"The ID of the main display is %@", NSScreen.mainScreen.deviceDescription[@"NSScreenNumber"]);

Other answers use CGDisplayIOServicePort which was deprecated.

As of macOS 10.15 -[NSScreen localizedName] is available:

NSLog(@"Name of main display is %@", NSScreen.mainScreen.localizedName);

For the display ID you can still use -[NSScreen deviceDescription]:

NSLog(@"The ID of the main display is %@", NSScreen.mainScreen.deviceDescription[@"NSScreenNumber"]);
败给现实 2024-08-06 04:59:37

我使用 Robert Harder 的实现在 github.com 上创建了一个示例项目
@robert-harder 感谢您提供这个想法!

I created an example project on github.com using the implementation of Robert Harder.
@robert-harder Thank you for providing the idea!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文