2015-04-03 16 views
8

Tôi cần phải có quy mô DPI, như được đặt từ Bảng điều khiển> Hiển thị, cho mỗi màn hình được kết nối với máy tính, ngay cả những màn hình không mở được cửa sổ WPF. Tôi đã thấy một số cách để có được DPI (ví dụ: http://dzimchuk.net/post/Best-way-to-get-DPI-value-in-WPF) nhưng dường như điều này phụ thuộc vào hoặc Graphics.FromHwnd(IntPtr.Zero) hoặc PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice.Làm thế nào để có được quy mô DPI cho tất cả các màn hình?

Có cách nào để nhận cài đặt DPI cho từng màn hình riêng lẻ không?

Bối cảnh - Tôi đang tạo trình chỉnh sửa cấu hình bố cục để người dùng có thể thiết lập cấu hình của họ trước khi khởi chạy. Đối với điều này, tôi vẽ mỗi màn hình tương đối với nhau. Đối với một cấu hình, chúng tôi đang sử dụng màn hình 4K có kích thước DPI lớn hơn mặc định. Nó được vẽ nhỏ hơn nhiều so với thể chất xuất hiện liên quan đến các màn hình khác vì nó báo cáo độ phân giải giống như các màn hình khác.

+0

Bạn có thể tạo cửa sổ giả trên mỗi màn hình và lấy thông tin theo cách này không? –

+0

Bạn có thể đi với nhận xét trước đó, nếu không bạn sẽ phải liệt kê các thiết bị hiển thị và nhận DPI theo cách đó. – Kcvin

+0

Windows hiện hỗ trợ DPI trên mỗi màn hình, bắt đầu bằng 8,1. Bạn có thể gặp phải nó trong một thiết lập, nơi bạn có một màn hình "võng mạc" đắt tiền và một màn hình khác, thường là một máy chiếu. Backgrounder cho WPF [ở đây] (https://msdn.microsoft.com/en-us/library/windows/desktop/ee308410%28v=vs.85%29.aspx). –

Trả lời

11

Tôi đã tìm được cách để lấy dpi bằng WinAPI. Lần đầu tiên cần tham chiếu đến System.DrawingSystem.Windows.Forms. Có thể nhận được màn hình xử lý với WinAPI từ một điểm trên vùng hiển thị - lớp Screen có thể cho chúng ta điểm này. Sau đó, chức năng GetDpiForMonitor trả về dpi của màn hình được chỉ định.

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

Có ba loại tỷ lệ, bạn có thể tìm thấy description in the MSDN.

Tôi đã thử nghiệm nó một cách nhanh chóng với một ứng dụng WPF mới:

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

Tôi hy vọng nó sẽ giúp!

+0

Tôi đã phải thay đổi 'MonitorFromPoint (Point, short)' thành 'MonitorFromPoint (Point, uint)', nhưng khác hơn là nó hoạt động tốt. Cảm ơn bạn! – Sarah

+0

@Sarah bạn nói đúng, tôi đã thay đổi tuyên bố. – Koopakiller

+0

Lưu ý nhanh, tính năng này chỉ hoạt động trên Windows 8 trở lên. –

Các vấn đề liên quan