2008-10-09 27 views
32

Tôi đã tạo một ứng dụng cho một doanh nghiệp nhỏ. Một số nhân viên trong văn phòng không thể nhìn thấy biểu mẫu chính xác. Lý do là họ có thiết lập DPI của họ thiết lập trên 96dpi. Có ai biết cách kiểm soát điều này không?Cách kiểm soát phông chữ DPI trong ứng dụng .NET WinForms

Đối với tất cả các bạn có kinh nghiệm với ứng dụng winforms, làm thế nào để bạn kiểm soát bố cục biểu mẫu để DPI không ảnh hưởng đến giao diện của ứng dụng?

+0

có thể trùng lặp của [Làm thế nào để viết mã WinForms tự động quy mô để cài đặt phông chữ và dpi hệ thống?] (Http://stackoverflow.com/questions/22735174/how-to-write-winforms-code-that-auto -scales-to-system-font-and-dpi-settings) –

+0

Bạn cũng kiểm tra blog này về vấn đề này, tôi nghĩ nó cung cấp thông tin tốt về chủ đề: http://www.telerik.com/blogs/winforms -scaling-at-large-dpi-settings-is-it-even-possible- – checho

Trả lời

16

Đặt AutoScaleMode thành Inherit ở khắp mọi nơi (nghĩa là tất cả các UserControls) của bạn thông qua tìm kiếm/thay thế toàn cục, sau đó đặt AutoScaleMode thành Dpi trên biểu mẫu chính của bạn.

Tôi cũng thấy rằng các vùng chứa bố cục hoạt động tốt hơn so với các neo cho loại tình huống này.

+0

Điều này đã giúp tôi đối phó với một tình huống mở rộng quy mô DPI khó chịu với bộ công cụ giao diện người dùng của bên thứ ba. Cảm ơn! – pelazem

63

Giả sử bạn không cố gắng tôn trọng lựa chọn phông chữ giao diện người dùng của người dùng (SystemFonts.IconTitleFont) và mã hóa cứng các biểu mẫu của bạn chỉ với một cỡ chữ (ví dụ: Tahoma 8pt, Microsoft Sans Serif 8.25pt), bạn có thể đặt biểu mẫu của mình AutoScaleMode đến ScaleMode.Dpi.

này sẽ mở rộng kích thước của hình thức và nhất của nó điều khiển con bởi các yếu tố CurrentDpiSetting/96 bằng cách gọi Form.Scale(), mà lần lượt gọi là bảo vệ ScaleControl() phương pháp recursivly trên chính nó và tất cả các điều khiển con. ScaleControl sẽ tăng vị trí, kích thước, phông chữ, vv của điều khiển khi cần cho hệ số chia tỷ lệ mới.

Cảnh báo: Không phải tất cả các điều khiển đều tự điều chỉnh chính xác. Ví dụ: các cột của danh sách xem sẽ không nhận được kích thước rộng hơn khi phông chữ lớn hơn. Trong đơn hàng để xử lý bạn sẽ phải thực hiện thủ công quy mô bổ sung theo yêu cầu . tôi làm điều này bằng cách ghi đè các phương pháp bảo vệ ScaleControl(), và rộng các cột listview bằng tay:

public class MyForm : Form 
{ 
    protected override void ScaleControl(SizeF factor, BoundsSpecified specified) 
    { 
     base.ScaleControl(factor, specified); 
     Toolkit.ScaleListViewColumns(listView1, factor); 
    } 
} 

public class Toolkit 
{ 
    /// <summary> 
    /// Scale the columns of a listview by the Width scale factor specified in factor 
    /// </summary> 
    /// <param name="listview"></param> 
    /// <param name="factor"></param> 
    /// <example>/* 
    /// protected override void ScaleControl(SizeF factor, BoundsSpecified specified) 
    /// { 
    /// base.ScaleControl(factor, specified); 
    ///  
    /// //ListView columns are not automatically scaled with the ListView, so we 
    /// //must do it manually 
    /// Toolkit.ScaleListViewColumns(lvPermissions, factor); 
    /// } 
    ///</example> 
    public static void ScaleListViewColumns(ListView listview, SizeF factor) 
    { 
     foreach (ColumnHeader column in listview.Columns) 
     { 
      column.Width = (int)Math.Round(column.Width * factor.Width); 
     } 
    } 
} 

này là tất cả tốt và tốt nếu bạn chỉ sử dụng điều khiển. Nhưng nếu bạn đã từng sử dụng bất kỳ kích thước pixel được mã hóa cứng nào, bạn sẽ cần phải mở rộng độ rộng và độ dài pixel theo hệ số tỷ lệ hiện tại của biểu mẫu. Một số ví dụ về các tình huống mà có thể mã hóa cứng kích thước điểm ảnh:

  • vẽ một hình chữ nhật 25px cao
  • vẽ một hình ảnh ở vị trí (11,56) về hình thức
  • căng vẽ một biểu tượng để 48x48
  • vẽ văn bản sử dụng Microsoft Sans Serif 8.25pt
  • nhận định dạng 32x32 của một biểu tượng và nhồi nhét nó vào một PictureBox

Nếu thi Trong trường hợp này, bạn sẽ cần phải mở rộng các giá trị mã hóa cứng đó theo "hệ số chia tỷ lệ hiện tại". Không may là yếu tố tỷ lệ "hiện tại" không được cung cấp, chúng tôi cần phải tự ghi lại. Giải pháp là giả định rằng ban đầu hệ số chia tỷ lệ là 1,0 và mỗi lần ScaleControl() được gọi, sửa đổi hệ số tỷ lệ chạy theo hệ số mới.

public class MyForm : Form 
{ 
    private SizeF currentScaleFactor = new SizeF(1f, 1f); 

    protected override void ScaleControl(SizeF factor, BoundsSpecified specified) 
    { 
     base.ScaleControl(factor, specified); 

     //Record the running scale factor used 
     this.currentScaleFactor = new SizeF(
     this.currentScaleFactor.Width * factor.Width, 
     this.currentScaleFactor.Height * factor.Height); 

     Toolkit.ScaleListViewColumns(listView1, factor); 
    } 
} 

Ban đầu hệ số chia tỷ lệ là 1.0. Nếu hình thức sau đó được nhân rộng bởi 1.25, các yếu tố rộng sau đó trở thành:

1.00 * 1.25 = 1.25 //scaling current factor by 125% 

Nếu hình thức sau đó được nhân rộng bởi 0.95, các yếu tố rộng mới trở nên

1.25 * 0.95 = 1.1875 //scaling current factor by 95% 

Lý do một SizeF được sử dụng (chứ không phải so với một giá trị dấu phẩy động đơn) là số lượng chia tỷ lệ có thể khác nhau theo hướng x và y. Nếu một biểu mẫu được đặt thành ScaleMode.Font, biểu mẫu được chia tỷ lệ thành kích thước phông chữ mới. Phông chữ có thể có tỷ lệ khung hình khác nhau (ví dụ:Giao diện người dùng Segoe là phông chữ cao hơn Tahoma). Điều này có nghĩa là bạn phải quy mô các giá trị x và y một cách độc lập.

Vì vậy, nếu bạn muốn đặt một điều khiển tại vị trí (11,56), bạn sẽ phải thay đổi mã vị trí của bạn từ:

Point pt = new Point(11, 56); 
control1.Location = pt; 

để

Point pt = new Point(
     (int)Math.Round(11.0*this.scaleFactor.Width), 
     (int)Math.Round(56.0*this.scaleFactor.Height)); 
control1.Location = pt; 

cũng áp dụng nếu bạn đang đi để chọn kích thước phông chữ:

Font f = new Font("Segoe UI", 8, GraphicsUnit.Point); 

sẽ phải trở thành:

Font f = new Font("Segoe UI", 8.0*this.scaleFactor.Width, GraphicsUnit.Point); 

Và chiết xuất một biểu tượng 32x32 đến một bitmap sẽ thay đổi từ:

Image i = new Icon(someIcon, new Size(32, 32)).ToBitmap(); 

để

Image i = new Icon(someIcon, new Size(
    (int)Math.Round(32.0*this.scaleFactor.Width), 
    (int)Math.Round(32.0*this.scaleFactor.Height))).ToBitmap(); 

, vv

Hỗ trợ hiển thị DPI phi tiêu chuẩn là một tax that all developers should pay. Nhưng thực tế là không ai muốn là lý do tại sao Microsoft gave up and added to Vista the ability for the graphics card to stretch any applications that don't say they properly handle high-dpi.

2

Tôi biết nó khá là quyết liệt, nhưng hãy cân nhắc viết lại ứng dụng của bạn trong WPF. Các ứng dụng WPF có cùng giao diện trên mọi thiết lập DPI.

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