Saltar al contenido

Interfaz Gráfico de Usuario Moderno, Multi Forms, C#, VB.Net, WinForm – (RC, Estable)

Hola, en este tutorial realizaremos un Formulario de Menú Principal Plano, Moderno y Multi Forms (Abrir Varios Formularios en un panel, tal como lo harías en un MDI Parent), con todas las funcionalidades de un formulario normal, totalmente personalizado, con Windows Form, C# o Visual Basic (VB.Net).

Bien, empecemos con el tutorial:

Paso 1: Crear Proyecto y Formulario de Menú Principal

  • Creamos un proyecto nuevo de aplicación de Windows Form en C# o Visual Vasic (VB.Net).
  • Removemos el borde del formulario: Propiedad-> FormBorderStyle=None
  • Cambiamos el tamaño al formulario: Propiedad-> Size= 1100; 600
  • Asignamos el tamaño mínimo del formulario: Propiedad-> MinimumSize= 680; 500

Paso 2: Crear Función de Redimensionar (Cambiar de Tamaño – Resize) el Formulario

Al establecer la propiedad FormBorderStyle=None del formulario, este pierde la funcionalidad de poder cambiar de tamaño, para solucionar el problema, realizamos lo siguiente.

  • Agregamos un Panel como Contenedor Principal para otros paneles y formularios.
  • Establecemos la propiedad BackColor = ActiveCaption (OPCIONAL)
  • Establecemos la propiedad Dock = Fill
  • Asignamos un nombre al panel: Name = “PanelContenedor”
  • El diseño de debió haber quedado de la siguiente manera:
  • Ahora es momento de codificar la funcionalidad de redimensionar el formulario a través de Panel Contenedor Principal.

FormMenuPrincipal.cs /.vb

//Constructor
        public FormMenuPrincipal()
        {
            InitializeComponent();
            //Estas lineas eliminan los parpadeos del formulario o controles en la interfaz grafica (Pero no en un 100%)
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.DoubleBuffered = true;
        }
//RESIZE METODO PARA REDIMENCIONAR/CAMBIAR TAMAÑO A FORMULARIO EN TIEMPO DE EJECUCION ----------------------------------------------------------
private int tolerance = 12;
private const int WM_NCHITTEST = 132;
private const int HTBOTTOMRIGHT = 17;
private Rectangle sizeGripRectangle;

protected override void WndProc(ref Message m)
{
    switch (m.Msg)
    {
        case WM_NCHITTEST:
            base.WndProc(ref m);
            var hitPoint = this.PointToClient(new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16));
            if (sizeGripRectangle.Contains(hitPoint))
                m.Result = new IntPtr(HTBOTTOMRIGHT);
            break;
        default:
            base.WndProc(ref m);
            break;
    }
}
//----------------DIBUJAR RECTANGULO / EXCLUIR ESQUINA PANEL 
protected override void OnSizeChanged(EventArgs e)
{
    base.OnSizeChanged(e);
    var region = new Region(new Rectangle(0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height));

    sizeGripRectangle = new Rectangle(this.ClientRectangle.Width - tolerance, this.ClientRectangle.Height - tolerance, tolerance, tolerance);

    region.Exclude(sizeGripRectangle);
    this.panelContenedor.Region = region;
    this.Invalidate();
}
//----------------COLOR Y GRIP DE RECTANGULO INFERIOR
protected override void OnPaint(PaintEventArgs e)
{
    SolidBrush blueBrush = new SolidBrush(Color.FromArgb(244, 244, 244));
    e.Graphics.FillRectangle(blueBrush, sizeGripRectangle);

    base.OnPaint(e);
    ControlPaint.DrawSizeGrip(e.Graphics, Color.Transparent, sizeGripRectangle);
}
'RESIZE DEL FORMULARIO- CAMBIAR TAMAÑO'
Dim cGrip As Integer = 10

Protected Overrides Sub WndProc(ByRef m As Message)
    If (m.Msg = 132) Then
        Dim pos As Point = New Point((m.LParam.ToInt32 And 65535), (m.LParam.ToInt32 + 16))
        pos = Me.PointToClient(pos)
        If ((pos.X _
                    >= (Me.ClientSize.Width - cGrip)) _
                    AndAlso (pos.Y _
                    >= (Me.ClientSize.Height - cGrip))) Then
            m.Result = CType(17, IntPtr)
            Return
        End If
    End If
    MyBase.WndProc(m)
End Sub
'----------------DIBUJAR RECTANGULO / EXCLUIR ESQUINA PANEL' 
Dim sizeGripRectangle As Rectangle
Dim tolerance As Integer = 15

Protected Overrides Sub OnSizeChanged(ByVal e As EventArgs)
    MyBase.OnSizeChanged(e)
    Dim region = New Region(New Rectangle(0, 0, Me.ClientRectangle.Width, Me.ClientRectangle.Height))
    sizeGripRectangle = New Rectangle((Me.ClientRectangle.Width - tolerance), (Me.ClientRectangle.Height - tolerance), tolerance, tolerance)
    region.Exclude(sizeGripRectangle)
    Me.PanelContenedor.Region = region
    Me.Invalidate()
End Sub

'----------------COLOR Y GRIP DE RECTANGULO INFERIOR'
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    Dim blueBrush As SolidBrush = New SolidBrush(Color.FromArgb(244, 244, 244))
    e.Graphics.FillRectangle(blueBrush, sizeGripRectangle)
    MyBase.OnPaint(e)
    ControlPaint.DrawSizeGrip(e.Graphics, Color.Transparent, sizeGripRectangle)
End Sub

 

Paso 3: Diseñar la Interfaz Gráfica de Menú Principal

  • Diseñe la interfaz gráfica de menú principal sobre el Panel Contenedor. La configuración de las propiedades se describen abajo.
  • Establezca las siguientes propiedades en los controles de usuario.

Panel Barra Titulo

BackColor = 0; 100; 182
Dock = Top
Name = «panelBarraTitulo»
Size = 1200; 40

Panel Menú

Name = «panelMenu»
Dock = Left 
Size = 240; 560
BackColor = 37; 54; 75

Panel Formularios

BackColor = Control
Dock = Fill
Name = «panelFormularios»

Picture Box Cerrar, Maximizar, Minimizar, Restaurar

Size = 16;16
Cursor = Hand
Anchor = Top | Right (Responsive)

Botones

FlatStyle = Flat
FlatAppearance.BorderSize = 0
Size = 230, 45

Paso 4: Crear Función de Cerrar, Maximizar/Restaurar y Minimizar el formulario

  • Creamos los eventos Clic de cada botón, y codificamos de la siguiente manera:
private void btnCerrar_Click(object sender, EventArgs e)
{
    Application.Exit();
}
//Capturar posicion y tamaño antes de maximizar para restaurar
int lx, ly;
int sw, sh;
private void btnMaximizar_Click(object sender, EventArgs e)
{
    lx = this.Location.X;
    ly = this.Location.Y;
    sw = this.Size.Width;
    sh = this.Size.Height;
    btnMaximizar.Visible = false;
    btnRestaurar. Visible = true;
    this.Size = Screen.PrimaryScreen.WorkingArea.Size;
    this.Location = Screen.PrimaryScreen.WorkingArea.Location;
}

private void btnRestaurar_Click(object sender, EventArgs e)
{
    btnMaximizar.Visible = true ;
    btnRestaurar.Visible = false;
    this.Size = new Size(sw,sh);
    this.Location = new Point(lx,ly);
}

private void btnMinimizar_Click(object sender, EventArgs e)
{
    this.WindowState = FormWindowState.Minimized;
}
Private Sub btnCerrar_Click(sender As Object, e As EventArgs) Handles btnCerrar.Click
    Application.Exit()
End Sub

Dim lx, ly As Integer
Dim sw, sh As Integer

Private Sub btnMaximizar_Click(sender As Object, e As EventArgs) Handles btnMaximizar.Click

    lx = Me.Location.X
    ly = Me.Location.Y
    sw = Me.Size.Width
    sh = Me.Size.Height

    btnMaximizar.Visible = False
    btnRestaurar.Visible = True

    Me.Size = Screen.PrimaryScreen.WorkingArea.Size
    Me.Location = Screen.PrimaryScreen.WorkingArea.Location

End Sub

Private Sub btnRestaurar_Click(sender As Object, e As EventArgs) Handles btnRestaurar.Click
    Me.Size = New Size(sw, sh)
    Me.Location = New Point(lx, ly)

    btnMaximizar.Visible = True
    btnRestaurar.Visible = False
End Sub

Private Sub btnMinimizar_Click(sender As Object, e As EventArgs) Handles btnMinimizar.Click
    Me.WindowState = FormWindowState.Minimized
End Sub

 

Paso 5: Crear Función de Arrastrar el formulario (Drag Form)

  • Importamos la librería  System.Runtime.InteropServices, y agregamos los siguientes fragmentos de código.
[DllImport("user32.DLL", EntryPoint = "ReleaseCapture")]
private extern static void ReleaseCapture();

[DllImport("user32.DLL", EntryPoint = "SendMessage")]
private extern static void SendMessage(System.IntPtr hWnd, int wMsg, int wParam, int lParam);
<DllImport("user32.DLL", EntryPoint:="ReleaseCapture")>
Private Shared Sub ReleaseCapture()
End Sub

<DllImport("user32.DLL", EntryPoint:="SendMessage")>
Private Shared Sub SendMessage(ByVal hWnd As System.IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer)
End Sub

 

  • Creamos el evento MouseDown del Panel Barra de Titulo, e invocamos los métodos anteriores creados.
private void panelBarraTitulo_MouseMove(object sender, MouseEventArgs e)
{
    ReleaseCapture();
    SendMessage(this.Handle, 0x112, 0xf012, 0);
}
Private Sub PanelBarraTitulo_MouseMove(sender As Object, e As MouseEventArgs) Handles PanelBarraTitulo.MouseMove

    ReleaseCapture()
    SendMessage(Me.Handle, &H112&, &HF012&, 0)

End Sub

Paso 6: Crear Método para Abrir formularios en el panel Contenedor.

  • Creamos el siguiente método que nos permitirá abrir varios formularios dentro del panel contenedor de formularios.
private void AbrirFormulario<MiForm>() where MiForm : Form, new() {
    Form formulario;
    formulario = panelformularios.Controls.OfType<MiForm>().FirstOrDefault();//Busca en la colecion el formulario
    //si el formulario/instancia no existe
    if (formulario == null)
    {
        formulario = new MiForm();
        formulario.TopLevel = false;
        formulario.FormBorderStyle = FormBorderStyle.None;
        formulario.Dock = DockStyle.Fill;
        panelformularios.Controls.Add(formulario);
        panelformularios.Tag = formulario;
        formulario.Show();
        formulario.BringToFront();
    }
    //si el formulario/instancia existe
    else {
        formulario.BringToFront();
    }
}
Private Sub AbrirFormEnPanel(Of Miform As {Form, New})()

    Dim Formulario As Form
    Formulario = PanelFormularios.Controls.OfType(Of Miform)().FirstOrDefault() 'Busca el formulario en la coleccion'

    'Si form no fue econtrado/ no existe'
    If Formulario Is Nothing Then
        Formulario = New Miform()
        Formulario.TopLevel = False

        Formulario.FormBorderStyle = FormBorderStyle.None
        Formulario.Dock = DockStyle.Fill

        PanelFormularios.Controls.Add(Formulario)
        PanelFormularios.Tag = Formulario
        Formulario.Show()
        Formulario.BringToFront()
    Else
        Formulario.BringToFront()
    End If

End Sub

 

  • Invocamos el método anterior de la siguiente manera:
private void button1_Click(object sender, EventArgs e)
{
    AbrirFormulario<Form1>();
}

private void button2_Click(object sender, EventArgs e)
{
    AbrirFormulario<Form2>();
}
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    AbrirFormEnPanel(Of Form1)()

End Sub

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click

    AbrirFormEnPanel(Of Form2)()

End Sub

 

Recomendaciones Finales

Crea los formularios hijos que se abrirán en el panel contenedor de Formulario al mismo tamaño de este, adicionando las dimensiones del borde. para este ejemplo, el tamaño ideal es: 886 de ancho; 496 de alto (El tamaño del panel contenedor de Formulario es 870; 457, a este le sumamos el tamaño de los bordes del form: 16 de ancho, 39 de alto ), de esa manera evitamos que le formulario parpadee al abrir formularios o redimensionar en tiempo de ejecución.

Eso es todo 🙂

Ver Video Tutorial

C#

Visual Basic (VB .Net)

Descargas

Ver Tutorial Dashboard/ Gráficos estadísticos