C#里winform最大化时,如何使里面的控件按比例变化?

_培_风_ 2016-03-18 02:44:25
用ANCHOR和DOCK我试过了 ,效果不太好,控件的大小变不了,都LEFT,TOP锚定的话,右边会空一大截很难看,上下左右的话 就重叠了
...全文
5872 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
我们拿 #13 楼贴的那个简单布局图做了例子来说明。使用 Anchor 时,设置了 ListBox 向左、向上、向右、向下对齐。而两个Button仅需要向上对齐。这样就能在窗体拉伸时比较美观,也根本不会出现你说的那种“左右空一大截”的现象。你看到空了一大截,一定是没有设置好 ListBox 向对齐。因此 Dock 和 Anchor 是最常需要用到的。 但是,我们可能希望 ListBox 的宽度不要超过窗体宽度的90%,超过了就不协调了。这就是 Anchor 做不到的了。例如我们希望窗体内部分为左右两部分、左边占80%,右边占 20%,然后按钮宽度和ListBox 分别自动地使用 Anchor 向各自的容器的对齐。 实际上在 WPF/Silverlight 中具有很智能的按比例分割屏幕的功能。Winform毕竟是20年以前就设计完成 UI 的架构(在 vb 中就有了 Anchor 等机制),而 WPF 是13年前研发的 UI 架构,自然是后者在布局上比较先进。
sp1234_maJia 2016-03-19
  • 打赏
  • 举报
回复
但是我要强调的是,通常这种东西只是对最外层布局控件进行响应式调整,绝不是对内部所有的东西都随便调整。 比如说一张图片,如果你胡乱拉伸,那么就变得很丑了。 如果是按钮,如果把高度拉高、或者宽度拉宽,那么按钮中的文字周围的空白就突然显得很不协调,一点美感都没有了。 ....... 如果一大堆控件都胡乱改变 Width、Height,其实是很垃圾的界面,一看就是程序员做的,而不是美工设计的界面。 因此这种方式其实不常使用,仅仅对窗体下面最外层的布局控件使用,这样才不至于让一堆很具体的控件变形。仅对布局控件使用百分比的定位方式,然后布局控件里边的内容还是使用 ANCHOR和DOCK。
crystal_lz 2016-03-19
  • 打赏
  • 举报
回复 11

private Size m_szInit;//初始窗体大小
private Dictionary<Control, Rectangle> m_dicSize
= new Dictionary<Control,Rectangle>();

protected override void OnLoad(EventArgs e) {
m_szInit = this.Size;//获取初始大小
this.GetInitSize(this);
base.OnLoad(e);
}

private void GetInitSize(Control ctrl) {
foreach (Control c in ctrl.Controls) {
m_dicSize.Add(c, new Rectangle(c.Location,c.Size));
this.GetInitSize(c);
}
}

protected override void OnResize(EventArgs e) {
//计算当前大小和初始大小的比例
float fx = (float)this.Width / m_szInit.Width;
float fy = (float)this.Height / m_szInit.Height;
foreach (var v in m_dicSize) {
v.Key.Left = (int)(v.Value.Left * fx);
v.Key.Top = (int)(v.Value.Top * fy);
v.Key.Width = (int)(v.Value.Width * fx);
v.Key.Height = (int)(v.Value.Height * fy);
}
base.OnResize(e);
}


完全按比例缩放
  • 打赏
  • 举报
回复
例如窗体中有一个 Button 控件,那么你可以在窗体代码中写
private void Form1_Load(object sender, EventArgs e)
{
    this.button1.GridAgent(0, 0.5F, 0, 0);
}
这样可以看到,这个button1控件的 top 总是保持为窗体的高度的一半。 我这里只是写一个例子代码,你还可以扩展 GridAgent 方法,例如告诉它“设置 top 时还应该减去 17 个像素”之类的参数。 这里说明了,用百分比来设置控件位置,而不是用像素数来设置。
  • 打赏
  • 举报
回复
引用 2 楼 spf11045 的回复:
还是会重叠啊
你需要自定义机制,让内容按照比例定位,而不是按照像素定位。 例如可以定义这样的“扩展方法”
public static void GridAgent(this Control p, float AbsLeft, float AbsTop, float AbsWidth = 0.35F, float AbsHeight = 0.1F)
{
    var form = p.FindForm();
    var proc = new Action(() =>
        {
            if (AbsLeft > 0.01)
                p.Left = (int)(form.Width * AbsLeft);
            if (AbsWidth > 0.01)
                p.Width = (int)(form.Width * AbsWidth);
            if (AbsTop > 0.01)
                p.Top = (int)(form.Height * AbsTop);
            if (AbsHeight > 0.01)
                p.Height = (int)(form.Height * AbsHeight);
        });
    proc();
    form.Resize += (s, e) => proc();        //当窗口大小改变时,重复执行
}
它能够让任意Control,在窗体修改大小时,自动按照“百分率”来调整位置。
  • 打赏
  • 举报
回复
例如,在用户控件中你可以写
private void UserControl1_Load(object sender, EventArgs e)
{
    this.GridAgent(0, 0, 0.3F, 0);  //宽度保持30%宽,左右高都不设置
}
这样就能看到此用户控件宽度总是窗口的的30%宽度。 使用ANCHOR和DOCK其实都是绝对像素定位,因此会有弊端!
d1070193993 2016-03-19
  • 打赏
  • 举报
回复
简要步骤如下: 1.创建C#窗体程序项目 2.Panel放置到窗体 3.设置dock属性为fill 4.注意MinnumSize不能设置为0,必须大于0

public partial class FrmDemo : Form  
    {  
        double dFrmWidth;  
        double dFrmHeight;  
        double dZoomHorizon;  
        double dZoomVerticality;  
        Dictionary<string, string> dicControlsAttribute = new Dictionary<string, string>();  
   
        protected void GetAllInitiateContrlInfo(Control CrlContainer)  
        {  
            if (CrlContainer.Parent == this)  
            {  
                dFrmWidth = Convert.ToDouble(CrlContainer.Width);  
                dFrmHeight = Convert.ToDouble(CrlContainer.Height);  
            }  
            foreach (Control item in CrlContainer.Controls)  
            {  
                if (item.Name.Trim() != "")  
                    dicControlsAttribute.Add(item.Name, (item.Left + item.Width / 2) + "," + (item.Top + item.Height / 2)   
                                             + "," + item.Width + "," + item.Height + "," + item.Font.Size);  
                if ((item as UserControl) == null && item.Controls.Count > 0)  
                    GetAllInitiateContrlInfo(item);  
            }  
        }  
   
        private void ChangeControlsInitiate(Control CrlContainer)  
        {  
            dZoomHorizon = (Convert.ToDouble(CrlContainer.Width) / dFrmWidth);  
            dZoomVerticality = (Convert.ToDouble(CrlContainer.Height) / dFrmHeight);
        }  
           
        private void ChangeCurrentControlAttr(Control CrlContainer)  
        {  
            double[] dPosition = new double[5];  
            foreach (Control item in CrlContainer.Controls)  
            {  
                if (item.Name.Trim() != "")  
                {  
                    if ((item as UserControl) == null && item.Controls.Count > 0)  
                        ChangeCurrentControlAttr(item);  
                    string[] strs = dicControlsAttribute[item.Name].Split(',');  
                    for (int j = 0; j < 5; j++)  
                    {  
                        dPosition[j] = Convert.ToDouble(strs[j]);  
                    }  
                    double itemWidth = dPosition[2] * dZoomHorizon;  
                    double itemHeight = dPosition[3] * dZoomVerticality;  
                    item.Left = Convert.ToInt32(dPosition[0] * dZoomHorizon - itemWidth / 2);  
                    item.Top = Convert.ToInt32(dPosition[1] * dZoomVerticality - itemHeight / 2);  
                    item.Width = Convert.ToInt32(itemWidth);  
                    item.Height = Convert.ToInt32(itemHeight);  
                    //item.Font = new Font(item.Font.Name, float.Parse  
                    //((dPosition[4] * Math.Min(dZoomHorizon, dZoomVerticality)).ToString()));  
                    //字体也可以实现同比放缩。  
                     }  
            }  
        }  
        protected override void OnSizeChanged(EventArgs e)  
        {  
            base.OnSizeChanged(e);  
            if (dicControlsAttribute.Count > 0)  
            {  
                ChangeControlsInitiate(this.Controls[0]);  
                ChangeCurrentControlAttr(this.Controls[0]);  
            }  
        }   
   
        public FrmDemo()  
        {  
            InitializeComponent();  
            GetAllInitiateContrlInfo(this.Controls[0]);//构造函数里面调用即可。  
        }  
}
waterzhz 2016-03-18
  • 打赏
  • 举报
回复
设置Anchor属性
changjiangzhibin 2016-03-18
  • 打赏
  • 举报
回复
Anchor,Dock 足矣
大鱼> 2016-03-18
  • 打赏
  • 举报
回复
设置Anchor属性就可以了
Poopaye 2016-03-18
  • 打赏
  • 举报
回复

只要设置Anchor就行了,不知道你试的什么
haoduo123456789001 2016-03-18
  • 打赏
  • 举报
回复
在resize时间里通过计算,重画所有控件的大小,确实麻烦
studyarea 2016-03-18
  • 打赏
  • 举报
回复
添加resize事件,然后自定义控件的大小
_培_风_ 2016-03-18
  • 打赏
  • 举报
回复
还是会重叠啊
qbilbo 2016-03-18
  • 打赏
  • 举报
回复
上面的上下左右, 下面的下左右。 这样下面的高度不变,上面的会占用剩余高度。你可以看一下,很多软件布局都是这样的,总一块是固定高度或固定宽度。 如果你说一定要上下等比,那你可以用:TableLayoutPanel来布局。

110,524

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧