2011-05-12 111 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> 
相關問題