早在18年,博主第一次开始写博客,内容为 C# 上位机开发,写完后收获了不错的阅读量和好评:
这个系列存在的问题就是没有进行界面布局,所有的控件都是固定位置,所以时隔多年,再次利用空闲时间学习WinForm如何进行界面控件布局。
Github开源仓库:https://github.com/Mculover666/SerialAssistant。
Anchor意味锚点,可以将控件设置到某个固定的位置,随着窗口大小的改变,控制在窗口中的相对位置不变。
① 控件位于右上角/左上角/右下角/左下角
设置Anchor属性锚点在上侧和右侧,意味着控件相对于父控件,上侧和右侧的位置不变:
运行效果如下:
② 控件水平居中/垂直居中
首先将控件放置于水平居中位置:
点击后控件自动位于水平居中位置,接着设置Anchor属性,取消左右锚点,只设置上侧锚点:
这样控件一直位于水平居中位置:
同理,控件垂直居中只需要设置左侧或者右侧的锚点,取消上侧和下侧的锚点即可。
控件水平垂直都居中只需要取消上下左右所有的锚点即可。
③ 控件水平拉伸/垂直拉伸
设置Anchor属性,设置上侧锚点以及左右锚点:
演示效果如下:
Dock意味停靠,可以将控件停靠到某一侧或者中央。
① 使面板(Panel)停靠在某一侧(上/下/左/右/中)
在窗口中添加一个Panel,此时Panel的父控件是窗口(From),为了方便查看Panel的大小和位置,先给panel设置一个背景颜色,然后设置 Dock 属性为上侧停靠:
运行结果如图:
同样,可以设置其停靠在上/下/左/右中的某一侧。
设置为中间(Fill)时,会将整个父控件填满:
② 多个panel使用Dock布局
按照panel1至panel5的顺序依次添加panel,并设置Dock属性,如图:
因为panel4的添加在panel2和panel3之后,所以就添加在了剩余空间的底部。
如果换一种顺序添加,则又是另一种效果,如图:
所以在使用Dock属性时,一定要注意添加控件的先后顺序。
当界面大小变化时:
在实际软件开发的时候,如果使用布局器,我们应该按照从大往小的思路来布局,注意两点即可:
① Anchor属性和Dock属性是相对父控件而言的,所以可以进行嵌套;
② Anchor属性和Dock属性只能二选一,不能同时使用。
接下来我们以串口助手为例,设计一个界面。
首先划分为三个大块:
接着分别在panel2中嵌套,组合出设置界面;在panel3中嵌套,组合出发送数据和接收数据界面。
左侧设置区分为三个区:串口设置区,接收设置区,发送设置区。
特别说明:串口设置区,接收设置区,发送设置区应该使用GroupBox控件,可以在左上角显示名称,效果要优于使用panel,效果如图:
这三个区在界面动态变化时并不需要变化,所以简单添加三个Panel即可,默认会设置Anchor属性为左上。
窗口动态变化时界面效果如图:
串口设置区中只有Label和ComboBox,在界面动态变化时并不需要变化,所以简单的拖放即可,默认会设置Anchor属性为左上。
右侧数据区包括串口接收数据区和串口发送数据区,在之前设计绿色这块窗口时,已经设置了相对于父控件(窗口Form)的Dock属性为Fill,所以在动态变化时,绿色窗口会永远填满窗口。
在一些场景下,我们也需要将串口发送数据区放大一点,这个时候就需要用到splitContainer这个容器,它提供了动态的两个Panel,但是两个panel间分离,可以由用户调整大小。
拖入一个该控件放入绿色框中,填满整个区域,设置属性为垂直分离:
再分别给内部的panel1和panel2设置不同的颜色,运行程序,可以看到效果:
放大之后再看效果,简直完美:
用户改变两个缓冲区的大小:
实验完毕后,取消两个内置panel的颜色,接着下面的设计:
串口数据接收区使用TextBox,并开启多行显示:
接着拖动TextBox的大小,填满整个父控件(内置Panel1),然后设置Anchor属性为上下左右:
串口数据发送区使用TextBox,并开启多行显示,同时还要再设置一个发送按钮,再添加一个comboBox用于记录历史发送。
拖放好发送按钮的位置,设置为只向右侧相对位置不变:
然后再拖放好TextBox的位置,设置Anchor属性为上下左右都不变,这样当窗口变化时,TextBox就会拉伸填充了:
最后拖放好ComBox的位置,设置Anchor属性为左侧、右侧、下侧有锚点,这样当窗口变化时,可以跟随底部变化,并且进行水平拉伸:
至此,串口助手界面搞定,查看一下效果:
最大化窗口,看看效果:
非常完美!
底部状态栏设计的信息主要有:
其中状态信息单独设置一个panel,里面用标签Label即可,设置Dock属性在Left即可;
版本信息也单独设置一个panel,里面添加一个linkLabel,设置Dock属性在Right即可;