code

Windows 디스플레이 설정을 얻는 방법은 무엇입니까?

codestyles 2020. 11. 13. 08:14
반응형

Windows 디스플레이 설정을 얻는 방법은 무엇입니까?


Windows 7 (제어판-> 디스플레이)에서 디스플레이에 대한 설정이 있습니다. 화면의 텍스트 및 기타 항목의 크기를 변경할 수 있습니다. 설정 값에 따라 내 C # 응용 프로그램에서 일부 기능을 켜거나 끌 수 있도록이 설정을 가져와야합니다. 가능합니까?


이 설정은 화면 DPI 또는 dpi입니다.

다음과 같이 읽으십시오.

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

지금은 X와 Y 값이 다를 수 있다고 생각하지 않습니다. 96 값은 100 % 글꼴 크기 조절 (작게)에 해당하고 120은 125 % 크기 조절 (중간)에 해당하며 144는 150 % 크기 조절 (크게)에 해당합니다. 그러나 사용자는 이러한 표준 값 이외의 값을 설정할 수 있습니다.

응용 프로그램이 DPI를 인식하도록 선언되지 않은 경우 관찰되는 값은 DPI 가상화의 영향을받을 수 있습니다.


graphics.DpiX 및 DeviceCap.LOGPIXELSX는 모든 크기 조정 수준에서 Surface Pro에서 96을 반환합니다.

대신 다음과 같은 방법으로 배율을 계산했습니다.

[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%
}

제 생각에 가장 쉬운 방법은 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 인식으로 표시 할 필요가 없습니다.


이것이 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

( 출처 )


내 콘솔 응용 프로그램에서이 방법을 사용합니다.

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

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

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...
        }

This is a very old question, but since Windows 8.1, one can use various other functions, like GetDpiForWindow

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

For this to work correctly on Windows 10 anniversary, you need to add an app.manifest to your C# project:

<?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>

Here's a solution that works nicely in Windows 10. There's no need for DPI awareness or anything.

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

I think this should provide you with the information you are looking for:

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

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

Edit - oh sorry it looks like there is an easier way to get this information now without a pinvoke,

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

참고URL : https://stackoverflow.com/questions/5977445/how-to-get-windows-display-settings

반응형