WinForms - Como faço para criar uma borda personalizada do Windows e fechar/minimizar os botões?

StackOverflow https://stackoverflow.com/questions/305937

Pergunta

Gostaria de poder criar uma janela preta personalizada (com borda e controles) como o enviado como parte da mistura de expressão, Twirl ou Adobe Lightroom.

Existe uma maneira das práticas recomendadas de criar uma janela desenhada do proprietário?

Plataforma: C# e WindowsForms (qualquer versão)

Outras dicas

Se as ferramentas personalizadas não fornecerem a aparência que você deseja, esse tipo de coisa é fácil de fazer em C#. Basicamente, você cria uma forma sem fronteiras (formbordersTyle = Nenhum) e, em seguida, cria todos os controles e faz fronteira, colocando controles onde você precisa deles (um rótulo para a barra de título, botões de comando para fechar e minimizar etc.) e/ou desenho diretamente na superfície do formulário usando o objeto gráfico.

Você também precisa implementar o código para permitir que o formulário seja arrastado por sua barra de título "Fake" (veja esta resposta para uma amostra de como fazer isso). Você também pode ter que implementar seu próprio mecanismo de redimensionamento (se você precisar que os formulários sejam redimensionáveis).

Por fim, embora o código de formato personalizado possa ser um pouco desajeitado, você pode implementá-lo em um único formulário e depois ter todos os outros formulários em seu aplicativo herdado a partir deste formulário, o que o torna uma técnica muito útil para a pele personalizada de um inteiro inscrição.

Minha tarefa era tornar as janelas ativas mais visíveis, brilhantes - do que outras, janelas inativas do aplicativo. O aplicativo tem muitas janelas abertas, alguns modais, alguns modal - e o pai MDI.

Você pode usar algo como não-border-um quadro dentro da área do cliente. Aqui está o snippet de código, uma parte de uma classe base (pode ser usada diretamente em um formulário):

    #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

Os campos estáticos da classe são inicializados no formulário de configurações de aplicativos (classe) - portanto, todos os formulários no aplicativo têm o mesmo comportamento.

Espero que ajude a alguém.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top