私の仮説
これは、LCD モニターで非ネイティブ解像度を実行することに関係していると思います。「昔」では、CRT 自体にはネイティブ解像度がありませんでした。そのため、コンピューターは、特定のモニター サイズまたはアスペクト比に適した解像度を認識していませんでした。新しいデジタル ディスプレイ (LCD) では、適切に取り付けられていれば、コンピューターはディスプレイの優先解像度と縦横比を認識するようになりました。Windows 7 マシンでは、LCD のネイティブ解像度の横に「推奨」と表示され、残りの「不一致」はラベル付けされていませんが選択可能であり、残りの 2 つの等しい縦横比の解像度が黒で表示されます (その結果、見たくない押しつぶされたまたは引き伸ばされた外観になります)。他の人のコンピュータで!)。
Windows のデフォルトの DPI である 96 と 120 は、CRT の時代に確立されました。私の Windows 7 マシンは DPI を表示しなくなり、「小」、「中」、「大」とだけ表示されます。
いずれにせよ、1920x1080 や 1920x1200 などの LCD モニターを購入し、ディスプレイの解像度をそれより小さいものに設定すると、変換係数が発生します。水平方向と垂直方向の解像度が 72 に近く一致しない場合、非ネイティブのディスプレイ解像度は、水平方向と垂直方向のスケーリング係数がまったく同じではない可能性があり、結果としてこの小さな不一致が生じます。
私の仮説を検証する方法
各テスト マシンで、オペレーティング システムで構成された解像度とディスプレイのネイティブ解像度を記録します。これら 2 つの比率が、メタファイルの「画面上」と 96 または 120 dpi の比率に近いかどうかを確認します。このテストは物理マシンで実施して、リモート デスクトップまたは仮想マシン ドライバーでさらにスケーリングする可能性を除外することをお勧めします。
解決策がすぐにわからない場合は、さらに一歩進んで、DPI または「小」、「中」、「大」の操作パネルとコントロール パネルの設定を記録します。Windows XP は、Windows Vista/Windows 7 とは動作が異なる場合があります。
同じ物理マシンでテストを数回再実行して、テスト間で構成されたディスプレイ解像度を調整し、変更を観察することもできます。私の仮説が正しければ、同じ物理マシン/ディスプレイの組み合わせで構成されたディスプレイ解像度ごとに異なるメタファイル解像度が表示され、この結果は予測可能で再現可能であるはずです (最初の解像度に戻ると、同じメタファイル解像度に戻るはずです)。
編集#1
物理 DPI と論理 DPI について説明している優れた記事を見つけました。これを読んでください: 96 DPI は Windows のどこから来たのですか?
そこで、次にお勧めするテストは、ディスプレイの変更です。テスト用に別のブランド/サイズ/解像度の LCD モニターを利用できますか? さまざまな解像度が同じディスプレイに対して非常に類似した DPI を生成する傾向があることを確立したため、上記の最初のテストほど多くの行は必要ありません。ディスプレイのネイティブ解像度と、比較のための「ベースライン」としての 1024x768 を含む、いくつかの一般的な解像度をテストしてください。
また、Windows 7 をいじっているときに、コントロール パネルの [カスタム テキスト サイズ (DPI) の設定] リンクを見つけました - >ディスプレイには、[Windows XP スタイルの 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);
}
}
私のディスプレイ上のこのコードは、次を出力します。
- サイズ:677mm×381mm
- デスクトップの解像度: 1920x1080
- 論理 DPI: 96x96
- 物理 DPI: 72.0354505169867x72
論理 DPI と物理 DPI の両方に注目してください。その物理 DPI は見覚えがありますか? 1pt=1px を反映する 72dpi に関する記事を読んだ後、すべてが理にかなっています。このコードをさまざまなテスト マシンで試してみて、どうなるか教えてください。(参考までに、私はこのコードを C# winforms アプリで実行しました。コンソール アプリは画面デバイス コンテキストを取得できるはずですが、そうでない可能性があります...)