In che modo Excel calcola la risoluzione dei metafile che genera durante la copia di una gamma “come mostrato sullo schermo”?
Domanda
Ho qualche codice C # che ho ricevuto da http: // bytes.com/topic/c-sharp/answers/572657-net-clipboard-metafiles che copia un intervallo di celle in presenza delle seguenti due impostazioni:
- Come mostrato sullo schermo,
- Come mostrato in fase di stampa .
Quando guardo la risoluzione del metafile risultante (che è documentato come Gets the resolution, in pixels-per-inch, of this Image object
), ottengo valori diversi a seconda del metodo di copia.
-
Con il Come mostrato in fase di stampa , la risoluzione è di 600, che credo corrisponda alle impostazioni DPI che ho in Excel.
-
Con il Come mostrato sullo schermo impostazione, sputa fuori qualcosa come
Metafile.VerticalResolution = 72.08107
eMetafile.HorizontalResolution = 71.95952
. Su altre macchine, ho visto questo valore variano molto (valori intorno a 111, 130, ecc.).
Lo zoom non sembra influenzare questo. Da quello che ho osservato, i valori rimangono coerenti su una singola macchina, ma potrebbero differire da macchina a macchina.
Qualcuno può spiegare la logica di Excel segue quando si calcola la risoluzione del metafile in Come mostrato sullo schermo modalità?
Dopo aver modificato la risoluzione di Windows e misurando le risoluzioni metafile, qui è la tabella I generato (speranza sembra formattato correttamente):
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
Dopo l'esecuzione di una procedura simile in una macchina virtuale (stessa macchina fisica), questi sono i risultati. Un po 'più volatile rispetto alla macchina fisica in sé. Questi dati non potrebbe essere utile, ma ho pensato di fornire in ogni modo.
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
Soluzione
La mia ipotesi
Credo che questo abbia a che fare con l'esecuzione di una risoluzione non nativa su un monitor LCD. In "vecchi tempi" CRT non hanno una risoluzione nativa di per sé. Quindi il computer non era a conoscenza di qualsiasi risoluzione preferito per una data dimensione del monitor o le proporzioni. Con display digitali più recenti (LCD) il computer è ora a conoscenza della risoluzione preferita e rapporto di aspetto per lo schermo, se installato correttamente. Le mie finestre 7 macchina mostra "raccomandato" accanto alla risoluzione nativa del mio LCD e quindi mostra gli altri 2 pari risoluzioni proporzioni in nero, con i restanti "mismatch" di essere privi di etichetta, ma selezionabili (con conseguente sguardo schiacciata o allungata che odio vedere su altri computer popoli!).
I DPI di default di 96 e 120 in finestre sono state stabilite nei giorni CRT. Le mie finestre 7 macchina non dice nemmeno DPI più si dice solo, 'medium' 'piccolo', 'grande'.
In entrambi i casi, quando si acquista un monitor LCD che è dire 1920x1080 o 1920x1200, ma impostare la risoluzione del display a qualcosa di più piccolo, è risultato un fattore di conversione. Nel caso delle risoluzioni orizzontali e verticali non corrispondenza vicino a 72, la risoluzione dello schermo non nativa non può essere esattamente lo stesso fattore di scala verticale come è orizzontalmente traduce in questa piccola discrepanza.
Come testare la mia ipotesi
In ciascuna delle vostre macchine di prova registrare la risoluzione configurato i sistemi operativi ei display risoluzione nativa. Vedere se il rapporto tra i due è vicino al rapporto tra il metafile 'come sullo schermo' vs sia 96 o 120dpi. Io preferirei di condurre il test su macchine fisiche semplicemente escludere la possibilità di un ulteriore ridimensionamento con il desktop remoto o driver delle macchine virtuali.
Se la soluzione non è immediatamente evidente, fare un passo avanti e registrare le impostazioni del pannello comando e di controllo per DPI o 'più piccolo', 'media' e 'grande'. Windows XP può comportarsi in modo diverso rispetto a Windows Vista / Windows 7.
Si potrebbe anche ri-eseguire il test sulla stessa macchina fisica più volte, regolare la risoluzione visualizzazione configurata tra un test e osservare eventuali modifiche. Se la mia ipotesi è corretta si dovrebbe vedere risoluzione metafile diverso per ogni risoluzione dello schermo configurato sulla stessa combinazione di fisica della macchina / display e questo risultato dovrebbe essere prevedibile e ripetibile (tornando alla prima risoluzione dovrebbe tornare alla stessa risoluzione metafile)
EDIT # 1
Ho trovato un eccellente articolo che discute DPI fisico vs logica DPI. Avere una lettura di questo: dove viene 96 DPI provengono in di Windows?
Così ora il prossimo test io consiglierei sta cambiando schermi! Avete un differente del monitor LCD di marca / formato / risoluzione per il test? Non hai bisogno di più così tante linee come il primo test di cui sopra come abbiamo stabilito le varie risoluzioni tendono a produrre una molto simile DPI per lo stesso display. Proprio di prova forse un paio risoluzioni comuni, tra cui la risoluzione nativa del display e 1024x768 come "base" per il confronto.
Anche mentre rovistando in Windows 7, ho trovato il "Formato Custom Text (DPI)" collegamento nel Pannello di controllo-> display che includeva un'opzione "Usa ridimensionamento di Windows XP Style DPI". Anche se non credo che questo sia la preoccupazione principale, la curiosità mi fa interessata nei suoi effetti, così ho pensato di parlarne.
EDIT # 2 - Risolto
La risoluzione che state vedendo nelle vostre metafile è il DPI fisica del monitor. Vi posto qualche codice C # qui per voi per mettervi alla prova:
[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);
}
}
Questo codice sul mio display emette il seguente:
- Dimensioni: 677 millimetri x 381 millimetri
- Risoluzione Desktop: 1920x1080
- Logical DPI: 96x96
- DPI fisico: 72.0354505169867x72
Avviso sia la logica e fisica DPI? Ritiene che PHYSical DPI sembra familiare? Tutto ha un senso dopo aver letto quell'articolo merito 72dpi riflettente 1pt = 1 pixel. Dare a questo codice di una prova sulle varie macchine di prova e fammi sapere come va! (FYI, ho eseguito questo codice in un C # WinForms app, una console app dovrebbe essere in grado di ottenere il contesto di periferica schermo, ma forse no ...)