我们自己编写程序的界面,会遇到各种屏幕分辨率,只有自适应才能显的美观。实际上,做到这点也很简单,就是首先记录窗体和它上面控件的初始位置和大小,当窗体改变比例时,其控件的位置和大小也按此比例变化即可。因为窗体上控件的位置和大小是相对于自己所在的窗体的,也就是所谓的窗口坐标。

  在这里我们只考虑相对于自己窗体的窗口坐标更简单,也就是成比例变化。为了多个窗体共用,我在这里创建一个类AutoSizeFormClass ,1.使用它去记录窗体和其控件的初始位置和大小,2.判断窗体中的控件是否为容器控件,如果是记录容器控件中的控件的初始位置和大小3.根据窗体变化了的大小,成比例地实现其控件的水平和垂直方向的变化,也就是自适应。
 
二。使用方法
  使用方法很简单,
  1.把自适应的类整体复制到你的工程命名空间里,
     然后在需要自适应的窗体中做2步即可:
  2.声明自适应类实例。
  3.为窗体添加大小改变事件,并在其方法中,调用类的自适应方法,完成自适应

通过上面的介绍我们会发现其中的几个实现难点:

1.如何保存窗体的以及其中控件的位置以及大小等属性,当然我们最常用的方法就是自己定义一个实体,实体中包含我们需要保持的属性(主要包括left,top,width,height,以及fontsize属性)这个我提供的解决方案是定义一个数据结构。

普及一下结构体的知识:结构体中包含其中要存储的数据,使用结构体的好处在于可以将不同类型的数据有序的组合在一起,结构造出一个新的数据类型,不占内存空间,只用定义结构体的变量时才开辟内存空间,结构体类型的变量在内存依照其成员顺序顺序排列,所占内存空间的大小是其全体成员所占空间的总和,结构体可以作为函数的参数,函数也可以返回结构体。

看我们定义的结构体:

/// <summary>/// 声明一个结构,用于保存控件位置的基本属性。/// </summary>public struct controlRect{/// <summary>/// 控件的left属性/// </summary>public int Left;/// <summary>/// 控件的Right属性/// </summary>public int Top;/// <summary>/// 控件的Weight属性/// </summary>public int Width;/// <summary>/// 控件的High属性/// </summary>public int Height;/// <summary>/// 控件的Fontsize属性/// </summary>public float FontSize;}

然后声明一个泛型用来保存所有控件位置以及大小信息产生的结构体信息。

//这里只是列出两个容器控件分别为panel控件和groupbox控件if (c.GetType().ToString() == "System.Windows.Forms.Panel"){//要执行的代码}//如果是GroupBox控件if (c.GetType().ToString() == "System.Windows.Forms.GroupBox"){//要执行的代码}

但我发现自己很难把所有的控件都想全了,即使是想全了也会重复太多的代码,最后采取了一个很有效的方法就是加上这个判断:

if (c.Controls.Count > 0)

一旦这个判断成立就说明这个控件就是一个容器控件了。

问题3.递归调用保存控件信息类,实现所有控件(包括容器控件)的位置和大小信息的保存。

问题4.如何保存画窗体时窗体的大小,听起来有些别嘴,其实也可以说是你想要窗体呈现的大小,这个大大家好像会有疑问但虽然说窗体是控件的一种,但是进过我的实现,当我们改变分辨率的同时,比如我们原来设置窗体每次打开时最大化显示,但是无论我们编写程序时设置的窗体的大小多大,我们运行起来时窗体都会占满整个屏幕,这也是出现由于分辨率改变,大窗体中部分控件无法显示完全的原因。比如我们的做的这个很大的登陆界面,看看效果:

小分辨率下的情况:

大分辨率下应该是这样:

​我们会发现窗体最大化了。但是窗体中的控件没有跟上。

说了这么多我想大家都迫不及待的想看代码了:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace AutoSizeFormClass
{public class AutoSizeFormClass{/// <summary>/// 声明一个结构,用于保存控件位置的基本属性。/// </summary>public struct controlRect{/// <summary>/// 控件的left属性/// </summary>public int Left;/// <summary>/// 控件的Right属性/// </summary>public int Top;/// <summary>/// 控件的Weight属性/// </summary>public int Width;/// <summary>/// 控件的High属性/// </summary>public int Height;/// <summary>/// 控件的Fontsize属性/// </summary>public float FontSize;}/// <summary>/// 声明一个泛型,类型为什么的保存控件属性的结构类,/// </summary>public List<controlRect> oldCtrl = new List<controlRect>();int ctrlNo = 0;//初始化标识控件的变量为0,表示窗体本身。   /// <summary>/// 保存控件的位置和大小信息/// </summary>/// <param name="ctl">需要被保存的控件</param>private void AddControl(Control ctl){foreach (Control c in ctl.Controls){  controlRect objCtrl;objCtrl.Left = c.Left;objCtrl.Top = c.Top;objCtrl.Width = c.Width;objCtrl.Height = c.Height;objCtrl.FontSize = c.Font.Size;oldCtrl.Add(objCtrl);//**放在这里,是先记录控件本身,后记录控件的子控件,重点是前后要一致if (c.Controls.Count > 0)AddControl(c);//窗体内其余控件还可能嵌套控件(比如panel),要单独抽出,因为要递归调用}}/// <summary>/// 窗体自适应分辨率类/// </summary>/// <param name="mForm">需要进行设置的窗体</param>public void controlAutoSize(Control mForm){if (ctrlNo == 0){ //*如果在窗体的Form1_Load中,记录控件原始的大小和位置,正常没有问题,但要加入皮肤就会出现问题,因为有些控件如dataGridView的的子控件还没有完成,个数少//*要在窗体的Form1_SizeChanged中,第一次改变大小时,记录控件原始的大小和位置,这里所有控件的子控件都已经形成controlRect cR;cR.Left = mForm.Left;cR.Top = mForm.Top;cR.Width = mForm.Width;cR.Height = mForm.Height;cR.Width = int.Parse(mForm.Tag.ToString().Split(',')[0]);cR.Height = int.Parse(mForm.Tag.ToString().Split(',')[1]);cR.FontSize = mForm.Font.Size;oldCtrl.Add(cR);//第一个为"窗体本身",只加入一次即可                AddControl(mForm);//窗体内其余控件可能嵌套其它控件(比如panel),故单独抽出以便递归调用}float wScale = (float)mForm.Width / (float)oldCtrl[0].Width;//新旧窗体之间的比例,与最早的旧窗体比较float hScale = (float)mForm.Height / (float)oldCtrl[0].Height;//.Height;ctrlNo = 1;//进入=1,第0个为窗体本身,窗体内的控件,从序号1开始AutoScaleControl(mForm, wScale, hScale);//窗体内其余控件还可能嵌套控件(比如panel),要单独抽出,因为要递归调用}/// 设置控件的属性/// </summary>/// <param name="ctl">需要设置的控件</param>/// <param name="wScale">调整的高度比例</param>/// <param name="hScale">调整的宽度比例</param>private void AutoScaleControl(Control ctl, float wScale, float hScale){int ctrLeft0, ctrTop0, ctrWidth0, ctrHeight0;float ctrFontSize0;//第1个是窗体自身的 Left,Top,Width,Height,所以窗体控件从ctrlNo=1开始foreach (Control c in ctl.Controls){ //获得控件原有的位置和大小信息ctrLeft0 = oldCtrl[ctrlNo].Left;ctrTop0 = oldCtrl[ctrlNo].Top;ctrWidth0 = oldCtrl[ctrlNo].Width;ctrHeight0 = oldCtrl[ctrlNo].Height;ctrFontSize0 = oldCtrl[ctrlNo].FontSize;//设置控件新的位置和大小信息。c.Left = (int)((ctrLeft0) * wScale);//新旧控件之间的线性比例。控件位置只相对于窗体c.Top = (int)((ctrTop0) * hScale);//c.Width = (int)(ctrWidth0 * wScale);//只与最初的大小相关,所以不能与现在的宽度相乘 c.Height = (int)(ctrHeight0 * hScale);//c.Font = new Font(c.Font.Name, (float)(ctrFontSize0 * wScale));//设置控件中字体的大小以适应控件的大小ctrlNo++;//累加序号//**放在这里,是先缩放控件本身,后缩放控件的子控件,重点是前后要一致(与保存时)if (c.Controls.Count > 0)AutoScaleControl(c, wScale, hScale);//窗体内其余控件还可能嵌套控件(比如panel),要单独抽出,因为要递归调用}}}
}代码中的注释比较详细了,如果你想实现窗体的自适应分辨率,你只需要在窗体的Layout事件中添加如下代码:/// <summary>/// 声明一个窗体自适应分辨率类/// </summary>public AutoSizeFormClass As = new AutoSizeFormClass();/// <summary>/// 在窗体的layout事件中调用/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Form1_Layout(object sender, LayoutEventArgs e){As.controlAutoSize(this);}

最后想说的是为什么用layout事件,不用Resize或者是SizeChanged事件,这个我查了好长时间,也自己试了所有的方法,但还是没能明白只是发现这几个事件的触发顺序是不同的首先触发的是Resize→然后是SizeChanged→然后是layout→最后是Load事件,是不是把适应分辨率的代码写在那个事件下都可以呢,这个我也尝试了,当窗体中含有tabcontrol控件时只有layout事件触发时才能检测出窗体中包含控件,这几个事件的区别我实在不知道有声明区别。希望读者给出帮助。

C#——WinForm窗体自适应分辨率相关推荐

  1. WinForm窗体自适应分辨率

    我们自己编写程序的界面,会遇到各种屏幕分辨率,只有自适应才能显的美观.实际上,做到这点也很简单,就是首先记录窗体和它上面控件的初始位置和大小,当窗体改变比例时,其控件的位置和大小也按此比例变化即可.因 ...

  2. Winform窗体控件自适应大小

    自己写的winform窗体自适应大小代码,代码比较独立,很适合贴来贴去不会对原有程序造成影响,可以直接继承此类或者把代码复制到自己的代码里面直接使用 借鉴了网上的一些资料,最后采用重写WndProc方 ...

  3. WPF窗体自适应电脑分辨率的问题

    如何解决WPF窗体自适应电脑分辨率 前言 一.DockPanel 二.使用方法 1.引入代码 总结 前言 很多时候做WPF窗体的控件在运行展示的时候会有放大缩小的操作,这时候有些控件或者控件的文本就不 ...

  4. winformbutton边框怎么改_C# WinForm窗体控件Panel修改边框颜色以及边框宽度方法

    C# WinForm窗体控件Panel修改边框颜色以及边框宽度方法 1.新建组件这里可以自定义一个Panel控件起名为PanelEx 2.增加一个BoderColor属性和BoderSize属性 pr ...

  5. 自适应分辨率可扩展二层JS下拉菜单

    1. S下拉菜单原理 下拉菜单实际上就是在开始的时候显示一级或者说是主菜单(图一).当触发条件(例如:鼠标移动到上面时)显示次级菜单(图二). 图一 图二 那么如何实现这样的效果呢.其实很简单.所有的 ...

  6. 如何在多线程中调用winform窗体控件2——实例篇

    如何在多线程中调用winform窗体控件2--实例篇 针对之前文章<如何在多线程中调用winform窗体控件>,下面举个我项目中的实际案例,这是一个我自定义控件在异步设置焦点时的代码.在新 ...

  7. 重绘Winform窗体

    本文转载自:http://www.cnblogs.com/encoding/p/5603080.html 按照惯例,先来几张样例图(注:为了展示窗口阴影效果,截图范围向外扩展了些,各位凭想象吧). 还 ...

  8. C#:绘制Winform窗体

    Winform窗体缺少左上角效果: public void SetWindowRegion(){System.Drawing.Drawing2D.GraphicsPath FormPath;FormP ...

  9. WinForm窗体缩放动画

    WinForm自带的窗体大小发生改变的时候,当内存不够的时候,会出现界面停滞的现象,会出现许多的条条纹纹,给人很不好的感觉,这里提供一个WinForm窗体缩放时会有一个渐变的动画效果给大家. 思路是这 ...

最新文章

  1. H5嵌入原生开发小结----兼容安卓与ios的填坑之路
  2. 【Paper】2021_Robust Near-Optimal Coordination in Uncertain Multiagent Networks With Motion Const
  3. Java-工具类之ZIP压缩解压
  4. 跟我一起学.NetCore之熟悉的接口权限验证不能少(Jwt)
  5. ftp 断点续传 Android,Android使用FTP实现断点续传
  6. RTMP代理的协议规范(RtmpProxy)
  7. Visual Studio 2012 Update 4 RC 启动调试失败解决方案
  8. ASCII码对照表(参考用)
  9. 微软亚洲研究院20周年庆典:纳德拉致敬、沈向洋展望
  10. C/C++面试题总结
  11. 计算机的发展经历阶段应用领域,手机的发展经历了哪3个阶段?
  12. 知识点026-rsync命令的使用
  13. python csv wordpress xmlrpc_wordpress_xmlrpc模块批量自动发布文章到wordpress - 老牛博客...
  14. LintCode Python 简单级题目 112.删除链表中的重复元素
  15. javascript 替换全部字符串
  16. 不是吧,还有人不会做国庆头像小程序(可开通流量主,赚零花钱)
  17. Python:正则表达式 flags 参数
  18. Xubuntu22.04之连接filco蓝牙键盘
  19. 阿里新推出“阿里云网盘”App,有机会干掉“百度网盘”吗?
  20. 《桃花庵歌》——唐伯虎

热门文章

  1. 手把手教你写android项目@第一期项目——身份证查询创新
  2. 成都玖益科技:优化店铺关键词的技巧
  3. redis的rdb持久化的cow技术(写时复制)及fork子进程理解
  4. 大师罗莊自己整理的绘画色彩笔记
  5. 手机status500_HTTP Status 500 -
  6. aws认证有用吗?怎么备考AWS认证考试?
  7. 如何查看bilibili分集合集视频总时长
  8. 为什么别人家的APP,上报日志就这么省流量?
  9. 关于ARM芯片中内存架构的疑惑记录
  10. 阿里 MySQL 规约_阿里手册 Mysql 数据库规约