vs 在高分屏下開發 winform 配置


一、窗體控件大小

第一種方法:使用網格避免整除誤差

在選項中將Windows窗體設計器的LayoutMode(布局模式)改成SnapToGrid(對齊到網格),並將Default Grid Cell Size(默認網格大小)設為最小可縮放單元(或它的倍數),以避免移植時產生整除誤差。同時由於這些單元是可見的,也使得將控件拖到合適的尺寸非常簡單。

同時,應該將窗體的AutoScaleMode改為Dpi。默認的Font縮放使用系統默認字體的大小進行縮放,但是系統默認字體並不和DPI完全等比例,這樣也會造成整除誤差。

如果文字不能對齊的話,可以考慮調整TextAlign屬性,比如單行Label推薦使用MiddleLeft、MiddleCenter或MiddleRight對齊方式,而不是默認的TopLeft對齊方式,以和其它控件的對齊方式統一。

最小可縮放單元如下表所示(最小可縮放單元=縮放/25%=DPI/24):

縮放    DPI值   最小可縮放單元
100%    96      4
125%    120     5
150%    144     6
175%    168     7
200%    192     8
225%    216     9
250%    240     10


Windows窗體設計器選項(150%):
pic


效果:
pic


第二種方法:使用布局容器進行布局

如果認真學習過WPF,就會知道WPF可通過Grid、StackPanel、WrapPanel等布局容器進行布局。實際上,Windows Forms也有兩個這樣的容器,叫做TableLayoutPanel和FlowLayoutPanel,其中前者和Grid一樣是表格布局容器,而后者和WrapPanel一樣是流式布局容器。

在新建了窗體之后,按照以下流程使用TableLayoutPanel(表格布局面板)布局控件:

1.拖拉父窗口到合適大小,屬性設置如下:
Padding:設置合適的內邊距【最小可縮放單元(如150%縮放下是6)或它的倍數】

2.拖一個TableLayoutPanel控件,屬性設置如下:
Dock:設置為Fill(停靠方式=填充)

3.根據需要分割出Columns(列)和Rows(行)
要求:一個單元格最多只能放置一個控件(或容器),但是一個控件可跨多行或多列

4.拖其它控件(或容器)到對應單元格,設置
Dock:設置為Fill(停靠方式=填充)
Margin:設置合適的外邊距【最小可縮放單元(如150%縮放下是6)或它的倍數】
ColumnSpan:需要跨的列數
RowSpan:需要跨的行數

注意:Windows Forms中某些控件的Height屬性有時不起作用(比如單行TextBox等),設置Dock屬性並不能保證單元格被完全填充,但是只要文字仍然能夠對齊就可以了。

FlowLayoutPanel(流式布局面板)和TableLayoutPanel有所不同,子控件要設置Width、Height、Margin屬性,不能設置Dock屬性,並且Width、Height和Margin一樣也必須是最小可縮放單元的倍數。也就是說,仍然需要使用“對齊到網格”功能來完成設計。

運行階段

默認情況下,Windows Forms程序由於高DPI支持不完整,在Windows Vista以后的系統中是由系統的DWM來縮放的(稱為DPI虛擬化),這樣的話會導致界面模糊。可以修改Program.cs並調用SetProcessDPIAware函數關閉DPI虛擬化,由程序自己來管理界面:

using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; // 導入System.Runtime.InteropServices命名空間 using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication1 {     static class Program     {         // 外部函數聲明         [DllImport("kernel32.dll")]         private static extern IntPtr GetModuleHandle(string name);         // 這個函數只能接受ASCII,所以一定要設置CharSet = CharSet.Ansi,不然會失敗         [DllImport("kernel32.dll", CharSet = CharSet.Ansi)]         private static extern IntPtr GetProcAddress(IntPtr hmod, string name);         private delegate void FarProc();         /// <summary>         /// The main entry point for the application.         /// </summary>         [STAThread]         static void Main()         {             // SetProcessDPIAware是Vista以上才有的函數,需兼容XP的話不能直接調用,需按如下所示間接調用             IntPtr hUser32 = GetModuleHandle("user32.dll");             IntPtr addrSetProcessDPIAware = GetProcAddress(hUser32, "SetProcessDPIAware");             if (addrSetProcessDPIAware != IntPtr.Zero)             {                 FarProc SetProcessDPIAware = (FarProc)Marshal.GetDelegateForFunctionPointer(addrSetProcessDPIAware, typeof(FarProc));                 SetProcessDPIAware();             }             // C#的原有代碼             Application.EnableVisualStyles();             Application.SetCompatibleTextRenderingDefault(false);             Application.Run(new Form1());         }     } }


如果不需要兼容Windows XP的話,可以更簡單地直接調用SetProcessDPIAware:

using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; // 導入System.Runtime.InteropServices命名空間 using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication1 {     static class Program     {         // 外部函數聲明         [DllImport("user32.dll")]         private static extern void SetProcessDPIAware();         /// <summary>         /// The main entry point for the application.         /// </summary>         [STAThread]         static void Main()         {             // SetProcessDPIAware是Vista以上才有的函數,這樣直接調用會使得程序不兼容XP             SetProcessDPIAware();             // C#的原有代碼             Application.EnableVisualStyles();             Application.SetCompatibleTextRenderingDefault(false);             Application.Run(new Form1());         }     } }


.NET Framework 4.5.1提供了優化的高DPI支持,但需要手動開啟,在工程中添加app.config(發布時需要將.exe文件和.exe.config文件一起發布),內容如下:

<?xml version="1.0" encoding="utf-8"?> <configuration>     <appSettings>         <add key="EnableWindowsFormsHighDpiAutoResizing" value="true" />     </appSettings> </configuration>

二 、FormSize和設計不符

Windows的高DPI支持是通過DWM(Desktop Window Manager)縮放實現的,但是有時候我們不希望這種效果(例如縮放會使一些內容變得模糊),因此需要禁用Windows高DPI對程序的縮放。有兩種方式可以實現這種效果:一個是使用應用程序清單文件,一個是使用系統API實現。

1、使用清單文件

這里以Winform為例,右鍵項目->添加->新建項->應用程序清單文件,將含有dpiAware標簽的屬性取消注釋,代碼如下:

<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
2、使用系統API

下面的代碼對Win7及以上的系統禁用高DPI。

if (Environment.OSVersion.Version.Major >= 6)
{
SetProcessDPIAware();
}

[DllImport("user32.dll")]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM