2015-04-03 8 views
8

Ho bisogno di ottenere la scala DPI, come impostata da Pannello di controllo> Schermo, per ciascuna delle schermate collegate al computer, anche quelle che non hanno una finestra WPF aperta. Ho visto un certo numero di modi per ottenere DPI (ad esempio, http://dzimchuk.net/post/Best-way-to-get-DPI-value-in-WPF) ma questi sembrano essere dipendenti da Graphics.FromHwnd(IntPtr.Zero) o da PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice.Come ottenere la scala DPI per tutti gli schermi?

C'è un modo per ottenere le impostazioni DPI per ogni singola schermata?

Sfondo: sto creando un editor di configurazione del layout in modo che l'utente possa configurare la propria configurazione prima dell'avvio. Per questo, disegno ognuna delle schermate l'una rispetto all'altra. Per una configurazione utilizziamo un display 4K con un set di scale DPI più grande del valore predefinito. Si sta disegnando molto più piccolo di quanto appare fisicamente in relazione agli altri schermi perché riporta la stessa risoluzione degli altri schermi.

+0

È sufficiente creare una finestra fittizia su ogni schermata e acquisire le informazioni in questo modo? –

+0

Si potrebbe andare con il commento precedente, altrimenti sarà necessario enumerare i dispositivi di visualizzazione e ottenere DPI in questo modo. – Kcvin

+0

Windows ora supporta DPI per schermo, a partire da 8.1. È probabile che tu lo incontri in una configurazione in cui hai un costoso display "retina" e un altro normale, di solito un proiettore. Backgrounder per WPF [è qui] (https://msdn.microsoft.com/en-us/library/windows/desktop/ee308410%28v=vs.85%29.aspx). –

risposta

11

Ho trovato un modo per ottenere i dpi con WinAPI. Come prima necessita di riferimenti a System.Drawing e System.Windows.Forms. È possibile ottenere l'handle del monitor con WinAPI da un punto dell'area di visualizzazione: la classe Screen può darci questi punti. Quindi la funzione GetDpiForMonitor restituisce il dpi del monitor specificato.

public static class ScreenExtensions 
{ 
    public static void GetDpi(this System.Windows.Forms.Screen screen, DpiType dpiType, out uint dpiX, out uint dpiY) 
    { 
     var pnt = new System.Drawing.Point(screen.Bounds.Left + 1, screen.Bounds.Top + 1); 
     var mon = MonitorFromPoint(pnt, 2/*MONITOR_DEFAULTTONEAREST*/); 
     GetDpiForMonitor(mon, dpiType, out dpiX, out dpiY); 
    } 

    //https://msdn.microsoft.com/en-us/library/windows/desktop/dd145062(v=vs.85).aspx 
    [DllImport("User32.dll")] 
    private static extern IntPtr MonitorFromPoint([In]System.Drawing.Point pt, [In]uint dwFlags); 

    //https://msdn.microsoft.com/en-us/library/windows/desktop/dn280510(v=vs.85).aspx 
    [DllImport("Shcore.dll")] 
    private static extern IntPtr GetDpiForMonitor([In]IntPtr hmonitor, [In]DpiType dpiType, [Out]out uint dpiX, [Out]out uint dpiY); 
} 

//https://msdn.microsoft.com/en-us/library/windows/desktop/dn280511(v=vs.85).aspx 
public enum DpiType 
{ 
    Effective = 0, 
    Angular = 1, 
    Raw = 2, 
} 

Ci sono tre tipi di ridimensionamento, è possibile trovare un description in the MSDN.

ho testato rapidamente con una nuova applicazione WPF:

private void Window_Loaded(object sender, System.Windows.RoutedEventArgs e) 
{ 
    var sb = new StringBuilder(); 
    sb.Append("Angular\n"); 
    sb.Append(string.Join("\n", Display(DpiType.Angular))); 
    sb.Append("\nEffective\n"); 
    sb.Append(string.Join("\n", Display(DpiType.Effective))); 
    sb.Append("\nRaw\n"); 
    sb.Append(string.Join("\n", Display(DpiType.Raw))); 

    this.Content = new TextBox() { Text = sb.ToString() }; 
} 

private IEnumerable<string> Display(DpiType type) 
{ 
    foreach (var screen in System.Windows.Forms.Screen.AllScreens) 
    { 
     uint x, y; 
     screen.GetDpi(type, out x, out y); 
     yield return screen.DeviceName + " - dpiX=" + x + ", dpiY=" + y; 
    } 
} 

Spero che aiuta!

+0

Ho dovuto cambiare 'MonitorFromPoint (Point, Short)' a 'MonitorFromPoint (Point, uint)', ma a parte questo funziona benissimo. Grazie! – Sarah

+0

@Sarah hai ragione, ho cambiato la dichiarazione. – Koopakiller

+0

Una nota veloce, funziona solo su Windows 8 e versioni successive. –

Problemi correlati