Wie berechnet Excel die Auflösung der Metafiles, die er erzeugt, wenn ein Bereich „wie auf dem Bildschirm gezeigt“ kopiert?
Frage
Ich habe einen C# Code, von dem ich bekommen habe http://bytes.com/topic/c-sharp/answers/572657-net-clipboard-metafiles Das kopiert einen Zellbereich unter den folgenden zwei Einstellungen:
- Wie auf dem Bildschirm gezeigt,
- Wie beim Druck gezeigt.
Wenn ich mir die resultierende Auflösung von Metafile anschaue (die als dokumentiert ist wie Gets the resolution, in pixels-per-inch, of this Image object
), Ich erhalte je nach Kopiermethode unterschiedliche Werte.
Mit dem Wie beim Druck gezeigt Option, die Auflösung beträgt 600, was meiner Meinung nach den DPI -Einstellungen entspricht, die ich in Excel habe.
Mit dem Wie auf dem Bildschirm gezeigt Einstellung spuckt so etwas wie aus
Metafile.VerticalResolution = 72.08107
undMetafile.HorizontalResolution = 71.95952
. Bei anderen Maschinen habe ich gesehen, dass dieser Wert stark variiert (Werte um 111, 130 usw.).
Das Zoom -Level scheint dies nicht zu beeinflussen. Nach dem, was ich beobachtet habe, bleiben die Werte auf einer einzelnen Maschine konsistent, können sich jedoch von Maschine zu Maschine unterscheiden.
Kann jemand die logische Excel erklären, die bei der Berechnung der Auflösung des Metafiles in folgt Wie auf dem Bildschirm gezeigt Modus?
Nachdem ich die Windows -Auflösung geändert und die metafilen Auflösungen gemessen hatte, ist hier die Tabelle, die ich generiert habe (hoffe, sie sieht richtig formatiert aus):
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
Nach einem ähnlichen Verfahren auf einer virtuellen Maschine (gleiche physische Maschine) sind dies die Ergebnisse. Etwas volatiler als die physische Maschine selbst. Diese Daten sind vielleicht nicht nützlich, aber ich dachte, ich würde sie sowieso bereitstellen.
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
Lösung
Meine Hypothese
Ich glaube, dies hat damit zu tun, dass eine nicht einheimische Auflösung auf einem LCD-Monitor durchgeführt wird. In "The Old Days" hatte CRTS keine native Auflösung an sich. Daher war der Computer keine bevorzugte Auflösung für eine bestimmte Überwachungsgröße oder ein Seitenverhältnis. Mit neueren digitalen Displays (LCD) ist der Computer nun die bevorzugte Auflösung und das Seitenverhältnis für Ihr Display kennen, wenn sie ordnungsgemäß installiert sind. Meine Windows 7 -Maschine zeigt "Empfohlen" neben der nativen Auflösung meines LCD und zeigt dann die anderen 2 -gleichgeeigneten Auflösungen in Schwarz, wobei die verbleibenden "Fehlanpassungen" unbeschreiblich, aber wählbar sind (was zu dem zerquetschten oder gestreckten Look führt, den ich hasse zu sehen hasse es zu sehen auf anderen Völkern Computer!).
Die Standard -DPIs von 96 und 120 in Fenstern wurden in den CRT -Tagen festgelegt. Meine Windows 7 -Maschine sagt nicht einmal mehr DPI. Es heißt nur "kleiner", "mittel", "größer".
In jedem Fall, wenn Sie einen LCD -Monitor kaufen, der 1920x1080 oder 1920x1200 heißt, die Anzeigeauflösung jedoch auf etwas kleineres festlegen, führen Sie zu einem Conversion -Faktor. Bei den nicht passenden horizontalen und vertikalen Auflösungen in der Nähe von 72 ist Ihre nicht einheimische Anzeigeauflösung möglicherweise nicht genau der gleiche Skalierungsfaktor vertikal, wie sie horizontal zu dieser geringen Diskrepanz führt.
Wie man meine Hypothese testet
Auf jedem Ihrer Testmaschinen zeichnen Sie die konfigurierte Auflösung der Betriebssysteme und die native Auflösung anzeigen. Sehen Sie, ob das Verhältnis zwischen diesen beiden nahe am Verhältnis zwischen Ihrem Metafile „auf dem Bildschirm“ gegenüber 96 oder 120DPI liegt. Ich würde es vorziehen, dass Sie diesen Test auf physischen Maschinen durchführen, um einfach die Möglichkeit einer weiteren Skalierung mit Remote -Desktop- oder virtuellen Maschinentreibern auszuschließen.
Wenn die Lösung nicht sofort erkennbar ist, gehen Sie einen Schritt weiter und zeichnen Sie die Einstellungen für das Betriebs- und Bedienfeld für DPI oder "kleiner", "mittel" und "größer" auf. Windows XP kann sich anders verhalten als Windows Vista/Windows 7.
Sie können den Test auch mehrmals auf derselben physischen Maschine erneut ausführen, um die konfigurierte Anzeigeauflösung zwischen Tests anzupassen und Änderungen zu beobachten. Wenn meine Hypothese korrekt ist, sollten Sie für jede konfigurierte Anzeigeauflösung auf derselben physischen Maschine/Anzeige -Kombination eine andere Metafilenauflösung sehen, und dieses Ergebnis sollte vorhersehbar und wiederholbar sein (die Rückkehr zur ersten Auflösung sollte auf dieselbe Metafile -Auflösung zurückkehren)
Bearbeiten #1
Ich fand einen ausgezeichneten Artikel, in dem physische DPI gegen logische DPI erörtert wird. Lesen Sie dies: Woher kommt 96 DPI in Windows?
Jetzt ist der nächste Test, den ich empfehlen würde, die Anzeige! Haben Sie einen anderen LCD -Monitor für Marke/Größe/Auflösung zum Testen verfügbar? Sie brauchen nicht so viele Zeilen wie Ihr erster Test oben, da wir die verschiedenen Auflösungen erstellt haben, die dazu neigen, ein sehr ähnliches DPI für das gleiche Display zu erzeugen. Testen Sie nur ein paar gemeinsame Auflösungen, einschließlich der nativen Auflösung des Displays und 1024x768 als "Grundlinie" zum Vergleich.
Auch während ich in Windows 7 herumstochte, fand ich den Link "Benutzerdefinierte Textgröße (Benutzerdefinierte Textgröße)" in der Bedienfelder-> Anzeige, das eine Option "DPI-Skalierung von Windows XP-Stil verwenden" enthielt. Obwohl ich nicht denke, dass dies das Hauptanliegen ist, interessiert mich Neugier für seine Wirkung, und ich dachte, ich würde es erwähnen.
Bearbeiten #2 - gelöst!
Die Auflösung, die Sie in Ihren Metafiles sehen, ist der physische DPI Ihres Monitors. Ich werde hier einen C# -Code veröffentlichen, damit Sie sich selbst testen:
[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);
}
}
Dieser Code auf meiner Anzeige gibt Folgendes aus:
- Größe: 677 mm x 381 mm
- Desktop -Auflösung: 1920x1080
- Logischer DPI: 96x96
- Physischer DPI: 72.0354505169867x72
Beachten Sie sowohl den logischen als auch den physischen DPI? Sieht dieser physische DPI bekannt vor? Nach dem Lesen dieses Artikels über 72DPI, das 1PT = 1PX reflektiert, ist es sinnvoll. Probieren Sie diesen Code an Ihre verschiedenen Testmaschinen und lassen Sie mich wissen, wie es geht! (Zu Ihrer Information, ich habe diesen Code in einer C# Winforms -App, einer Konsolen -App, ausgeführt sollte in der Lage sein, den Kontext des Bildschirmgeräts zu erhalten, aber vielleicht auch nicht ...)