Winforms - Как создать пользовательскую границу окна и кнопки закрытия / сворачивания? - PullRequest
5 голосов
/ 20 ноября 2008

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

Есть ли лучший способ создания окна, нарисованного владельцем?

Платформа: C # и WindowsForms (любая версия)

Ответы [ 3 ]

5 голосов
/ 20 ноября 2008

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

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

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

3 голосов
/ 20 сентября 2012

Моей задачей было сделать активное окно более заметным, ярким, чем другие, неактивными окнами приложения. В приложении много открытых окон, некоторые модальные, некоторые немодальные - и родительское 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

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

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

1 голос
/ 20 ноября 2008
...