高度な検索
Developer Connection
Member Login ログイン | ご入会 ADC連絡先

Technical Q&A QA1217
How can I programmatically determine the DPI of the current video mode?


Q: 現在のビデオモードの DPI(1 インチあたりのドット数)をプログラムで判断するには、どうすればよいでしょうか?

A: ビデオモードの DPI を返すための単独の API はありませんが、IOKit および Core Graphics から必要な情報を得ることができます。IOKit では、モニタの物理的なサイズをミリメートル単位で確認できます。一方、Core Graphics (CG) では、現在のディスプレイ解像度がわかります。リスト 1 に、任意のモニタにおける任意のディスプレイモードの DPI を返す関数を示します。リスト 2 には、現在のディスプレイモードでメインモニタの水平および垂直 DPI を判断するための関数の使用方法を示します。



// CFDictionaryRef から int を取得する簡易関数
static int GetIntFromDictionaryForKey( CFDictionaryRef desc, CFStringRef key )
{
    CFNumberRef value;
    int num = 0;
    if ( (value = CFDictionaryGetValue(desc, key)) == NULL
            || CFGetTypeID(value) != CFNumberGetTypeID())
        return 0;
    CFNumberGetValue(value, kCFNumberIntType, &num);
    return num;
}

CGDisplayErr GetDisplayDPI(
    CFDictionaryRef displayModeDict,
    CGDirectDisplayID displayID,
    double *horizontalDPI, double *verticalDPI )
{
    CGDisplayErr err = kCGErrorFailure;
    io_connect_t displayPort;
    CFDictionaryRef displayDict;

    // 要求されたディスプレイのために IOKit へ接続情報を取り込む
    displayPort = CGDisplayIOServicePort( displayID );
    if ( displayPort != MACH_PORT_NULL )
    {
        // このディスプレイについて IOKit が持っている情報を調る
        displayDict = IOCreateDisplayInfoDictionary(displayPort, 0);
        if ( displayDict != NULL )
        {
            const double mmPerInch = 25.4;
            double horizontalSizeInInches =
                (double)GetIntFromDictionaryForKey(displayDict,
                        CFSTR(kDisplayHorizontalImageSize)) / mmPerInch;
            double verticalSizeInInches =
                (double)GetIntFromDictionaryForKey(displayDict,
                        CFSTR(kDisplayVerticalImageSize)) / mmPerInch;

            // IOKit から取得したディクショナリを必ず解放すること
            CFRelease(displayDict);

            // これで、displayModeDict からの情報を使用
            // して、実際の DPI を計算することができる
            *horizontalDPI =
                (double)GetIntFromDictionaryForKey( displayModeDict, kCGDisplayWidth )
                    / horizontalSizeInInches;
            *verticalDPI = (double)GetIntFromDictionaryForKey( displayModeDict,
                    kCGDisplayHeight ) / verticalSizeInInches;
            err = CGDisplayNoErr;
        }
    }
    return err;
}

リスト 1. スクリーン DPI の算出





double horizontalDPI, verticalDPI;
CGDisplayErr err = GetDisplayDPI( CGDisplayCurrentMode(kCGDirectMainDisplay),
                kCGDirectMainDisplay,
                &horizontalDPI, &verticalDPI );
if ( err == CGDisplayNoErr )
{
    // horizontalDPI と verticalDPI で何かする
}

リスト 2. 典型的な使用法




[2002 年 12 月 2 日]