WinForm响应式布局设计试行

引言

创立响应式WinForm应用程序并不那么粗略。
响应式布局,在此作者指的是应用程序在分化显示器分辨率下的可用性。
对于WinForm应用程序,大家需求明确地遵照分辨率来调动控件的高低和再度定位。
固然在行使WPF时有相关的实践应用,通过动用控件的docking和anchoring,或选择panels等格局,但本文提供了一种将响应式应用于WinForm应用程序的分化措施。

背景

自己在二个和谐设计的归纳游戏中境遇了难题:作者计划了一台分辨率为一九二零x拾80的机械,
不过当自家企图在台式机Computer上播报时,开采应用程序边界跑到显示器之外。因此很有不可或缺让程序来适应分歧分辨率的配备,而不是让用户来适应程序。
因而,作者对代码进行了创新。

技术

实际上没什么技巧可言,只是用了1个小手艺。大家用七个常量来保存设计时的显示屏分辨率,大家誉为设计时分辨率。那样,无论曾几何时运维应用程序,它都会获得叁个乘法因子,这实在是三个百分比因子,通过将近些日子分辨率除以设计时分辨率来赢得该因子。
窗体的持有控件都被传送给这一个类对象进行缩放和调动大小。

代码

The Responsive Class – Responsive.cs

开创1个类Responsive.cs,增加四个变量。

float WIDTH_AT_DESIGN_TIME = (float)Convert.ToDouble
                             (ConfigurationManager.AppSettings["DESIGN_TIME_SCREEN_WIDTH"]);
float HEIGHT_AT_DESIGN_TIME = (float)Convert.ToDouble
                              (ConfigurationManager.AppSettings["DESIGN_TIME_SCREEN_HEIGHT"]);
Rectangle Resolution;
float WidthMultiplicationFactor;
float HeightMultiplicationFactor;

统一打算时显示屏分辨率保存在App.config文件中。

<add key ="DESIGN_TIME_SCREEN_WIDTH" value="1920"/>
<add key ="DESIGN_TIME_SCREEN_HEIGHT" value="1080"/>

当类的3个实例被创立时,当前的解析被提要求构造函数。
之后调用该类的SetMultiplicationFactor()方法。
这种方法通过将近期分辨率除以设计时间分辨率来获取缩放因子。

public Responsive(Rectangle ResolutionParam)
{
    Resolution = ResolutionParam;
}

public void SetMultiplicationFactor()
{
    WidthMultiplicationFactor = Resolution.Width / WIDTH_AT_DESIGN_TIME;
    HeightMultiplicationFactor = Resolution.Height / HEIGHT_AT_DESIGN_TIME;
}

举例,该应用程序设计在壹九一8×10八十多分辨率。
假如此应用程序在分辨率为拾二4×76八的Computer上运维,则WidthMultiplicationFactor和HeightMultiplicationFactor更换如下:

WidthMultiplicationFactor = 1024/1920 = 0.533
HeightMultiplicationFactor = 768/1080 = 0.711

末段有三种重载方法,它们为应用程序控件提供响应式解决方案(最棒大小,地方和字体大小)的最终方法。

public int GetMetrics(int ComponentValue)
{
    return (int)(Math.Floor(ComponentValue * WidthMultiplicationFactor));
}

public int GetMetrics(int ComponentValue, string Direction)
{
    if (Direction.Equals("Width") || Direction.Equals("Left"))
        return (int)(Math.Floor(ComponentValue * WidthMultiplicationFactor));
    else if (Direction.Equals("Height") || Direction.Equals("Top"))
        return (int)(Math.Floor(ComponentValue * HeightMultiplicationFactor));
    return 1;
}

举例,假诺存在宽度=四陆伍,高度=7贰,左=36陆,顶端=四一和字体大小=40的控件,则该措施重临提出的轻重,位置和字体大小为:

Width = 465 * 0.533 = 248
Height = 72 * 0.711= 51
Left = 366 * 0.533= 195
Top = 41 * 0.711= 29
Font-size = 40 * 0.533 = 21

骨子里,那么些措施再次回到缩放的控件与大小、地方和字体大小,而这么些值是体现的最棒值。

使用 Responsive Class

咱俩须求的是以其余须求响应的款式简单地成立那么些类的指标。
当前的分辨率是在构造函数中提供的, 之后的办事正是确立所需的乘法因子。

Responsive ResponsiveObj;
ResponsiveObj = new Responsive(Screen.PrimaryScreen.Bounds);
ResponsiveObj.SetMultiplicationFactor();

在那未来,表单的有着控件都将每一个传递,以在表单的加载事件中调治大小和另行定位。
这一个调用在下边的代码中实现。 它所做的是率先将窗体定位到荧屏的主导。
小编在此地安装了一个校准常数(30),为顶级的垂直地方加多控件,这大概因开荒职员而异。
之后,表单的每叁个控件都会再一次定位,调治大小,人己一视复校准字体大小。

private void ResponsiveForm_Load(object sender, EventArgs e)
{
    Width = ResponsiveObj.GetMetrics(Width, "Width");           // Form width and height set up.
    Height = ResponsiveObj.GetMetrics(Height, "Height");
    Left = Screen.GetBounds(this).Width / 2 - Width / 2;        // Form centering.
    Top = Screen.GetBounds(this).Height / 2 - Height / 2 - 30;  // 30 is a calibration factor.

    foreach (Control Ctl in this.Controls)
    {
        Ctl.Font = new Font(FontFamily.GenericSansSerif, 
                   ResponsiveObj.GetMetrics((int)Ctl.Font.Size), FontStyle.Regular);
        Ctl.Width = ResponsiveObj.GetMetrics(Ctl.Width, "Width");
        Ctl.Height = ResponsiveObj.GetMetrics(Ctl.Height, "Height");
        Ctl.Top = ResponsiveObj.GetMetrics(Ctl.Top, "Top");
        Ctl.Left = ResponsiveObj.GetMetrics(Ctl.Left, "Left");
    }
}

示例

以下是2个特别轻便的表单,当中积攒1个data
gird,1个label,2个textbox和二个button。
下面包车型客车图形以三种分化的分辨率截取。
下边包车型客车截图是在1917x十77分辨率下截取的:
图片 1

下边包车型地铁截图是在1360×7七十多分辨率下截取的:
图片 2

上面包车型地铁截图是在拾2四x7陆1伍分辨率下截取的:
图片 3

实在,通过减少/扩展和另行定位调整到一级水准,Form在分裂的分辨率下看起来是1律的。

代码调治

就像是我们对垂直中央定位所做的那样,大家兴许须求安装有些参数来调度总体布局。

除此以外,建议开辟者尝试以分歧的分辨率查看表单的外观,以确认全部的控件都以可见的,并根据预期在显示屏上科学定位。

除外,对于二个大致的表单,这是3个通用的艺术,它若是表单的保有控件都负有那个属性—宽度,低度,左侧,最上端和字体大小。但是,实情并非如此。有局地表单控件不具有全体那几个属性。例如,图片框没有font-size属性。因而,假使这么的事态下并未有刚烈管理,运行代码将会招致运维时特别。本文意在介绍这种格局,开拓职员需求依靠真实意况开展校准。建议的法门如下:

private void ResponsiveForm_Load(object sender, EventArgs e)
{
    Width = ResponsiveObj.GetMetrics(Width, "Width");           // Form width and height set up.
    Height = ResponsiveObj.GetMetrics(Height, "Height");
    Left = Screen.GetBounds(this).Width / 2 - Width / 2;        // Form centering.
    Top = Screen.GetBounds(this).Height / 2 - Height / 2 - 30;  // 30 is a calibration factor.

    foreach (Control Ctl in this.Controls)
    {
        if (Ctl is PictureBox)
        {
            Ctl.Width = ResponsiveObj.GetMetrics(Ctl.Width, "Width");
            Ctl.Height = ResponsiveObj.GetMetrics(Ctl.Height, "Height");
            Ctl.Top = ResponsiveObj.GetMetrics(Ctl.Top, "Top");
            Ctl.Left = ResponsiveObj.GetMetrics(Ctl.Left, "Left");
        }
        else
        {
            Ctl.Font = new Font(FontFamily.GenericSansSerif, 
                                ResponsiveObj.GetMetrics((int)Ctl.Font.Size), FontStyle.Regular);
            Ctl.Width = ResponsiveObj.GetMetrics(Ctl.Width, "Width");
            Ctl.Height = ResponsiveObj.GetMetrics(Ctl.Height, "Height");
            Ctl.Top = ResponsiveObj.GetMetrics(Ctl.Top, "Top");
            Ctl.Left = ResponsiveObj.GetMetrics(Ctl.Left, "Left");
        }
    }
}

恐怕会依据业务员须求和控件的习性来调治代码。
其余,大概须求为不一致的控件类型引进愈来愈多的重载方法。

其他

如前所述,还有其余一些措施,比方利用WPF,使用anchoring/docking等,那是3个更智慧的选项。
假诺表单上有数千个控件,则大概会遇到加载延迟。
然则,那点延迟对未来运转高效的微管理器来说小难题。
这种艺术只是在表单的加载时才实施三遍调用操作,因而不会带来沉重的性质下跌的标题。

结尾

成立响应式WinForm应用程序,依照机器的运作时刻分辨率自动调治大小,重新定位字体大小仁同一视复校准字体大小,那是壹种面向开拓人士的方法。
只需将该类增加到品种中,在App.config文件中设置规划时分辨率,然后在窗体的加载事件中增多响应代码。
So easy!