web-dev-qa-db-fra.com

Comment obtenir les paramètres d'affichage de Windows?

Il existe un paramètre pour l'affichage dans Windows 7 (Panneau de configuration -> Affichage). Il permet de modifier la taille du texte et d'autres éléments à l'écran. J'ai besoin d'obtenir ce paramètre pour pouvoir activer/désactiver certaines fonctionnalités de mon application C # en fonction de la valeur du paramètre. Est-ce possible?

65
newmember

Ce paramètre est le DPI de l'écran, ou points par pouce.

Lisez-le comme ceci:

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

Je ne pense pas qu'il soit possible pour le moment que les valeurs X et Y soient différentes. Une valeur de 96 correspond à une échelle de police de 100% (plus petite), 120 correspond à une échelle de 125% (moyenne) et 144 correspond à une échelle de 150% (plus grande). Cependant, les utilisateurs peuvent définir des valeurs autres que celles standard.

N'oubliez pas que, sauf si votre application est déclarée compatible DPI, les valeurs que vous observez peuvent être soumises à la virtualisation DPI.

42
David Heffernan

Graphics.DpiX et DeviceCap.LOGPIXELSX renvoient 96 sur Surface Pro à tous les niveaux de mise à l'échelle.

Au lieu de cela, j'ai réussi à calculer le facteur d'échelle de cette façon:

[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%
}
70
Farshid T

La manière la plus simple à mon avis est d'utiliser la fonction 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
{
  /// <summary>
  /// Logical pixels inch in X
  /// </summary>
  LOGPIXELSX = 88,
  /// <summary>
  /// Logical pixels inch in Y
  /// </summary>
  LOGPIXELSY = 90

  // Other constants may be founded on pinvoke.net
}      

Et l'utilisation:

Graphics g = Graphics.FromHwnd(IntPtr.Zero);            
IntPtr desktop = g.GetHdc();

int Xdpi = GetDeviceCaps(desktop, (int)DeviceCap.LOGPIXELSX);
int Ydpi = GetDeviceCaps(desktop, (int)DeviceCap.LOGPIXELSY);    

Dans cette approche, vous n'avez pas besoin de marquer votre application comme prenant en charge le dpi.

15
Anton Semenov

Voici comment vous pouvez le faire dans WPF. La valeur de retour est dans les unités logiques de WPF, qui sont égales à 1/96e de pouce. Donc, si votre écran DPI est réglé sur 96, vous obtiendrez une valeur 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

( source )

10
Eternal21

J'utilise de cette façon dans mon application console:

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

Dans le cas de WPF, utilisez l'extrait de code suivant,

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;
        }
6
Anees Deen

L'utilisation de la réponse de Farshid T comme base fonctionne dans tous les facteurs d'échelle, à l'exception de 125%. J'ai testé environ 20 facteurs d'échelle différents, et le DPI renvoie toujours 96, sauf lorsqu'il est réglé à 125%, ce qui renvoie un DPI de 120. 120/96 = 1,25. Je ne sais pas pourquoi c'est le cas, mais ce code semble fonctionner pour n'importe quel paramètre d'échelle.

    [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

et utilisation:

        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...
        }
5
Ric Gaudet

C'est une très vieille question, mais depuis Windows 8.1, on peut utiliser diverses autres fonctions, comme GetDpiForWindow

En 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;
    }
}

Pour que cela fonctionne correctement à l'anniversaire de Windows 10, vous devez ajouter un app.manifest à votre projet C #:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<Assembly xmlns="urn:schemas-Microsoft-com:asm.v1"
          manifestVersion="1.0">
  <application xmlns="urn:schemas-Microsoft-com:asm.v3">
    <windowsSettings>
      <!-- The combination of below two tags have the following effect : 
      1) Per-Monitor for >= Windows 10 Anniversary Update
      2) System < Windows 10 Anniversary Update -->
      <dpiAwareness xmlns="http://schemas.Microsoft.com/SMI/2016/WindowsSettings">PerMonitor</dpiAwareness>
      <dpiAware xmlns="http://schemas.Microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
    </windowsSettings>
  </application>

</Assembly>
3
Ziriax

Voici une solution qui fonctionne bien dans Windows 10. Il n'y a pas besoin de sensibilisation DPI ou quoi que ce soit.

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

Je pense que cela devrait vous fournir les informations que vous recherchez:

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

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

Modifier - oh désolé, il semble qu'il existe un moyen plus facile d'obtenir ces informations maintenant sans pinvoke,

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

1
asawyer