zoukankan      html  css  js  c++  java
  • 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")]

  • 相关阅读:
    oracle函数 MAX([distinct|all]x)
    oracle函数 MAX([distinct|all]x)
    oralce函数 count(*|[distinct|all]x)
    oracle函数 VARIANCE([distinct|all]x)
    oralce函数 STDDEV([distinct|all]x)
    oracle函数 SUM([distinct|all]x)
    oralcle函数 AVG([distinct|all]x)
    oracle函数 lag()和lead()
    oracle函数 ROW_NUMBER()
    Linux性能测试 netstat命令
  • 原文地址:https://www.cnblogs.com/z45281625/p/11090140.html
Copyright © 2011-2022 走看看