En Windows 8.1 no obtengo la resolución correcta de ctypes o tk. Otras personas están teniendo el mismo problema con los tipos de ctypes: getsystemmetrics devuelve un tamaño de pantalla incorrecto
Para obtener la resolución completa correcta de un monitor de alto DPI en Windows 8.1, se debe llamar a SetProcessDPIAware y usar el siguiente código:
import ctypes
user32 = ctypes.windll.user32
user32.SetProcessDPIAware()
[w, h] = [user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)]
Detalles completos a continuación:
Descubrí que esto se debe a que Windows informa una resolución escalada. Parece que Python es, de forma predeterminada, una aplicación "consciente de dpi del sistema". Los tipos de aplicaciones compatibles con DPI se enumeran aquí:
http://msdn.microsoft.com/en-us/library/windows/desktop/dn469266%28v=vs.85%29.aspx#dpi_and_the_desktop_scaling_factor
Básicamente, en lugar de mostrar el contenido con la resolución completa del monitor, lo que haría que las fuentes fueran pequeñas, el contenido se escala hasta que las fuentes sean lo suficientemente grandes.
En mi monitor obtengo:
Resolución física: 2560 x 1440 (220 DPI)
Resolución de Python reportada: 1555 x 875 (158 DPI)
Según este sitio de Windows: http://msdn.microsoft.com/en-us/library/aa770067%28v=vs.85%29.aspx
La fórmula para la resolución efectiva del sistema informado es: (report_px * current_dpi) / (96 dpi ) = físico_px
Puedo obtener la resolución de pantalla completa correcta y el DPI actual con el siguiente código. Tenga en cuenta que llamo a SetProcessDPIAware () para permitir que el programa vea la resolución real.
import tkinter as tk
root = tk.Tk()
width_px = root.winfo_screenwidth()
height_px = root.winfo_screenheight()
width_mm = root.winfo_screenmmwidth()
height_mm = root.winfo_screenmmheight()
# 2.54 cm = in
width_in = width_mm / 25.4
height_in = height_mm / 25.4
width_dpi = width_px/width_in
height_dpi = height_px/height_in
print('Width: %i px, Height: %i px' % (width_px, height_px))
print('Width: %i mm, Height: %i mm' % (width_mm, height_mm))
print('Width: %f in, Height: %f in' % (width_in, height_in))
print('Width: %f dpi, Height: %f dpi' % (width_dpi, height_dpi))
import ctypes
user32 = ctypes.windll.user32
user32.SetProcessDPIAware()
[w, h] = [user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)]
print('Size is %f %f' % (w, h))
curr_dpi = w*96/width_px
print('Current DPI is %f' % (curr_dpi))
Que regresó:
Width: 1555 px, Height: 875 px
Width: 411 mm, Height: 232 mm
Width: 16.181102 in, Height: 9.133858 in
Width: 96.099757 dpi, Height: 95.797414 dpi
Size is 2560.000000 1440.000000
Current DPI is 158.045016
Estoy ejecutando Windows 8.1 con un monitor con capacidad de 220 DPI. La escala de mi pantalla establece mi DPI actual en 158.
Usaré el 158 para asegurarme de que mis parcelas de matplotlib tengan el tamaño correcto con: from pylab import rcParams rcParams ['figure.dpi'] = curr_dpi