How to Get the Display Name with the Display ID in Mac OS X?

匿名 (未验证) 提交于 2019-12-03 00:57:01

问题:

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! :)

回答1:

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]; } 


回答2:

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:

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]; } 


回答3:

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

/*   DisplayID.m  Author: Robert Harder, rob@iHarder.net  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  #import  #import   #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; } 


回答4:

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   @interface NSScreen (DisplayInfo)  -(NSString*) displayName; -(NSNumber*) displayID;  @end 

NSScreen+DisplayInfo.m

#import "NSScreen+DisplayInfo.h"    #import   @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 


回答5:

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



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!