WinForm窗体自适应分辨率

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

在这里我们只考虑相对于自己窗体的窗口坐标更简单,也就是成比例变化。为了多个窗体共用,我在这里创建一个类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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/574943.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ping端口_干货分享:shell脚本批量telnet ip 端口

问1&#xff1a;亲&#xff0c;请教个问题&#xff0c;我这边有200台服务器&#xff0c;怎么看它是否在线呢&#xff1f;答&#xff1a;简单&#xff0c;下载个PingInfoView直接批量ping下&#xff0c;能ping通的就在线&#xff0c;反之离线。问2&#xff1a;那怎么看我这200台…

关于PHP代码的开始和结束标签书写,关于PHP结束标签?gt;的使用细节

当PHP解析一个文件时&#xff0c;会寻找开始&#xff0c;标记告诉PHP开始和停止解释其中的代码。此种方式的解析可以使PHP嵌入到各种不同的文档中&#xff0c;凡是在一对开始和结束标记之外的内容都会被PHP解析器忽略。大多数情况下PHP都是嵌入在HTML文档中的。单行注释仅仅注释…

IIS 7.0 部署MVC

开发的MVC 3.0 项目&#xff0c;在部署服务上还是与需要花一点功夫&#xff0c;这里把遇到的问题罗列出来。 本文主要介绍IIS 7.5中安装配置MVC 3.0的具体办法&#xff01; 部署必备&#xff1a; Microsoft .net FrameWork 4.0安装包 安装ASP.NET MVC 3.0 如果 Asp.NET v4.0.30…

python 爬虫 包_Python爬虫包BeautifulSoup实例(三)

一步一步构建一个爬虫实例&#xff0c;抓取糗事百科的段子先不用beautifulsoup包来进行解析第一步&#xff0c;访问网址并抓取源码# -*- coding: utf-8 -*-# Author: HaonanWu# Date: 2016-12-22 16:16:08# Last Modified by: HaonanWu# Last Modified time: 2016-12-22 20:17:…

phpdesigner8 php7.0,大家千万别用PHPDesigner8 的项目替换,多说是泪,改整个站点中!

PHP PHPDesigner 项目 替换 乱码 大家千万别用PHPDesigner8 的项目替换,多说是泪,改整个站点中!整个项目中文全是乱码,部分文件UTF-8编码变成ANSI编码,不知道有没有大神教我怎么还原回复讨论(解决方案)没有用svn么&#xff1f;没有的话碰上这种问题真的是蛋痛.没有用svn么&…

python 日志不会按照日期分割_python实现日志按天分割

本文实例为大家分享了python实现日志按天分割的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下日志格式&#xff1a;1.1.1.1 - - [30/Apr/2015:00:34:55 0800] “POST /iDataService/services/MemRoomService HTTP/1.0” 200 405 “-” “Axis/1.4” “-”1.1.1.1 - …

如何分析网站日志文件

很多新手站长对于如何分析网站日志文件一筹莫展&#xff0c;打开.log日志文件看到的只有密密麻麻的数字和字母&#xff0c;细看能看出是什么含义&#xff0c;但是想要系统科学的去进行分析太耗时间&#xff0c;这时一般只能借助于第三方日志分析软件&#xff0c;而下面介绍一种…

不是有效的函数或过程名_过程和函数

VBA代码有两种组织形式&#xff0c;一种是过程&#xff0c;另一种就是函数。其实过程和函数有很多相同之处&#xff0c;除了使用的关键字不同之外&#xff0c;还有不同的是&#xff1a;函数有返回值&#xff0c;过程没有。函数可以在Access窗体&#xff0c;查询中像一般的Acces…

怎么下载php源文件,设计了一个php下载当前文件,却把php源文件下载下来了,为何?...

当我点a.txt下载后&#xff0c;打开txt文件&#xff0c;发现里面的内容不是a.txt本身的内容&#xff0c;而是该php文件中除了php代码的其他文本内容&#xff0c;这样该如何解决&#xff1f;资料下载回复讨论(解决方案)$file_name”a.txt”;$file_dir”./”;if(!file_exists($fi…

自己构造构造函数

/*** description 扩展function的原型* function* obj this的上下文*/if(!Function.prototype.bind){Function.prototype.bind function(obj){var slice [].slice,args slice.call(arguments,1),self this,nop function(){},bound function(){return self.apply(this ins…

浏览器快捷键_浏览器快捷键,让你事半功倍

随着互联网时代的发展&#xff0c;手机、电脑已经成为人们生活中不可或缺得一部分&#xff0c;无论是生活还是工作。尤其是办公室族&#xff0c;几乎每天都要面对电脑7/8个小时&#xff0c;查找各种信息或者浏览新闻&#xff0c;浏览器无可厚非的成为了装机必备的软件&#xff…

java f.lenth返回值,这个是什么意思,求仔细说明

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼import java.io.File;import java.io.IOException;import java.util.Random;import java.util.Scanner;public class Test {boolean flagtrue;int count;String word;public static void main(String[] args) {Test t new Test();…

MySQL中的常用函数

1、 字符串函数 2、 字符串函数 模数和被模数任何一个为NULL结果都为NULL。 3、 日期和时间函数 4、 流程函数 5、其他常用函数 MySQL Administrator&#xff08;图形化管理工具&#xff09; MySQL Query Brower&#xff08;客户端查询工具&#xff09; phpMyAdmin&#xff08;…

小程序iconfont报错_【经验】开发微信小程序经验总结

一.技术要求(语言方面)有H5或H4和CSS3的书写经验&#xff0c;没有建议观看B站中的 渡一教育-Web前端开发(html css不算语言)。强烈推荐他们的视频&#xff0c;主讲人没有口音且视频质量很高&#xff0c;是哈尔滨理工大学毕业之后进入阿里工作的Web前端工程师 姬成老师。JavaScr…

超市商品管理系统php,超市商品管理系统(含附源代码)超市商品管理系统(含附源代码).doc...

超市商品管理系统(含附源代码)超市商品管理系统(含附源代码)黔南民族师范学院软件设计课程设计报告题 目&#xff1a; 超市商品管理系统系部名称&#xff1a;计科系专业名称&#xff1a;信息管理与信息系统班 级&#xff1a;B12计信班学号&#xff1a;1208045139学生姓名 &…

IOS_OC_id ,NSObject, idlt;NSObjectgt;差别

我们常常会混淆下面三种申明&#xff08;我是没有留意过&#xff09;&#xff1a; 1. id foo1; 2. NSObject *foo2; 3. id<NSObject> foo3;第一种是最经常使用的&#xff0c;它简单地申明了指向对象的指针&#xff0c;没有给编译器不论什么类型信息&#xff…

python移动端web开发代码_移动web前端开发,前端开发工作总结,移动端页面开发-我主页-一个前端程序猿的博客...

热门推荐html/css一、escape和它们不是同一类简单来说&#xff0c;escape是对字符串(string)进行编码(而另外两种是对URL)&#xff0c;作用是让它们在所有电脑上可读。编码之后的...标签&#xff1a;03-22html/css场景&#xff1a; 在项目开发过t程中需要找到url中某个参数的值…

tablednd保存 php,JQuery-tableDnD 拖拽的基本使用介绍

在页面上导入js复制代码 代码如下:jquery-1.3.2.min.jsjquery.tablednd_0_5.js注意&#xff1a;一定要先导入jquery-1.3.2.min.js 否则出错。建table复制代码 代码如下:1Onesome text2Twosome text3Threesome text4Foursome text5Fivesome text6Sixsome text插入js代码复制代码…

移动端页面0.5px border的实现

移动端上经常发现1px边框异常的粗&#xff0c;因此&#xff0c;决定用伪类配合css3来实现0.5px边框 代码如下&#xff1a; 1 <!doctype html>2 <html lang"en">3 <head>4 <meta content"widthdevice-width, initial-scale1.0, maximum-sc…

python 漂亮界面demo_在这个什么都看脸的时代,如何用 GUI 提高 python 程序的颜值?...

0、前言有不少初学者会问&#xff0c;Python 写的程序看起来好丑啊&#xff0c;只能在那个黑黑的框里运行吗&#xff1f;隔壁家的 JS 好像挺好看的&#xff0c;还能有酷炫效果呢……其实呢&#xff0c;术业有专攻&#xff0c;Python 擅长的领域在后台服务器、数据处理、科学计算…