代码之家  ›  专栏  ›  技术社区  ›  Brian Lyttle

WinForms-如何创建自定义的Windows边框和关闭/最小化按钮?

  •  5
  • Brian Lyttle  · 技术社区  · 16 年前

    我希望能够创建一个黑色自定义窗口(带边框和控件),就像作为ExpressionBlend、Twirl或Adobe Lightroom的一部分提供的那样。

    是否有创建所有者绘制的窗口的最佳实践方法?

    平台:C和WindowsForms(任何版本)

    3 回复  |  直到 12 年前
        2
  •  4
  •   Community CDub    8 年前

    如果定制的Chrome工具不能为您提供您想要的外观和感觉,那么在C中这种事情很容易做到。基本上,您创建一个无边框表单(FormBorderStyle=none),然后自己创建所有控件和边框,方法是将控件放置在需要的位置(标题栏的标签、用于关闭和最小化的命令按钮等)和/或使用图形对象直接在表单的表面上绘制。

    您还必须实现代码,以允许表单被其“假”标题栏拖动(请参见 this answer 以获取如何执行此操作的示例)。您可能还需要实现自己的调整大小机制(如果需要调整窗体的大小)。

    最后,尽管定制表单代码可能有点笨拙,但您可以在单个表单上实现它,然后让应用程序中的所有其他表单继承自该表单,这使得它成为定制整个应用程序的一种非常有用的技术。

        3
  •  3
  •   Nikita    12 年前

    我的任务是使活动窗口比其他应用程序的非活动窗口更引人注目、更明亮。应用程序有许多打开的窗口,一些模式,一些无模式-和MDI父窗口。

    您可以使用一些类似于非边界的东西——客户机区域内的框架。下面是代码段,是基类的一部分(可以直接在表单中使用):

        #region Кастомизированное поведение - рамки, активность и т.д.
        private bool isCurrentlyActive = false;
        private bool childControlsAreHandled = false;
        private Pen activeWindowFramePen, inactiveWindowFramePen;
        private Point[] framePoints;
    
        private void AddControlPaintHandler(Control ctrl)
        {
            ctrl.Paint += DrawWindowFrame;
            if (ctrl.Controls != null)
            {
                foreach (Control childControl in ctrl.Controls)
                {
                    AddControlPaintHandler(childControl);
                }
            }
        }
    
        protected override void OnActivated(EventArgs e)
        {
            base.OnActivated(e);
            if ((this.childControlsAreHandled == false)
                && (WindowFrameType != Forms.WindowFrameType.NoFrame)
                && (this.MdiParent == null))
            {
                RecalculateWindowFramePoints();
                AddControlPaintHandler(this);
                this.childControlsAreHandled = true;
            }
    
            this.isCurrentlyActive = true;
            if (InactiveWindowOpacity < 1)
            {
                base.Opacity = 1;
            }
            base.Invalidate(true);
        }
    
        protected override void OnDeactivate(EventArgs e)
        {
            base.OnDeactivate(e);
            this.isCurrentlyActive = false;
            if (InactiveWindowOpacity < 1)
            {
                base.Opacity = InactiveWindowOpacity;
            }
            base.Invalidate(true);
        }
    
        protected override void OnResizeEnd(EventArgs e)
        {
            base.OnResizeEnd(e);
            this.framePoints = null;
            RecalculateWindowFramePoints();
            this.Invalidate(true);
        }
    
        private Pen ActivePen
        {
            get
            {
                if (this.isCurrentlyActive)
                {
                    if (this.activeWindowFramePen == null)
                    {
                        this.activeWindowFramePen = new Pen(Color.FromArgb((int)(WindowFrameOpacity*255), WindowFrameActiveColor), WindowFrameSize * 2);
                    }
                    return this.activeWindowFramePen;
                }
                else
                {
                    if (this.inactiveWindowFramePen == null)
                    {
                        this.inactiveWindowFramePen = new Pen(Color.FromArgb((int)(WindowFrameOpacity*255), WindowFrameInactiveColor), WindowFrameSize * 2);
                    }
                    return this.inactiveWindowFramePen;
                }
            }
        }
    
        private Point[] RecalculateWindowFramePoints()
        {
            if ((WindowFrameType == Forms.WindowFrameType.AllSides)
                && (this.framePoints != null)
                && (this.framePoints.Length != 5))
            {
                this.framePoints = null;
            }
            if ((WindowFrameType == Forms.WindowFrameType.LeftLine)
                && (this.framePoints != null)
                && (this.framePoints.Length != 2))
            {
                this.framePoints = null;
            }
            if (this.framePoints == null)
            {
                switch (WindowFrameType)
                {
                    case Forms.WindowFrameType.AllSides:
                        this.framePoints = new Point[5]
                        {
                            new Point(this.ClientRectangle.X, this.ClientRectangle.Y),
                            new Point(this.ClientRectangle.X + this.ClientRectangle.Width, this.ClientRectangle.Y),
                            new Point(this.ClientRectangle.X + this.ClientRectangle.Width, this.ClientRectangle.Y + this.ClientRectangle.Height),
                            new Point(this.ClientRectangle.X, this.ClientRectangle.Y + this.ClientRectangle.Height),
                            new Point(this.ClientRectangle.X, this.ClientRectangle.Y)
                        };
                        break;
                    case Forms.WindowFrameType.LeftLine:
                        this.framePoints = new Point[2]
                        {
                            new Point(this.ClientRectangle.X, this.ClientRectangle.Y),
                            new Point(this.ClientRectangle.X, this.ClientRectangle.Y + this.ClientRectangle.Height)
                        };
                        break;
                }
            }
            return this.framePoints;
        }
    
        private void DrawWindowFrame(object sender, PaintEventArgs e)
        {
            if (WindowFrameType == Forms.WindowFrameType.NoFrame)
            {
                return;
            }
            if ((this.framePoints == null) || (this.framePoints.Length == 0))
            {
                return;
            }
            Control ctrl = (Control)(sender);
            // пересчитаем точки в координатах контрола.
            List<Point> pts = new List<Point>();
            foreach (var p in this.framePoints)
            {
                pts.Add(ctrl.PointToClient(this.PointToScreen(p)));
            }
            e.Graphics.DrawLines(ActivePen, pts.ToArray());
        }
    
        public static int WindowFrameSize = 2;
        public static WindowFrameType WindowFrameType = Forms.WindowFrameType.NoFrame;
        public static Color WindowFrameActiveColor = Color.YellowGreen;
        public static Color WindowFrameInactiveColor = SystemColors.ControlDark;
        public static double InactiveWindowOpacity = 1.0;
        public static double WindowFrameOpacity = 0.3;
        #endregion
    

    类的静态字段是从应用程序设置窗体(Class)初始化的,因此应用程序中的所有窗体都具有相同的行为。

    希望对某人有帮助。

    推荐文章