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).
我想知道你能不能帮我弄明白如何通过使用Mac OS X(10.5)中的显示ID号来获得显示器的显示名?一个要求是如果我给一个函数显示ID,它将返回显示名(反之亦然)。
Display Name looks something like this: "Color LCD", "SAMSUNG"
显示名称如下:“彩色LCD”、“三星”
Display ID looks something like this: "69671872", "893830283"
显示ID如下:“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:
Cocoa中的NSScreen (object -C)或Quartz中的CGGetActiveDisplayList (C)允许您获取监视器的显示ID号。两者似乎都没有获取显示名称的方法。噢,不!以下是NSScreen获取显示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.
系统分析器,并在系统首选项下显示,以显示名显示引用显示,而不是显示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! :)
我在询问,因为我想运行一个AppleScript,它需要一个显示名而不是显示ID。非常感谢您的帮助!:)
5 个解决方案
#1
17
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
13
Or if you don't want to mess with the preferred localization array, pass the kIODisplayOnlyPreferredName
flag to IODisplayCreateInfoDictionary()
如果不想打乱首选的本地化数组,则将kiodisplayonlyredname标志传递给IODisplayCreateInfoDictionary()
Here is a less CoreFoundation, more Cocoa and somewhat reduced code that will do the same thing:
这里有更少的CoreFoundation,更多的Cocoa和更少的代码可以做同样的事情:
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
6
And here's a whole app that puts it together (http://cl.ly/40Hw):
这里有一个完整的应用程序将它放在一起(http://cl.ly/40Hw):
/*
DisplayID.m
Author: Robert Harder, rob@iHarder.net
with help from http://*.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;
}
#4
5
Categories rulez =)
类别rulez =)
NSArray *screens = [NSScreen screens];
for (NSScreen *screen in screens) {
NSLog([NSString stringWithFormat:@"%@", [screen displayID]]);
NSLog([NSString stringWithFormat:@"%@", [screen displayName]]);
}
NSScreen+DisplayInfo.h
NSScreen + DisplayInfo.h
#import <Cocoa/Cocoa.h>
@interface NSScreen (DisplayInfo)
-(NSString*) displayName;
-(NSNumber*) displayID;
@end
NSScreen+DisplayInfo.m
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
#5
1
I created an example project on github.com using the implementation of Robert Harder.
@robert-harder Thank you for providing the idea!
我使用Robert hard的实现在github.com上创建了一个示例项目。@robert-hard感谢你提供了这个想法!
#1
17
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
13
Or if you don't want to mess with the preferred localization array, pass the kIODisplayOnlyPreferredName
flag to IODisplayCreateInfoDictionary()
如果不想打乱首选的本地化数组,则将kiodisplayonlyredname标志传递给IODisplayCreateInfoDictionary()
Here is a less CoreFoundation, more Cocoa and somewhat reduced code that will do the same thing:
这里有更少的CoreFoundation,更多的Cocoa和更少的代码可以做同样的事情:
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
6
And here's a whole app that puts it together (http://cl.ly/40Hw):
这里有一个完整的应用程序将它放在一起(http://cl.ly/40Hw):
/*
DisplayID.m
Author: Robert Harder, rob@iHarder.net
with help from http://*.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;
}
#4
5
Categories rulez =)
类别rulez =)
NSArray *screens = [NSScreen screens];
for (NSScreen *screen in screens) {
NSLog([NSString stringWithFormat:@"%@", [screen displayID]]);
NSLog([NSString stringWithFormat:@"%@", [screen displayName]]);
}
NSScreen+DisplayInfo.h
NSScreen + DisplayInfo.h
#import <Cocoa/Cocoa.h>
@interface NSScreen (DisplayInfo)
-(NSString*) displayName;
-(NSNumber*) displayID;
@end
NSScreen+DisplayInfo.m
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
#5
1
I created an example project on github.com using the implementation of Robert Harder.
@robert-harder Thank you for providing the idea!
我使用Robert hard的实现在github.com上创建了一个示例项目。@robert-hard感谢你提供了这个想法!