Excelは、「画面に表示されているように」範囲をコピーするときに生成するメタファイルの解像度をどのように計算しますか?

StackOverflow https://stackoverflow.com/questions/8317313

  •  25-10-2019
  •  | 
  •  

質問

私は得たC#コードをいくつか持っています http://bytes.com/topic/c-sharp/answers/572657-net-clipboard-metafiles これは、次の2つの設定の下でセルの範囲をコピーします。

  • 画面に示されているように、
  • 印刷したときに示されているように.

結果のメタファイルの解像度を見ると( Gets the resolution, in pixels-per-inch, of this Image object)、コピー方法に応じて異なる値を取得します。

  • とともに 印刷したときに示されているように オプション、解像度は600です。これは、ExcelにあるDPI設定に対応していると思います。

  • とともに 画面に示されているように 設定、それはようなものを吐き出します Metafile.VerticalResolution = 72.08107Metafile.HorizontalResolution = 71.95952. 。他のマシンでは、この値が大きく異なることがわかりました(111、130程度など)。

ズームレベルはこれに影響しないようです。私が観察したことから、値は単一のマシンで一貫していますが、マシンごとに異なる場合があります。

メタファイルの解像度を計算するときに、誰もが続くロジックExcelを説明できますか 画面に示されているように モード?

Windowsの解像度を変更し、メタファイルの解像度を測定した後、ここに私が生成したテーブルがあります(正しくフォーマットされているように見えることを願っています):

Width   Height  HorizontalResolution    VerticalResolution
1680    1050        71.95952                72.08107
1600    1024        72.05672                72.04874
1600    900         72.05672                71.88678
1360    768         71.96666                71.98228
1280    1024        71.9292                 72.04874
1280    960         71.9292                 71.9292
1280    800         71.9292                 72.05672
1280    768         71.9292                 71.98228
1280    720         71.9292                 71.99999
1152    864         72.07093                71.95278
1088    612         71.96666                71.96666
1024    768         72.04874                71.98228
960     600         71.9292                 71.88678
800     600         72.05672                71.88678

仮想マシン(同じ物理マシン)で同様の手順を実行した後、これらは結果です。物理マシン自体よりも少し揮発性があります。このデータは役に立たないかもしれませんが、とにかくそれを提供すると思いました。

Width   Height  HorizontalResolution    VerticalResolution
1680    1050    133.35                  111.125
1280    800     101.6                   84.66666
1024    768     81.27999                81.27999
800     600     63.5                    63.5
役に立ちましたか?

解決

私の仮説

これは、LCDモニターで非ネイティブの解像度を実行することに関係していると思います。 「The Old Days」では、CRTSにはネイティブの解決自体がありませんでした。したがって、コンピューターは、特定のモニターサイズまたはアスペクト比の好ましい解像度を認識していませんでした。新しいデジタルディスプレイ(LCD)を使用すると、コンピューターは、適切にインストールされている場合、ディスプレイの優先解像度とアスペクト比を認識しています。私のWindows 7マシンは、LCDのネイティブ解像度の横に「推奨」を示し、その後、他の2つの等しいアスペクト比の解像度を黒で示し、残りの「ミスマッチ」は無効ですが選択可能です(私が見るのが嫌いまたは伸びた外観になります。他の人々のコンピューターで!)。

Windowsの96と120のデフォルトのDPIは、CRT日に確立されました。私のWindows 7マシンは、「小さい」、「中」、「大きい」と言っているだけではありません。

いずれにせよ、1920x1080または1920x1200と言われているLCDモニターを購入すると、ディスプレイ解像度を小さいものに設定すると、変換係数が得られます。 72に近い非一致の水平および垂直解像度の場合、あなたの非ネイティブディスプレイ解像度は、この小さな矛盾をもたらす水平になっているのとまったく同じスケーリング係数ではない場合があります。

私の仮説をテストする方法

各テストマシンでは、オペレーティングシステムが構成された解像度を記録し、ネイティブ解像度を表示します。これら2つの比率が、96または120DPIのいずれかのメタファイルの比率に近いかどうかを確認してください。リモートデスクトップまたは仮想マシンドライバーでさらにスケーリングする可能性を排除するために、物理マシンでこのテストを実施することをお勧めします。

ソリューションがすぐに明らかにならない場合は、さらに一歩進んで、DPIまたは「小さい」、「中」、「大きい」の動作およびコントロールパネル設定を記録します。 Windows XPは、Windows Vista/Windows 7とは異なる動作をする場合があります。

また、同じ物理マシンでテストを数回再実行して、テスト間で構成されたディスプレイ解像度を調整し、変更を観察することもできます。私の仮説が正しい場合は、同じ物理マシン/ディスプレイの組み合わせで構成されたディスプレイ解像度ごとに異なるメタファイル解像度が表示され、この結果は予測可能で再現可能です(最初の解像度に戻ると同じメタファイル解像度に戻る必要があります)

編集#1

物理DPIと論理DPIについて説明する優れた記事を見つけました。これを読んでください: 96 DPIはWindowsのどこから来たのですか?

だから今、私がお勧めする次のテストはディスプレイを変更することです!テストに利用できる別のブランド/サイズ/解像度LCDモニターがありますか?さまざまな解像度を確立したため、上記の最初のテストほど多くの行は必要ありません。ディスプレイのネイティブ解像度や1024x768など、比較のための「ベースライン」として1024x768を含むいくつかの一般的な解像度をテストするだけです。

また、Windows 7で回転している間、「Windows XPスタイルのDPIスケーリングを使用する」オプションを含むコントロールパネルに「カスタムテキストサイズ(DPI)セット」リンクが見つかりました。これが主な関心事ではないと思いますが、好奇心はその効果に興味を持っているので、言及したと思いました。

編集#2-解決しました!

メタファイルに表示されている解像度は、モニターの物理的なDPIです。あなたが自分自身をテストするために、ここにいくつかのC#コードを投稿してください:

[DllImport("user32.dll")]
static extern IntPtr GetDC(IntPtr hWnd);

[DllImport("user32.dll")]
static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);

[DllImport("gdi32.dll")]
static extern int GetDeviceCaps(IntPtr hdc, int nIndex);

public enum DeviceCap
{
    /// <summary>
    /// Device driver version
    /// </summary>
    DRIVERVERSION = 0,
    /// <summary>
    /// Device classification
    /// </summary>
    TECHNOLOGY = 2,
    /// <summary>
    /// Horizontal size in millimeters
    /// </summary>
    HORZSIZE = 4,
    /// <summary>
    /// Vertical size in millimeters
    /// </summary>
    VERTSIZE = 6,
    /// <summary>
    /// Horizontal width in pixels
    /// </summary>
    HORZRES = 8,
    /// <summary>
    /// Vertical height in pixels
    /// </summary>
    VERTRES = 10,
    /// <summary>
    /// Number of bits per pixel
    /// </summary>
    BITSPIXEL = 12,
    /// <summary>
    /// Number of planes
    /// </summary>
    PLANES = 14,
    /// <summary>
    /// Number of brushes the device has
    /// </summary>
    NUMBRUSHES = 16,
    /// <summary>
    /// Number of pens the device has
    /// </summary>
    NUMPENS = 18,
    /// <summary>
    /// Number of markers the device has
    /// </summary>
    NUMMARKERS = 20,
    /// <summary>
    /// Number of fonts the device has
    /// </summary>
    NUMFONTS = 22,
    /// <summary>
    /// Number of colors the device supports
    /// </summary>
    NUMCOLORS = 24,
    /// <summary>
    /// Size required for device descriptor
    /// </summary>
    PDEVICESIZE = 26,
    /// <summary>
    /// Curve capabilities
    /// </summary>
    CURVECAPS = 28,
    /// <summary>
    /// Line capabilities
    /// </summary>
    LINECAPS = 30,
    /// <summary>
    /// Polygonal capabilities
    /// </summary>
    POLYGONALCAPS = 32,
    /// <summary>
    /// Text capabilities
    /// </summary>
    TEXTCAPS = 34,
    /// <summary>
    /// Clipping capabilities
    /// </summary>
    CLIPCAPS = 36,
    /// <summary>
    /// Bitblt capabilities
    /// </summary>
    RASTERCAPS = 38,
    /// <summary>
    /// Length of the X leg
    /// </summary>
    ASPECTX = 40,
    /// <summary>
    /// Length of the Y leg
    /// </summary>
    ASPECTY = 42,
    /// <summary>
    /// Length of the hypotenuse
    /// </summary>
    ASPECTXY = 44,
    /// <summary>
    /// Shading and Blending caps
    /// </summary>
    SHADEBLENDCAPS = 45,

    /// <summary>
    /// Logical pixels inch in X
    /// </summary>
    LOGPIXELSX = 88,
    /// <summary>
    /// Logical pixels inch in Y
    /// </summary>
    LOGPIXELSY = 90,

    /// <summary>
    /// Number of entries in physical palette
    /// </summary>
    SIZEPALETTE = 104,
    /// <summary>
    /// Number of reserved entries in palette
    /// </summary>
    NUMRESERVED = 106,
    /// <summary>
    /// Actual color resolution
    /// </summary>
    COLORRES = 108,

    // Printing related DeviceCaps. These replace the appropriate Escapes
    /// <summary>
    /// Physical Width in device units
    /// </summary>
    PHYSICALWIDTH = 110,
    /// <summary>
    /// Physical Height in device units
    /// </summary>
    PHYSICALHEIGHT = 111,
    /// <summary>
    /// Physical Printable Area x margin
    /// </summary>
    PHYSICALOFFSETX = 112,
    /// <summary>
    /// Physical Printable Area y margin
    /// </summary>
    PHYSICALOFFSETY = 113,
    /// <summary>
    /// Scaling factor x
    /// </summary>
    SCALINGFACTORX = 114,
    /// <summary>
    /// Scaling factor y
    /// </summary>
    SCALINGFACTORY = 115,

    /// <summary>
    /// Current vertical refresh rate of the display device (for displays only) in Hz
    /// </summary>
    VREFRESH = 116,
    /// <summary>
    /// Horizontal width of entire desktop in pixels
    /// </summary>
    DESKTOPVERTRES = 117,
    /// <summary>
    /// Vertical height of entire desktop in pixels
    /// </summary>
    DESKTOPHORZRES = 118,
    /// <summary>
    /// Preferred blt alignment
    /// </summary>
    BLTALIGNMENT = 119
}

private void GetScreenInfo()
{
    IntPtr sdc = IntPtr.Zero;
    try
    {
        //Get the Screen Device Context
        sdc = GetDC(IntPtr.Zero);

        // Get the Screen Devive Context Capabilities Information
        Console.WriteLine(string.Format("Size: {0} mm X {1} mm", GetDeviceCaps(sdc, (int)DeviceCap.HORZSIZE), GetDeviceCaps(sdc, (int)DeviceCap.VERTSIZE)));
        Console.WriteLine(string.Format("Desktop Resolution: {0}x{1}", GetDeviceCaps(sdc, (int)DeviceCap.DESKTOPHORZRES), GetDeviceCaps(sdc, (int)DeviceCap.DESKTOPVERTRES)));
        Console.WriteLine(string.Format("Logical DPI: {0}x{1}", GetDeviceCaps(sdc, (int)DeviceCap.LOGPIXELSX), GetDeviceCaps(sdc, (int)DeviceCap.LOGPIXELSY)));

        //Remember: Convert Millimeters to Inches 25.4mm = 1 inch
        double PhsyicalDPI_X = GetDeviceCaps(sdc, (int)DeviceCap.DESKTOPHORZRES) * 25.4 / GetDeviceCaps(sdc, (int)DeviceCap.HORZSIZE);
        double PhsyicalDPI_Y = GetDeviceCaps(sdc, (int)DeviceCap.DESKTOPVERTRES) * 25.4 / GetDeviceCaps(sdc, (int)DeviceCap.VERTSIZE);
        Console.WriteLine(string.Format("Physical DPI: {0}x{1}", PhsyicalDPI_X, PhsyicalDPI_Y));

    }
    finally
    {
        ReleaseDC(IntPtr.Zero, sdc);
    }
}

私のディスプレイ上のこのコードは、次のものを出力します:

  • サイズ:677 mm x 381 mm
  • デスクトップ解像度:1920x1080
  • 論理DPI:96x96
  • 物理DPI:72.0354505169867x72

論理的および物理的なDPIの両方に気付きますか?その物理的なDPIはおなじみに見えますか? 1pt = 1pxを反映して72dpiについてその記事を読んだ後、それはすべて理にかなっています。このコードをさまざまなテストマシンで試してみて、どうなるか教えてください! (参考までに、私はこのコードをC#Winformsアプリ、コンソールアプリで実行しました したほうがいい 画面デバイスのコンテキストを取得できるが、多分そうではない...)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top