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

在这里我们只考虑相对于自己窗体的窗口坐标更简单,也就是成比例变化。为了多个窗体共用,我在这里创建一个类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事件触发时才能检测出窗体中包含控件,这几个事件的区别我实在不知道有声明区别。希望读者给出帮助。

转载于:https://www.cnblogs.com/CandiceW/p/4226711.html

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

  1. C#——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. ICCV 2019 | 加一个任务路由让数百个任务同时跑起来,怎么做到?
  2. 确认AD DS域是否正常
  3. centos7 cmake安装mysql_centos7 安装cmake
  4. Kafka使用遇到的坑
  5. C# 系统应用之调用SDelete程序粉碎文件及基础原理知识
  6. 实现本机拷贝带进度的方法
  7. 在.NET Core中用最原生的方式读取Nacos的配置
  8. Service Fabric 与Ocelot 的集成
  9. C语言 ---文件读取
  10. php开发工程师考试试卷,腾讯PHP开发工程师面试试卷
  11. SQL中 拆解函数 之 strsplit()
  12. Thrift java.net.SocketException: Broken pipe问题分析定位
  13. 贪吃蛇代码--c语言版 visual c++6.0打开
  14. 用计算机绘制工作表,实用计算机机械图样绘制技法
  15. 介绍 Jersey 依赖
  16. html字幕精灵图标,视频加字幕精灵
  17. 实施ERP系统软件的十个好处,你造吗?
  18. 记一次 ERROR scheduler.AsyncEventQueue: Dropping event from queue shared导致OOM
  19. 【情人节表白神器:送她一个HTML动态表白网站 带源码】
  20. Scrapy爬虫框架,爬取小说网的所有小说

热门文章

  1. 算法竞赛入门经典 第五章总结1
  2. linux 开启关闭tomcat服务器端口,linux系统安装、启动和关闭tomcat
  3. Java调用虚拟键盘输入法_Android 点击屏幕空白处收起输入法软键盘(手动打开)...
  4. 地图自定义图标_如何在H5里添加地图导航?这份教程请收藏!
  5. java打印倒立直角三角形
  6. android安全性发展,Android未来发展 安全是重点
  7. 苹果php环境,苹果电脑安装PHP环境步骤-PHP问题
  8. bigdicmal除法精度设置_BigDecimal 高精度计算 熟悉扩展,java除法保留小数问题
  9. php配置email支持_使用PHPMailer实现PHP发邮件功能
  10. SkyEye——汽车电子系统仿真测试工具