WinForm响应式布局规划试行

引言

开创响应式WinForm应用程序并不那么轻便。
响应式布局,在此小编指的是应用程序在不一样荧屏分辨率下的可用性。
对于WinForm应用程序,大家要求显然地依照分辨率来调节控件的尺寸和重复定位。
尽管在利用WPF时有相关的实行应用,通过接纳控件的docking和anchoring,或行使panels等方法,但本文提供了一种将响应式应用于WinForm应用程序的两样方式。

背景

自个儿在1个和谐布置的大约游戏中相见了难点:小编设计了壹台分辨率为191陆x拾80的机器,
可是当自己筹划在台式机电脑上海人民广播广播台播时,发掘应用程序边界跑到荧屏之外。因而很有需要让程序来适应分化分辨率的器具,而不是让用户来适应程序。
因而,笔者对代码实行了革新。

技术

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

代码

The Responsive Class – Responsive.cs

制造3个类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"/>

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

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

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

比方,该应用程序设计在一九二零x拾七17分辨率。
如若此应用程序在分辨率为拾二肆x76八的微型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陆,最上端=41和字体大小=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");
    }
}

示例

以下是3个特别轻巧的表单,在那之中带有多少个data
gird,叁个label,1个textbox和3个button。
下边包车型地铁图形以两种分歧的分辨率截取。
上面包车型地铁截图是在壹玖一七x十76分辨率下截取的:
图片 1

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

下边包车型地铁截图是在10贰四x7711分辨率下截取的:
图片 3

实际,通过压缩/扩充和再一次定位调整到一级水平,Form在分化的分辨率下看起来是同样的。

代码调解

就像大家对垂直中央定位所做的那么,大家恐怕供给设置有些参数来调动总体布局。

除此以外,提议开垦者尝试以分裂的分辨率查看表单的外观,以确认全数的控件都以可知的,并依据预期在显示器上正确定位。

除此而外,对于二个粗略的表单,那是二个通用的办法,它就算表单的装有控件都具备这么些属性—宽度,中度,左边,最上部和字体大小。可是,真实情形并非如此。有1对表单控件不具有全体这么些属性。举个例子,图片框未有font-size属性。因而,假使这么的气象下并未有刚烈管理,运营代码将会促成运营时10分。本文意在介绍这种办法,开荒职员必要依附实况开始展览校准。建议的不二秘诀如下:

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等,那是1个更智慧的选取。
要是表单上有数千个控件,则只怕会超出加载延迟。
不过,那点延迟对前些天运营高效的Computer来讲小难点。
这种办法只是在表单的加载时才推行1次调用操作,因而不会拉动致命的天性降低的标题。

结尾

创制响应式WinForm应用程序,依照机器的周转时刻分辨率自动调解大小,重新定位字体大小并再一次校准字体大小,那是壹种面向开荒职员的秘籍。
只需将该类增加到品种中,在App.config文件中装置规划时分辨率,然后在窗体的加载事件中拉长响应代码。
So easy!