2015-01-16 25 views
8

Tôi thấy sự khác biệt thú vị giữa độ phân giải được đặt qua Bảng điều khiển và đầu ra của Screen.Bounds cho máy tính xách tay màn hình rộng của tôi. Màn hình 15,5" và độ phân giải thiết lập thông qua Control Panel là 1920x1080. Tuy nhiên khi tôi chạy một số mã như thế này.Độ phân giải màn hình không khớp với Screen.Bounds

Screen[] screens = Screen.AllScreens; 
foreach (Screen scr in screens) 
{ 
    Console.WriteLine("Width: " + scr.Bounds.Width + ", Height: " + scr.Bounds.Width); 
} 

Kết quả cho thấy độ phân giải của tôi là 1536x864. Tôi đã làm một số tìm kiếm xung quanh, và tôi nghĩ rằng nó có thể liên quan đến vấn đề DPI và khi tôi xem cài đặt hiển thị của mình, thanh trượt (Tôi đang sử dụng Windows 8.1) ở giữa và hộp kiểm cho biết "Hãy để tôi chọn một cấp độ thu nhỏ cho tất cả các màn hình của tôi" được bỏ chọn Tôi đã chạy mã nhỏ này để có được thiết lập DPI hiện tại

float dpiX, dpiY; 
Graphics graphics = new System.Windows.Forms.Form().CreateGraphics(); 
Console.WriteLine("DPI: " + graphics.DpiX); 

DPI được trả về là 96.0 theo sự hiểu biết của tôi là 100% DPI setti ng (do đó không mở rộng hoặc bất cứ điều gì nó được gọi). Điều có vẻ kỳ quặc đối với tôi là các giới hạn được trả về bởi Màn hình chính xác là 80% độ phân giải thực tế của tôi, điều này khiến tôi nghĩ rằng DPI của tôi được đặt thành 100 (hoặc 125%) nhưng không phải vậy. Tôi chỉ gặp vấn đề này với màn hình máy tính xách tay của tôi, như màn hình phụ của tôi có giới hạn bằng với độ phân giải thông qua Bảng điều khiển. Đây có phải là do thực tế là thiết lập DPI của tôi không được thiết lập để hiển thị độc lập với nhau (hộp kiểm được chọn) không? Đối với một chút nền, tôi đang viết một công cụ lấy màn hình hiện tại và lấy hình ảnh từ reddit và phù hợp với màn hình độc lập với nhau, vì vậy bất kỳ giải pháp nào tôi có, nó phải có độ phân giải chính xác của từng màn hình.

+0

Tôi giả sử 'scr.Bounds..Primary' trong ví dụ mã đầu tiên của bạn thực sự nên là' scr.Bounds.Height'? –

+0

Nếu "Hãy để tôi chọn một mức tỷ lệ cho tất cả các màn hình của tôi" được ** bỏ chọn ** thì chắc chắn bạn có các DPI khác nhau được đặt cho mỗi màn hình? –

+0

@StevenRands cố định ví dụ và tôi nghĩ rằng đó là trường hợp, tuy nhiên nếu hộp đó được bỏ chọn, DPI cho cả hai màn hình vẫn là 96.0. Tôi có làm điều gì sai trái trong cách tôi nhận được DPI không? –

Trả lời

3

Tôi tin rằng bạn phải thông báo cho hệ điều hành mà ứng dụng của bạn là DPI biết. Nếu không, hệ điều hành giả vờ rằng tất cả mọi thứ chỉ là tốt, dẫn đến hành vi bạn đang quan sát - hệ điều hành xử lý việc thay đổi kích thước.

Bạn có thể tìm thấy một số thông tin về cách viết các ứng dụng nhận biết DPI tại đây - http://msdn.microsoft.com/cs-cz/library/dd464646.aspx Tất nhiên, bạn nên đảm bảo rằng ứng dụng của bạn thực sự là . Nó không phải là tốt đẹp, nhưng ít nhất nó sẽ làm việc.

Sự khác biệt chính mà Windows 8.1 mang lại cho điều này là bạn có thể có DPI khác nhau trên các màn hình khác nhau và bạn có thể truy vấn API DPI của màn hình. .NET (và đặc biệt là WPF) theo mặc định sẽ tự động xử lý nhận thức DPI, nhưng chỉ dựa trên hệ thống DPI. Nếu màn hình của bạn có các thiết lập DPI khác nhau, nó sẽ hoạt động như không nhận thức được DPI (chính xác hơn, nhận thức hệ thống-DPI, nhưng kết quả cuối cùng là đồ họa ứng dụng của bạn sẽ được ảo hóa bởi Windows). Tôi hy vọng rằng nếu bạn ngắt kết nối màn hình thứ hai, ứng dụng của bạn sẽ hoạt động như mong đợi trên màn hình duy nhất của bạn (ít nhất là sau khi đặt DPI theo cách thủ công, bất kể giá trị nào).

+0

Cảm ơn điều này, nó rất hữu ích. Bạn có biết nếu có một cách để có được DPI của cả hai màn hình cùng một lúc? Ví dụ cho các công trình khi di chuyển các ứng dụng WPF giữa các màn hình (120 trên máy tính xách tay, 96 trên thứ cấp) nhưng tôi cần phải có được DPI của màn hình thứ hai mà không cần di chuyển ứng dụng lên đó. –

+0

@Issac Để nhận được DPI cho mỗi màn hình, bạn cần gọi hàm [GetDpiForMonitor] (http://msdn.microsoft.com/en-us/library/windows/desktop/dn280510.aspx) bằng P/Invoke. Để có tổng quan chung về DPI trên mỗi màn hình, hãy kiểm tra [Viết DPI-Aware Desktop và ứng dụng Win32] (http://msdn.microsoft.com/en-us/library/windows/desktop/dn469266.aspx). – emoacht

+0

@IsaacLevin Bạn có chắc chắn bạn cần phải làm điều đó? Nếu bạn chắc chắn rằng ứng dụng của bạn là giám sát DPI, bạn sẽ nhận được giới hạn màn hình chính xác. Bạn chỉ đang cố nhân rộng độ phân giải của DPI hay gì đó? Biểu mẫu sẽ thực sự có ít không gian hơn trên màn hình khác, như được báo cáo bởi 'Screen.Bounds'. – Luaan

9

Tôi cũng gặp vấn đề tương tự đối với công cụ chụp màn hình. Tôi tìm thấy giải pháp và nó hoạt động cho tôi.

private enum ProcessDPIAwareness 
{ 
    ProcessDPIUnaware = 0, 
    ProcessSystemDPIAware = 1, 
    ProcessPerMonitorDPIAware = 2 
} 

[DllImport("shcore.dll")] 
private static extern int SetProcessDpiAwareness(ProcessDPIAwareness value); 

private static void SetDpiAwareness() 
{ 
    try 
    { 
    if (Environment.OSVersion.Version.Major >= 6) 
    { 
     SetProcessDpiAwareness(ProcessDPIAwareness.ProcessPerMonitorDPIAware); 
    } 
    } 
    catch (EntryPointNotFoundException)//this exception occures if OS does not implement this API, just ignore it. 
    { 
    } 
} 

Bạn nên gọi phương thức SetDpiAwareness() trước khi chức năng cuộc gọi để có được độ phân giải hệ thống vv Ngoài ra nếu bạn có một số giao diện người dùng trong ứng dụng của bạn bây giờ nó là trách nhiệm của bạn để mở rộng giao diện người dùng của bạn trong màn hình với DPI cao.

Hy vọng điều này sẽ hữu ích.

+0

Cảm ơn! Đây là giải pháp duy nhất, giúp tôi với chương trình chia sẻ màn hình và mở rộng trong Windows 8.1 – Art

+1

Một điều, trên Windows 7 mã này không cần thiết để mở rộng độ phân giải, nhưng nếu mã này chạy trên Windows 7, hãy thử bắt được ' t bắt lỗi và nó sẽ sụp đổ chương trình. Bạn sẽ cần phải thay đổi lỗi mà nó kiểm tra, hoặc trong trường hợp của tôi, tôi chỉ cần đặt nó để bắt bất kỳ ngoại lệ nào. – Byte11

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