Loading,你用IE,难怪你打不开

WinForm 简单实现仿WPF的WrapPanel和StackPanel


    public interface IDesiredPanel
    {
        Size GetDesiredSize(int availableWidth, int avaiableHeight);
    }

    public class StackPanel : Panel, IDesiredPanel
    {
        protected override void OnLayout(LayoutEventArgs levent)
        {
            base.OnLayout(levent);
            List<Control> visibleCtrls = this.GetVisiableControls();
            int renderHeight = 0;
            for (int i = 0; i < visibleCtrls.Count; i++)
            {
                Control childCtrl = visibleCtrls[i];
                IDesiredPanel idesiredPnl = childCtrl as IDesiredPanel;
                Size childDesignSize = (idesiredPnl == null) 
                    ? new Size(childCtrl.Width, childCtrl.Height)
                    : idesiredPnl.GetDesiredSize(this.Width, this.Height);
                childCtrl.Location = new Point(0, renderHeight);
                childCtrl.Width = base.Width;
                renderHeight += childDesignSize.Height;
            }
            if (base.Parent is IDesiredPanel)
            {
                if (visibleCtrls.Count > 0)
                {
                    base.Height = renderHeight;
                }
                else
                {
                    base.Height = 3;
                }
            }
            else
            {
               // base.Height = renderHeight;
                //this.Invalidate();
                //this.PerformLayout();
            }
        }

        // Token: 0x06000086 RID: 134 RVA: 0x0000FA04 File Offset: 0x0000DC04
        private List<Control> GetVisiableControls()
        {
            List<Control> controls = new List<Control>();
            foreach (object obj in base.Controls)
            {
                Control c = (Control)obj;
                if (c.Visible)
                {
                    controls.Add(c);
                }
            }
            //controls.Reverse();
            return controls;
        }

        // Token: 0x06000087 RID: 135 RVA: 0x0000FA98 File Offset: 0x0000DC98
        public Size GetDesiredSize(int availableWidth, int avaiableHeight)
        {
            List<Control> visibleCtrls = this.GetVisiableControls();
            int desiredHeight = 0;
            for (int i = 0; i < visibleCtrls.Count; i++)
            {
                Control childCtrl = visibleCtrls[i];
                IDesiredPanel idesiredPnl = childCtrl as IDesiredPanel;
                Size childDesignSize = idesiredPnl == null
                      ? new Size(childCtrl.Width, childCtrl.Height)
                      :  idesiredPnl.GetDesiredSize(availableWidth, avaiableHeight);
                desiredHeight += childDesignSize.Height;
            }
            return new Size(availableWidth, desiredHeight);
        }

    }

    public class WrapPanel : Panel, IDesiredPanel
    {
        protected override void OnLayout(LayoutEventArgs levent)
        {
            base.OnLayout(levent);

            List<Control> visibleCtrls = GetVisiableControls();


            int renderHeight = 0;
            int curLineWidth = 0, curLineMaxHeight = 0;
            for (int i = 0; i < visibleCtrls.Count; i++)
            {
                Control childCtrl = visibleCtrls[i];
                IDesiredPanel idesiredPnl = childCtrl as IDesiredPanel;
                Size childDesiredSize = idesiredPnl == null
                       ? new Size(childCtrl.Width, childCtrl.Height)
                       : idesiredPnl.GetDesiredSize(this.Width, this.Height);
                if (idesiredPnl != null)
                {
                    childCtrl.Width = childDesiredSize.Width;
                    childCtrl.Height = childDesiredSize.Height;
                }
                if (curLineWidth == 0)
                {   //第一个元素
                    childCtrl.Location = new Point(0, renderHeight);
                    curLineWidth += childDesiredSize.Width;
                    curLineMaxHeight = Math.Max(curLineMaxHeight, childDesiredSize.Height);                  
                }
                else if (curLineWidth + childDesiredSize.Width < this.Width)
                {   //非第一个元素,再次元素则宽度累加 不会超出
                    childCtrl.Location = new Point(curLineWidth, renderHeight);
                    curLineWidth += childDesiredSize.Width;
                    curLineMaxHeight = Math.Max(curLineMaxHeight, childDesiredSize.Height);
                }
                else
                {   //非第一个元素,再次元素则宽度累加 会超出,采用换行
                    renderHeight += curLineMaxHeight;

                    //换行了
                    childCtrl.Location = new Point(0, renderHeight);
                    curLineWidth = childCtrl.Width;
                    curLineMaxHeight = childCtrl.Height;
                }


                if (curLineWidth > this.Width)
                {   //这个元素溢出了
                    renderHeight += curLineMaxHeight;       //累加上
                    curLineWidth = 0;       //重置为0
                    curLineMaxHeight = 0;   //需要换到下一行
                }
            }
            if (curLineWidth > 0)
            {
                renderHeight += curLineMaxHeight;
            }

            if(this.Parent is IDesiredPanel)
            {
                if(visibleCtrls.Count>0)
                {
                    this.Height =  renderHeight;
                }
                else
                {
                    this.Height = 3;
                }
            }
            else
            {
                this.Height = Math.Max(3, renderHeight);
            }
        }
        private List<Control> GetVisiableControls()
        {
            List<Control> controls = new List<Control>();
            foreach (Control c in this.Controls)
            {
                if (c.Visible)
                {
                    controls.Add(c);
                }
            }
            //controls.Reverse();
            return controls;
        }

        public Size GetDesiredSize(int availableWidth,int avaiableHeight)
        {
            List<Control> visibleCtrls = GetVisiableControls();
            int desiredHeight = 0;
            int curLineWidth = 0,curLineMaxHeight = 0;
            for (int i = 0; i < visibleCtrls.Count; i++)
            {
                Control childCtrl = visibleCtrls[i];
                IDesiredPanel idesiredPnl = childCtrl as IDesiredPanel;
                Size childDesiredSize = idesiredPnl == null
                       ? new Size(childCtrl.Width, childCtrl.Height)
                       : idesiredPnl.GetDesiredSize(availableWidth,avaiableHeight);

                if (curLineWidth == 0)
                {
                    curLineWidth += childDesiredSize.Width;
                    curLineMaxHeight = Math.Max(curLineMaxHeight, childDesiredSize.Height);
                }
                else if (curLineWidth + childDesiredSize.Width < availableWidth)
                {
                    curLineWidth += childDesiredSize.Width; 
                    curLineMaxHeight = Math.Max(curLineMaxHeight, childDesiredSize.Height);
                }
                else
                {
                    desiredHeight += curLineMaxHeight;

                    curLineWidth = childCtrl.Width;
                    curLineMaxHeight = childCtrl.Height;
                }
                if (curLineWidth > availableWidth)
                {
                    desiredHeight += curLineMaxHeight;
                    curLineWidth = 0;
                    curLineMaxHeight = 0;
                }
            }
            if (curLineWidth > 0)
            {
                desiredHeight += curLineMaxHeight;
            }
            return new Size(availableWidth, desiredHeight);
        }
    }

  public class FillLastLinePanel : Panel, IDesiredPanel
    {
    
        protected override void OnLayout(LayoutEventArgs levent)
        {
            base.OnLayout(levent);

            List<Control> visibleCtrls = GetVisiableControls();

            Size desiredSize = GetDesiredSize(this.Width, this.Height);

            int xOffset = 0;
            int maxHeight = 0;
            for (int i = 0; i < visibleCtrls.Count; i++)
            {
                Control childCtrl = visibleCtrls[i];
                IDesiredPanel idesiredPnl = childCtrl as IDesiredPanel;
                Size childDesignSize = idesiredPnl == null
                       ? new Size(childCtrl.Width, childCtrl.Height)
                       : idesiredPnl.GetDesiredSize(Math.Max(0, this.Width - xOffset), this.Height);

                //childCtrl.Height = desiredSize.Height;
                childCtrl.Location = new Point(xOffset, 0);
                if (i == visibleCtrls.Count - 1)
                {
                    childCtrl.Width = this.Width - xOffset;
                    if (idesiredPnl != null)
                    {
                        childCtrl.Height = this.Height;
                    }
                }
                else if (idesiredPnl != null)
                {
                    childCtrl.Width = childDesignSize.Width;
                }
                xOffset += childCtrl.Width;
                maxHeight = Math.Max(maxHeight, childDesignSize.Height);
            }

            if(this.Parent is IDesiredPanel)
            {
                if (visibleCtrls.Count > 0)
                {
                    this.Width = xOffset;
                    this.Height = maxHeight;
                }
                else
                {
                    this.Height = 3;
                    this.Width = 3;
                }
            }
            else if (this.DesignMode == false)
            {
                this.Width = xOffset;
                this.Height = maxHeight;
            }
        }
        private List<Control> GetVisiableControls()
        {
            List<Control> controls = new List<Control>();
            foreach (Control c in this.Controls)
            {
                if (c.Visible)
                {
                    controls.Add(c);
                }
            }
            //controls.Reverse();
            return controls;
        }

        public Size GetDesiredSize(int availableWidth,int avaiableHeight)
        {
            List<Control> visibleCtrls = GetVisiableControls();
            int maxDesiredHeight = 0;
            int totalDesiredWidth = 0;
            for (int i = 0; i < visibleCtrls.Count; i++)
            {
                Control childCtrl = visibleCtrls[i];
                IDesiredPanel idesiredPnl = childCtrl as IDesiredPanel;
                Size childDesiredSize = idesiredPnl == null
                       ? new Size(childCtrl.Width, childCtrl.Height)
                       : idesiredPnl.GetDesiredSize(Math.Max(0, availableWidth - totalDesiredWidth), avaiableHeight);

                maxDesiredHeight = Math.Max(maxDesiredHeight, childDesiredSize.Height);
                totalDesiredWidth += childDesiredSize.Width;
            }
            return new Size(totalDesiredWidth, maxDesiredHeight);
        }
    }

以上代码在AutoScroll=true会出现bug

posted @ 2024-10-24 15:32  老板娘的神秘商店  阅读(14)  评论(0编辑  收藏  举报