2011-05-12 71 views
47

在Windows 7中有显示设置(控制面板 - >显示)。它允许更改屏幕上的文本和其他项目的大小。 我需要获得此设置才能够根据设置值打开/关闭C#应用程序中的某些功能。 这可能吗?如何获取Windows显示设置?

+1

您对哪些设置感兴趣?有许多。 – 2011-05-12 11:46:11

+0

如果您使用设置 - 控制面板 - >显示打开此页面。只有一个设置可以改变屏幕上文本和其他项目的大小。选项为“较小”,“中等”和“较大” – newmember 2011-05-12 11:50:23

回答

35

此设置第e屏幕DPI或每英寸点数。

读它,像这样:

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

我不认为这是可能在目前的X和Y值是不同的。值为96对应于100%字体缩放(较小),120对应于125%缩放(中等),144对应于150%缩放(较大)。但是,用户可以设置这些标准值以外的值。

请注意,除非您的应用程序被声明为支持DPI,否则您观察到的值可能会受到DPI虚拟化的限制。

+2

我尝试使用不同的设置和图形的值运行此代码..DpiX始终为96. – newmember 2011-05-12 12:22:56

+0

@newmember当您更改设置时,Windows会告诉您需要在设置生效之前注销。你真的需要这样做! – 2011-05-12 12:26:53

+0

是的,我确实注销并重新登录 - 因此我已经改变了所有内容的大小,但DpiX是90! – newmember 2011-05-12 12:30:18

1

我想这应该为你提供你正在寻找的信息:

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

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

编辑 - 哦,对不起,它看起来像有一个更简单的方法,现在得到这个信息,而不一个PInvoke的,

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

+0

不幸的是,系统信息并不反映dpi比例。此外,似乎图形上下文的dpiX/dpiY属性返回96为150%(至少在Surface Pro 2上)。所以你无法区分100%和150%的变焦。有人知道一个合适的方法吗? – Zuppa 2013-12-13 13:30:03

11

我认为最简单的方法是使用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意识。

+6

不要忘记调用ReleaseHdc – BitsEvolved 2015-01-30 00:01:35

+0

@BitsEvolved绝对。这解决了“我的”内存泄漏(在完全不同的上下文中)!非常感谢。 – Wolf 2015-04-17 09:54:38

7

这是你如何在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 

source

+1

谢谢,我认为这是wpf最简单的方法。 – 2015-11-20 12:31:15

51

值都graphics.DpiX和DeviceCap.LOGPIXELSX在所有缩放级别上表面临返回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% 
} 
+7

哇,我已经搜索了很长时间如何获得真正的缩放因子,并且这最终解决了我的问题! – andreas 2015-01-17 01:40:11

+0

我第二个这个。我使用的是Dell XPS 15,并且使用3200x1800的原始分辨率查找,结果比我无法计算缩放因子,以便有用地使用来自GetWindowPlacement等的值。例如,使用控制台应用程序时,缩放比例为2,使用LINQPad它是1.这是最后的答案!谢谢 – joshcomley 2015-02-07 15:54:39

+2

那一刻,当你即将哭泣,放弃,然后你遇到这样的事情。 – 2015-04-21 22:06:25

6

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

我用这种方式在我的控制台应用程序:

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

使用Farshid T的答案作为基础在每个比例因子中起作用,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... 
     } 
1

这是一个非常古老的问题,但自从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 r 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>