精华内容
下载资源
问答
  • C# Winform自适应分辨率的类

    热门讨论 2013-05-24 18:08:24
    C# Winform自适应分辨率的类自适应分辨率的类
  • 如果a成立那么里面的控件如何做到按照屏幕分辨率等比缩放呢,比如1920*1080的开发环境放到1366*768等这种情况 我的想法是,既然屏幕分辨率和地图层级一样固定(大差不差),能不能把分辨率对应的控件宽高等比缩放以...
  • WinForm窗体自适应分辨率

    万次阅读 多人点赞 2014-02-18 21:57:00
    我们自己编写程序的界面,会遇到各种屏幕分辨率,只有自适应才能显的美观。实际上,做到这点也很简单,就是首先记录窗体和它上面控件的初始位置和大小,当窗体改变比例时,其控件的位置和大小也按此比例变化即可。...
        我们自己编写程序的界面,会遇到各种屏幕分辨率,只有自适应才能显的美观。实际上,做到这点也很简单,就是首先记录窗体和它上面控件的初始位置和大小,当窗体改变比例时,其控件的位置和大小也按此比例变化即可。因为窗体上控件的位置和大小是相对于自己所在的窗体的,也就是所谓的窗口坐标。  
      在这里我们只考虑相对于自己窗体的窗口坐标更简单,也就是成比例变化。为了多个窗体共用,我在这里创建一个类AutoSizeFormClass ,1.使用它去记录窗体和其控件的初始位置和大小,2.判断窗体中的控件是否为容器控件,如果是记录容器控件中的控件的初始位置和大小3.根据窗体变化了的大小,成比例地实现其控件的水平和垂直方向的变化,也就是自适应。
     
    二。使用方法
      使用方法很简单,
      1.把自适应的类整体复制到你的工程命名空间里,
         然后在需要自适应的窗体中做2步即可:
      2.声明自适应类实例。
      .为窗体添加大小改变事件,并在其方法中,调用类的自适应方法,完成自适应

        通过上面的介绍我们会发现其中的几个实现难点:
        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;
            }
        然后声明一个泛型用来保存所有控件位置以及大小信息产生的结构体信息。
            /// <summary>
            /// 声明一个泛型,类型为什么的保存控件属性的结构类,
            /// </summary>
            public List<controlRect> oldCtrl = new List<controlRect>();

        

             问题2,如何判断一个控件是否为容器控件,因为我们知道容器控件包含的种类有很多,如panel、groupbox、tabControl等控件,这些也只是我们最常用的,原来我使用的方法是逐个的判读,如下

        //这里只是列出两个容器控件分别为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事件触发时才能检测出窗体中包含控件,这几个事件的区别我实在不知道有声明区别。希望读者给出帮助。




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

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

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

    展开全文
  • Winform开发时 有时会碰到窗体 碰到不同分辨率而导致 有些控件被盖住的情况 所以还是 让窗体根据电脑分辨率显示大小吧! 第一步:添加类 类中添加实现功能的代码 using System; using System.Collections....

    Winform开发时   有时会碰到窗体 碰到不同分辨率而导致  有些控件被盖住的情况  所以还是  让窗体根据电脑分辨率显示大小吧!

    第一步:添加类 类中添加实现功能的代码

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;

    namespace PowerSystemByWinForm
    {
        public class AutoSizeFormClass
        {
            public struct controlRect
            {
                public int Left;
                public int Top;
                public int Width;
                public int Height;
            }

            private bool _Flag;
            public bool Flag
            {
                get { return _Flag; }
                set { _Flag = value; }
            }

            private int _Number;
            public int Number
            {
                get { return _Number; }
                set { _Number = value; }
            }

            private List<controlRect> oldCtrl;

            public void Initialize(Control mForm)
            {
                oldCtrl = new List<controlRect>();
                controlRect cR;

                cR.Left = mForm.Left;
                cR.Top = mForm.Top;
                cR.Width = mForm.Width;
                cR.Height = mForm.Height;

                oldCtrl.Add(cR);

                foreach (Control c in mForm.Controls)
                {
                    controlRect objCtrl;
                    objCtrl.Left = c.Left;
                    objCtrl.Top = c.Top;
                    objCtrl.Width = c.Width;
                    objCtrl.Height = c.Height;
                    oldCtrl.Add(objCtrl);
                }
                Flag = true;
                Number = mForm.Controls.Count;
            }

            public void ReSize(Control mForm)
            {
                if (!Flag) return;

                float wScale = (float)mForm.Width / (float)oldCtrl[0].Width;
                float hScale = (float)mForm.Height / (float)oldCtrl[0].Height;

                int ctrLeft0, ctrTop0, ctrWidth0, ctrHeight0;
                int ctrlNo = 1;

                try
                {
                    if (mForm.Controls.Count != Number) return;
                    foreach (Control c in mForm.Controls)
                    {
                        ctrLeft0 = oldCtrl[ctrlNo].Left;
                        ctrTop0 = oldCtrl[ctrlNo].Top;
                        ctrWidth0 = oldCtrl[ctrlNo].Width;
                        ctrHeight0 = oldCtrl[ctrlNo].Height;

                        c.Left = (int)(ctrLeft0 * wScale);
                        c.Top = (int)(ctrTop0 * hScale);
                        c.Width = (int)(ctrWidth0 * wScale);
                        c.Height = (int)(ctrHeight0 * hScale);
                        ctrlNo += 1;
                    }
                }
                catch
                {
                    return;
                }
            }
        }
    }


    第二步:调用类中的方法  实现窗体效果

    private void Form1_Resize(object sender, EventArgs e)
            {
                autoSize.ReSize(pnlMain);
            }

            private void Form1_Load(object sender, EventArgs e)
            {
                autoSize.Initialize(pnlMain);
            }


    大功告成   不过这只是通过我的程序  可能太复杂的程序   会出不来效果   谨提供思路!!!

    展开全文
  • 本来不爱鸡汤,今天说两句:winform开发有一个缺陷就是不能实现界面的自适应,切换不同的分辨率,或者窗体大小改变就会出现窗体显示不全的问题。这就需要自己写一个方法来实现不同情况下的自适应,WPF比Winform的一...

    今天给大家上一道硬菜。本来不爱鸡汤,今天说两句:winform开发有一个缺陷就是不能实现界面的自适应,切换不同的分辨率,或者窗体大小改变就会出现窗体显示不全的问题。这就需要自己写一个方法来实现不同情况下的自适应,WPF比Winform的一个显著优势就是可以实现自适应。今天给大家一个可以实现自适应的方案。(本篇博客代码,为本人,在本地调试通过后,手敲到博客中,难免出现敲错的状况,勿喷。代码里面的注释是比较清楚的)

    效果图:

     

    调整大小后

    新建一个AutoSizeFormClass.cs文件

    class AutoSizeFormClass
    {
        //1.声明一个结构体,记录窗体和控件的基本属性
        public struct controlRect
        {
            public string Name;
            public int Left;
            public int Top;
            public int Width;
            public int Height;
            public float FontSize;
            public FontFamily FontFamily;
        }
        //2.声明一个集合记录所有控件的属性
        //使用控件的Name作为key
        Dictionary<string,controlRect> dic=new Dictionary<string,controlRect>();
        int ctrNo=0;
        //这里是你开发环境下的分辨率
        private int ScW=1920;
        private int ScH=1080;
        //记录窗体是不是第一次加载的标记 0:第一次加载  1:重复加载
        private int IsFirstLoad=0;
        //窗体的名称
        private string FrmName=string.Empty;
        //3.创建两个函数
        //采用递归的方法将控件包含的所有控件属性记录下来(结构体的每一个属性都需要赋值)
        private void AddControl(Control ctl)
        {
            foreach(Control c in ctl.Controls)
            {
                GetCtrParameter(c);
                //使用递归函数先记录控件本身,后记录控件包含的子控件
                if(c.Controls.Count>0)
                {
                    AddControl(c);
                }
            }
        }
        //获取控件的所有属性
        private void GetCtrParameter(Control mForm)
        {
            controlRect cr;
            cr.Name=mForm.Name;
            cr.Left=mForm.Left;
            cr.Top=mForm.Top;
            cr.Width=mForm.Width;
            cr.Height=mForm.Height;
            cr.FontSize=mForm.Font.Size;
            cr.FontFamily=mForm.Font.FontFamily;
            dic.Add(cr.Name,cr);
        }
    
        //4.控件自适应大小
        public void controlAutoSize(Control mForm)
        {
            FrmName=mForm.Name;
            float wScale=0;
            float hScale=0;
            //因为有些控件和DataGridView的子空间加载时间较长,所以在Form1_SizeChanged中,
            //记录控件的原始大小和位置,第一次加载的时候先根据和开发环境的像素比例绘制窗体                
            if(IsFirstLoad==0&&ctrNo==0)
            {
                //获取当前的像素
                int SH=Screen.PrimaryScreen.Bounds.Height;
                int SW=Screen.PrimaryScreen.Bounds.Width;
                //和开发环境的像素相比获取对应的比值
                wScale=(float)SH/(float)ScH;
                hScale=(float)SW/(float)ScW;
                controlRect cR;
                cR.Name=mForm.Name;
                cR.Left=mForm.Left;
                cR.Top=mForm.Top;
                cR.Width=mForm.Width;
                cR.Height=mForm.Height;
                cR.FontSize=mForm.Font.Size;
                cR.FontFamily=mForm.Font.FontFamily;
                dic.Add(cR.Name,cR);//第一个为窗体本身
                AddControl(mForm);//递归获取所有窗体基础信息
                AutoScaleControl(mForm,wScale,hScale);//这里其实是第一次构造窗体
                IsFirstLoad=1;            
            }
            //这里是改变窗体大小时重新设置窗体的属性
            else
            {
                //新旧窗体之间的高和长的比例,与第一次加载的信息比较
                wScale=(float)mForm.Width/dic[FrmName].Width;
                hScale=(float)mForm.Height/dic[FrmName].Height;
                //将ctrNo设为1,代表为控件而非窗体
                ctrNo=1;
                //设置控件以及其嵌套的控件的比例大小,使用递归调用
                AutoScaleControl(mForm,wScale,hScale);
            }
        }
        //递归进行自适应调整
        private void AutoScaleControl(Control ctl,float wScale,float hScale)
        {
            int ctrLeft0,ctrTop0,ctrWidth0,ctrHeight0;
            float fontSize;
            FontFamily fontFamily;
            foreach(Control c in ctl.Controls)
            {
                string ctrName=c.Name;
                ctrLeft0=dic[ctrName].Left;
                ctrTop0=dic[ctrName].Top;
                ctrWidth0=dic[ctrName].Width;
                ctrHeight0=dic[ctrName].Height;
                fontSize=dic[ctrName].FontSize;
                fontFamily=dic[ctrName].FontFamily;
                //新旧控件之间的线性比例,字体大小依据高度转换
                c.Left=(int)(ctrLeft0*wScale);
                c.Top=(int)(ctrTop0*hScale);
                c.Width=(int)(ctrWidth0*wScale);
                c.Height=(int)(ctrHeight0*hScale);
                c.Font=new Font(fontFamily,fontSize*hScale);
                ctrNo++;
                //先缩放控件本身,后缩放控件的子控件
                if(c.Controls.Count>0)
                {
                    AutoScaleControl(c,wScale,hScale);
                }
                //dataGridview特殊处理
                if(c is DataGridView)
                {
                    DataGridView dgv=c as DataGridView;
                    Cursor.Current=Cursors.WaitCursor;
                    int widths=0;
                    for(int i=0;i<dgv.Columns.Count-1;i++)
                    {
                        //自动调整列宽
                        dgv.AutoResizeColumn(i,DataGridViewAutoSizeColumnMode.AllCells);
                        widths+=dgv.Columns[i].Width;
                    }
                    //如果调整列的宽度大于设定宽度
                    if(widths>ctl.Size.Width)
                    {
                                    dgv.AutoSizeColumnsMode=DataGridViewAutoSizeColumnsMode.DisplayedCells;//调整列的模式
    
                    }
                    else
                    {
                        dgv.AutoSizeColumnsMode=DataGridViewAutoSizeColumnsMode.Fill;//如果小于则填充
                       
                    }
                     Cursor.Current=Cursors.Default;
                }
            }
        }
    
    }
    

    添加一个Form1,在SizeChanged方法添加,不要在load中添加

    public partial class Form1:Form
    {
        private AutoSizeFormClass asc=new AutoSizeFormClass();
        public Form1()
        {
            InitializeComponent();
        } 
        private void Form1_SizeChanged(object sender,EventArgs e)
        {
            asc.controlAutoSize(this);
        }
    }

     

     

     

    展开全文
  • 最近在开发一个c/s软件,结果发现软件在本机和客户端上的显示大相径庭...在本机上显示佷规整,但在客户机上控件显示时都缩了一些。整个软件界面布局很不美观,原因是客户机上的分辨率要高。请问这种问题如何能解决呢?
  •  2012-11-30 曾经写过 《C# WinForm窗体及其控件自适应各种屏幕分辨率》 ,其中也讲解了控件自适应的原理。近期有网友说,装在panel里面的控件,没有效果?  这是控件嵌套的问题,加入即可实现。使用皮肤时,要注意...
  • c# winform窗口自适应各种分辨率

    千次阅读 2013-05-29 14:45:37
    近期做项目时,遇到开发的winform在自己电脑上可以正常显示,共享到其他电脑就事儿不能显示了: 1.当两个电脑分辨率相同时,无法显示完全,请检查form的autoscalemode属性是否为none,并设为none 2.分辨率不同时,...
  •  C# WinForm窗体及其控件自适应各种屏幕分辨率一。说明 我们自己编写程序的界面,会遇到各种屏幕分辨率,只有自适应才能显的美观。实际上,做到这点也很简单,就是首先记录窗体和它上面控件的初始位置和大小,当...
  • 转载于 新浪博客,链接...原文如下:改进C# WinForm窗体及其控件自适应各种屏幕分辨率一 、说明 2012-11-30 曾经写过 《C# WinForm窗体及其控件自适应各种屏幕分辨率》 ,其中也讲解了控件自适应的原理。近期有网友说,
  • winform 自适应屏幕分辨率

    千次阅读 2014-04-09 15:11:27
    比如panel不要和控件放在一层,panel与panel之间使用dock属性排好,除非特殊需求一般不要对非容器性控件直接使用dock,form界面设计不像一个函数一样是什么功能就是什么功能,没有一个可以应用于所有form 的设计...

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 176
精华内容 70
关键字:

winform控件自适应分辨率