可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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: