web-dev-qa-db-ja.com

Windowsディスプレイの設定を取得する方法は?

Windows 7のディスプレイの設定があります(コントロールパネル->ディスプレイ)。画面上のテキストやその他のアイテムのサイズを変更できます。設定値に基づいてC#アプリケーションの一部の機能のオン/オフを切り替えるには、この設定を取得する必要があります。それは可能ですか?

65
newmember

この設定は、画面のDPI、つまり1インチあたりのドット数です。

次のように読んでください:

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

現時点では、XとYの値が異なる可能性はないと思います。 96の値は100%のフォントスケーリング(小さい)に対応し、120は125%のスケーリング(中)に対応し、144は150%のスケーリング(大きい)に対応します。ただし、ユーザーはこれらの標準値以外の値を設定できます。

アプリケーションがDPI対応であると宣言されていない限り、観察する値はDPI仮想化の対象になる可能性があることに注意してください。

42
David Heffernan

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

私の意見では、最も簡単な方法は 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対応としてマークする必要はありません。

15
Anton Semenov

これは、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

ソース

10
Eternal21

コンソールアプリケーションでこの方法を使用します。

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

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

Farshid Tの答えをベースとして使用すると、125%を除くすべてのスケーリング係数で機能します。約20の異なるスケーリング係数をテストしましたが、DPIは常に96を返しますが、125%に設定した場合を除き、120のDPIを返します。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...
        }
5
Ric Gaudet

これは非常に古い質問ですが、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周年記念で正しく機能するには、C#プロジェクトにapp.manifestを追加する必要があります。

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

Windows 10でうまく機能するソリューションを次に示します。DPI認識などは必要ありません。

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

これはあなたが探している情報をあなたに提供するはずだと思います:

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

1
asawyer