How to get Windows Display settings?

2019-01-02 18:32发布

There is setting for Display in Windows 7 (Control Panel -> Display). It allows to change the size of the text and other items on the screen. I need to get this setting to be able to switch on/switch off some functionality in my C# application based on the setting value. Is that possible?

标签: c# windows dpi
10条回答
像晚风撩人
2楼-- · 2019-01-02 18:33

The most easier way in my opinion is to use GetDeviceCaps function. From 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
}      

And usage:

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

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

In this approach you have no need to mark your app as dpi aware.

查看更多
明月照影归
3楼-- · 2019-01-02 18:34

This is how you can do it in WPF. The return value is in WPF's logical units, which are equal to 1/96th of an inch. So if your screen DPI is set to 96, you will get a value of 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)

查看更多
伤终究还是伤i
4楼-- · 2019-01-02 18:39

Both graphics.DpiX and DeviceCap.LOGPIXELSX return 96 on Surface Pro in all scaling levels.

Instead, I managed to calculate the scaling factor this way:

[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%
}
查看更多
后来的你喜欢了谁
5楼-- · 2019-01-02 18:44

Using Farshid T's answer as a base works in every scaling factor, except for 125%. I tested about 20 different scaling factors, and the DPI always returns as 96, except for when set at 125%, which returns a DPI of 120. 120 / 96 = 1.25. Not sure why this is the case, but this code seems to work for any scale setting.

    [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

and usage:

        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...
        }
查看更多
闭嘴吧你
6楼-- · 2019-01-02 18:45

In case of WPF use the following snippet,

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;
        }
查看更多
琉璃瓶的回忆
7楼-- · 2019-01-02 18:45

I use this way in my console application:

float dpiX, dpiY;
using (Graphics graphics = Graphics.FromHwnd(IntPtr.Zero))
{
    dpiX = graphics.DpiX;
    dpiY = graphics.DpiY;
}
查看更多
登录 后发表回答