Как получить настройки дисплея Windows? - PullRequest
63 голосов
/ 12 мая 2011

Существует настройка для отображения в Windows 7 (Панель управления -> Дисплей). Позволяет изменять размер текста и других элементов на экране. Мне нужно получить этот параметр, чтобы иметь возможность включать / выключать некоторые функции в моем приложении C # в зависимости от значения параметра. Это возможно?

Ответы [ 10 ]

67 голосов
/ 30 января 2014

Оба графика.DpiX и DeviceCap.LOGPIXELSX возвращают 96 в Surface Pro при всех уровнях масштабирования.

Вместо этого мне удалось вычислить коэффициент масштабирования следующим образом:

[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%
}
41 голосов
/ 12 мая 2011

Этот параметр соответствует разрешению экрана или точкам на дюйм.

Прочитайте это так:

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

Я не думаю, что в настоящий момент значения X и Y могут быть разными. Значение 96 соответствует 100% масштабированию шрифта (меньше), 120 соответствует 125% масштабированию (среднее значение) и 144 соответствует 150% масштабированию (больше). Однако пользователи могут устанавливать значения, отличные от стандартных.

Имейте в виду, что если ваше приложение не объявлено с поддержкой DPI, то наблюдаемые вами значения могут подвергаться виртуализации DPI.

14 голосов
/ 12 мая 2011

Самый простой способ, на мой взгляд, это использовать функцию GetDeviceCaps.От 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
}      

И использование:

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

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

При таком подходе вам не нужно отмечать ваше приложение как поддерживающее dpi.

9 голосов
/ 11 января 2013

Вот как вы можете сделать это в WPF. Возвращаемое значение указывается в логических единицах WPF, которые равны 1/96 дюйма. Таким образом, если ваш DPI установлен на 96, вы получите значение 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

( источник )

7 голосов
/ 10 августа 2015

Я использую этот способ в своем консольном приложении:

float dpiX, dpiY;
using (Graphics graphics = Graphics.FromHwnd(IntPtr.Zero))
{
    dpiX = graphics.DpiX;
    dpiY = graphics.DpiY;
}
6 голосов
/ 18 июня 2014

В случае WPF используйте следующий фрагмент,

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;
        }
4 голосов
/ 19 ноября 2015

Использование ответа Фаршида Т в качестве основы работает при любом коэффициенте масштабирования, кроме 125%.Я протестировал около 20 различных масштабных коэффициентов, и DPI всегда возвращается как 96, за исключением случаев, когда установлено значение 125%, что возвращает DPI 120. 120/96 = 1,25.Не уверен, почему это так, но этот код работает для любой настройки масштаба.

    [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

и использование:

        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...
        }
3 голосов
/ 17 апреля 2017

Это очень старый вопрос, но начиная с Windows 8.1, можно использовать различные другие функции, такие как 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;
    }
}

Для корректной работы в Windows 10 вам нужно добавить app.manifest в ваш проект 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>
2 голосов
/ 12 июня 2018

Вот решение, которое хорошо работает в Windows 10. Нет необходимости в поддержке DPI или чего-либо еще.

public static int GetWindowsScaling()
{
    return (int)(100 * Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth);
}
1 голос
/ 12 мая 2011

Я думаю, что это должно предоставить вам информацию, которую вы ищете:

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

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

Редактировать - о, извините, похоже, что естьболее простой способ получить эту информацию сейчас без пинвока,

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

...