Winforms - Как создать настраиваемую границу окна и кнопки закрытия / сворачивания?

Я хотел бы иметь возможность создать черное настраиваемое окно (с рамкой и элементами управления), подобное тому, которое поставляется как часть наложения выражений, Twirl или Adobe Lightroom.

Как создать окно, нарисованное владельцем?


person Brian Lyttle    schedule 20.11.2008    source источник
comment
Вот статья о создании пользовательских форм окон с использованием только панелей - Создание пользовательских форм Windows Forms на C # с помощью панелей   -  person Pritam Zope    schedule 01.02.2016
comment
Возможный дубликат настраиваемых заголовков / хрома в приложении WinForms   -  person Cole Johnson    schedule 21.05.2016


Ответы (3)


Пользовательские заголовки / хром в приложении WinForms

person Community    schedule 20.11.2008

Если инструменты с настраиваемым хромированием не обеспечивают желаемого внешнего вида, такие вещи легко сделать самостоятельно на C #. По сути, вы создаете форму без полей (FormBorderStyle = None), а затем сами создаете все элементы управления и границы, размещая элементы управления там, где они вам нужны (метка для строки заголовка, командные кнопки для закрытия и минимизации и т. Д.) И / или рисования непосредственно на поверхности формы с помощью объекта Graphics.

Вам также необходимо реализовать код, позволяющий перетаскивать форму за ее «фальшивую» строку заголовка (см. этот ответ, чтобы узнать, как это сделать). Возможно, вам также придется реализовать свой собственный механизм изменения размера (если вам нужно, чтобы формы можно было изменять).

Наконец, хотя код настраиваемой формы может быть немного неуклюжим, вы можете реализовать его в одной форме, а затем сделать так, чтобы все другие формы в вашем приложении унаследовали от этой формы, что делает его очень полезным методом для настраиваемого оформления всего применение.

person MusiGenesis    schedule 20.11.2008
comment
Честно очень честный подход - person Hesein Burg; 28.03.2017

Моей задачей было сделать активное окно более заметным, ярким, чем другие, неактивные окна приложения. В приложении много открытых окон, некоторые модальные, некоторые немодальные, а также родительское окно MDI.

Вы можете использовать что-то вроде not-a-border - рамку внутри клиентской области. Вот фрагмент кода, часть базового класса (может использоваться непосредственно в форме):

    #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

Статические поля класса инициализируются из формы (класса) настроек приложения, поэтому все формы в приложении ведут себя одинаково.

Надеюсь, что это кому-то поможет.

person Nikita    schedule 20.09.2012
comment
где я могу найти этот тип WindowFrameType ?? - person user1912383; 15.09.2015