Как получить отображаемое имя с отображаемым идентификатором в Mac OS X? - PullRequest
15 голосов
/ 06 августа 2009

Мне было интересно, не могли бы вы помочь мне понять, как программно получить Отображаемое имя для монитора, используя его Отображаемый идентификатор номер в Mac OS X (10.5)? Требование заключается в том, что если я назначу функции идентификатор дисплея, она предоставит отображаемое имя взамен (или наоборот).

Отображаемое имя выглядит примерно так: «Цветной ЖК-дисплей», «SAMSUNG»

Идентификатор дисплея выглядит примерно так: «69671872», «893830283»

NSScreen в Какао (Obj-C) или CGGetActiveDisplayList в Кварце (C), позволяют получить идентификационный номер дисплея для монитора. Ни один из них не имеет метода для получения отображаемого имени. о нет! Вот код NSScreen для получения идентификатора дисплея:

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

System Profiler и Отображает в Системные настройки , ссылки отображаются по отображаемому имени, а не по идентификатору дисплея.

Я спрашиваю, так как хочу запустить AppleScript, и для него требуется отображаемое имя, а не идентификатор дисплея. Любая помощь высоко ценится! :)

Ответы [ 5 ]

17 голосов
/ 06 августа 2009

Это дает вам локализованное отображаемое имя:

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];
}
13 голосов
/ 07 августа 2009

Или, если вы не хотите связываться с предпочтительным массивом локализации, передайте флаг kIODisplayOnlyPreferredName в IODisplayCreateInfoDictionary()

Вот меньше CoreFoundation, больше Какао и несколько сокращенный код, который будет делать то же самое:

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];
}
6 голосов
/ 13 января 2011

А вот и целое приложение, которое объединяет его (http://cl.ly/40Hw):

/* 
 DisplayID.m
 Author: Robert Harder, rob@iHarder.net
 with help from /1163568/kak-poluchit-otobrazhaemoe-imya-s-otobrazhaemym-identifikatorom-v-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;
}
5 голосов
/ 25 августа 2013

Категории 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
1 голос
/ 22 июня 2011

Я создал пример проекта на github.com, используя реализацию Роберта Хардера .
@ robert-harder Спасибо за идею!

...