¿Cómo obtener la configuración de pantalla de Windows?

Hay una configuración para Pantalla en Windows 7 (Panel de control -> Pantalla). Permite cambiar el tamaño del texto y otros elementos en la pantalla. Necesito obtener esta configuración para poder activar / desactivar algunas funciones en mi aplicación C # en función del valor de configuración. ¿Es eso posible?

Esta configuración es la pantalla DPI, o puntos por pulgada.

Léelo de esta manera:

float dpiX, dpiY; Graphics graphics = this.CreateGraphics(); dpiX = graphics.DpiX; dpiY = graphics.DpiY; 

No creo que sea posible en este momento que los valores X e Y sean diferentes. Un valor de 96 corresponde al escalado de fuente del 100% (más pequeño), 120 corresponde al escalado del 125% (medio) y 144 corresponde al escalado del 150% (más grande). Sin embargo, los usuarios pueden establecer valores distintos a estos estándar.

Tenga en cuenta que, a menos que se declare que su aplicación tiene conocimiento de DPI, los valores que observe pueden estar sujetos a la virtualización de DPI.

Ambos gráficos.DpiX y DeviceCap.LOGPIXELSX devuelven 96 en Surface Pro en todos los niveles de escala.

En cambio, logré calcular el factor de escala de esta manera:

 [DllImport("gdi32.dll")] static extern int GetDeviceCaps(IntPtr hdc, int nIndex); public enum DeviceCap { VERTRES = 10, DESKTOPVERTRES = 117, // http://pinvoke.net/default.aspx/gdi32/GetDeviceCaps.html } private float getScalingFactor() { Graphics g = Graphics.FromHwnd(IntPtr.Zero); IntPtr desktop = g.GetHdc(); int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES); int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES); float ScreenScalingFactor = (float)PhysicalScreenHeight / (float)LogicalScreenHeight; return ScreenScalingFactor; // 1.25 = 125% } 

La forma más sencilla en mi opinión es usar la función GetDeviceCaps . De pinvoke.net :

 [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)] public static extern int GetDeviceCaps(IntPtr hDC, int nIndex); public enum DeviceCap { ///  /// Logical pixels inch in X ///  LOGPIXELSX = 88, ///  /// Logical pixels inch in Y ///  LOGPIXELSY = 90 // Other constants may be founded on pinvoke.net } 

Y el uso:

 Graphics g = Graphics.FromHwnd(IntPtr.Zero); IntPtr desktop = g.GetHdc(); int Xdpi = GetDeviceCaps(desktop, (int)DeviceCap.LOGPIXELSX); int Ydpi = GetDeviceCaps(desktop, (int)DeviceCap.LOGPIXELSY); 

En este enfoque, no necesita marcar su aplicación como consciente de dpi.

Así es como puedes hacerlo en WPF. El valor de retorno está en las unidades lógicas de WPF, que son igual a 1/96 de pulgada. Entonces, si su pantalla DPI está configurada en 96, obtendrá un valor de 1.

 Matrix m = PresentationSource.FromVisual(Application.Current.MainWindow).CompositionTarget.TransformToDevice; double dx = m.M11; // notice it's divided by 96 already double dy = m.M22; // notice it's divided by 96 already 

( fuente )

En el caso de WPF usa el siguiente fragmento,

 PresentationSource source = PresentationSource.FromVisual(this); double dpiX, dpiY; if (source != null) { dpiX = 96.0 * source.CompositionTarget.TransformToDevice.M11; dpiY = 96.0 * source.CompositionTarget.TransformToDevice.M22; } 

Lo uso de esta manera en mi aplicación de consola:

 float dpiX, dpiY; using (Graphics graphics = Graphics.FromHwnd(IntPtr.Zero)) { dpiX = graphics.DpiX; dpiY = graphics.DpiY; } 

Usar la respuesta de Farshid T como base funciona en todos los factores de escala, excepto en un 125%. Probé alrededor de 20 factores de escala diferentes, y el DPI siempre regresa como 96, excepto cuando se establece en 125%, que devuelve un DPI de 120. 120/96 = 1.25. No estoy seguro de por qué este es el caso, pero este código parece funcionar para cualquier configuración de escala.

  [DllImport("gdi32.dll")] static extern int GetDeviceCaps(IntPtr hdc, int nIndex); public enum DeviceCap { VERTRES = 10, DESKTOPVERTRES = 117, LOGPIXELSY = 90, // http://pinvoke.net/default.aspx/gdi32/GetDeviceCaps.html 

y uso:

  Graphics g = Graphics.FromHwnd(IntPtr.Zero); IntPtr desktop = g.GetHdc(); int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES); int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES); int logpixelsy = GetDeviceCaps(desktop, (int)DeviceCap.LOGPIXELSY); float screenScalingFactor = (float)PhysicalScreenHeight / (float)LogicalScreenHeight; float dpiScalingFactor = (float)logpixelsy / (float)96; if (screenScalingFactor > 1 || dpiScalingFactor > 1) { // do something nice for people who can't see very well... } 

Esta es una pregunta muy antigua, pero desde Windows 8.1, se pueden usar otras funciones, como GetDpiForWindow

Cª#:

 [DllImport("user32.dll")] static extern int GetDpiForWindow(IntPtr hWnd); public float GetDisplayScaleFactor(IntPtr windowHandle) { try { return GetDpiForWindow(windowHandle) / 96f; } catch { // Or fallback to GDI solutions above return 1; } } 

Para que esto funcione correctamente en el aniversario de Windows 10, debe agregar una app.manifest a su proyecto de C #:

      PerMonitor True/PM    

Creo que esto debería proporcionarle la información que está buscando:

http://www.pinvoke.net/default.aspx/user32.getsystemmetrics

http://pinvoke.net/default.aspx/Enums.SystemMetric

Editar – oh lo siento, parece que hay una manera más fácil de obtener esta información ahora sin un pinvoke,

http://msdn.microsoft.com/en-us/library/system.windows.forms.systeminformation.aspx

Aquí hay una solución que funciona muy bien en Windows 10. No hay necesidad de conocimiento de DPI ni nada.

 public static int GetWindowsScaling() { return (int)(100 * Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth); }