Hola, aquí os traigo un nuevo tutorial de diseño de interfaces moderno, plano y multicolor aleatorio, con la opción de abrir un único formulario secundario en un panel, el botón se resalta al abrir un formulario y este se mantiene activo hasta cerrar el formulario. Ademas mostraremos el titulo de formulario, aplicar el color actual al formulario secundario y agregar un único botón para cerrar cualquier formulario hijo.
Adicionalmente, crearemos la función de arrastrar el formulario, cerrar, minimizar, maximizar (Sin tapar la barra de tareas) y restaurar el formulario.
Bien, empecemos con el tutorial.
Clase ThemeColor
- Primeramente creamos una clase estática de nombre ThemeColor.
- Declaramos propiedades para el color primario y secundario.
- Creamos una lista de cadenas (List<string>) para almacenar la lista de colores que deseamos usar, en formato html.
- Finalmente creamos un método para cambiar el brillo del color, este método es muy útil si queremos oscurecer o aclarar un color, prácticamente cambiar la tonalidad de un color determinado.
public static class ThemeColor { public static Color PrimaryColor { get; set; } public static Color SecondaryColor { get; set; } public static List<string> ColorList = new List<string>() { "#3F51B5", "#009688", "#FF5722", "#607D8B", "#FF9800", "#9C27B0", "#2196F3", "#EA676C", "#E41A4A", "#5978BB", "#018790", "#0E3441", "#00B0AD", "#721D47", "#EA4833", "#EF937E", "#F37521", "#A12059", "#126881", "#8BC240", "#364D5B", "#C7DC5B", "#0094BC", "#E4126B", "#43B76E", "#7BCFE9", "#B71C46"}; public static Color ChangeColorBrightness(Color color, double correctionFactor) { double red = color.R; double green = color.G; double blue = color.B; //If correction factor is less than 0, darken color. if (correctionFactor < 0) { correctionFactor = 1 + correctionFactor; red *= correctionFactor; green *= correctionFactor; blue *= correctionFactor; } //If correction factor is greater than zero, lighten color. else { red = (255 - red) * correctionFactor + red; green = (255 - green) * correctionFactor + green; blue = (255 - blue) * correctionFactor + blue; } return Color.FromArgb(color.A, (byte)red, (byte)green, (byte)blue); } }
Module ThemeColor Public Property PrimaryColor As Color Public Property SecondaryColor As Color Public ColorList As List(Of String) = New List(Of String)() From { "#3F51B5", "#009688", "#FF5722", "#607D8B", "#FF9800", "#9C27B0", "#2196F3", "#EA676C", "#E41A4A", "#5978BB", "#018790", "#0E3441", "#00B0AD", "#721D47", "#EA4833", "#EF937E", "#F37521", "#A12059", "#126881", "#8BC240", "#364D5B", "#C7DC5B", "#0094BC", "#E4126B", "#43B76E", "#7BCFE9", "#B71C46" } Function ChangeColorBrightness(color As Color, correctionFactor As Double) As Color Dim red As Double = color.R Dim green As Double = color.G Dim blue As Double = color.B 'If correction factor is less than 0, darken color.' If correctionFactor < 0 Then correctionFactor = 1 + correctionFactor red *= correctionFactor green *= correctionFactor blue *= correctionFactor 'If correction factor is greater than zero, lighten color.' Else red = (255 - red) * correctionFactor + red green = (255 - green) * correctionFactor + green blue = (255 - blue) * correctionFactor + blue End If Return Color.FromArgb(color.A, CByte(red), CByte(green), CByte(blue)) End Function End Module
Diseño Formulario de Menú Principal
- Diseñamos el formulario de menú principal, puedes hacerlo a tu manera o de la siguiente manera:
- Agregamos un panel para el menú, elegimos un color (RGB=51, 51, 76), y los acoplamos al lado izquierdo (Dock=Left).
- En el panel menú, agregamos los botones necesarios, y le damos el estilo que queramos. Opcionalmente agregamos un panel en la parte superior para el logo
- Agregamos un panel para la barra de titulo, en ella, agregamos un label para el titulo, un botón hacia el lado izquierdo(Dock=Left) para cerrar el formulario hijo activo(abierto). También agregamos botones para minimizar, maximizar y cerrar el formulario principal.
- Finalmente agregamos un panel para contener/alojar los formularios secundarios (Hijos), opcionalemente en ella, agregamos un logo(picturebox).
Código Formulario de Menú Principal
- Una vez diseñado el formulario, pasemos a codificar, clic derecho -> ver código.
- Declaramos campos de forma privada para el boton actual, un generador de números aleatorios, un indice temporal y un formulario activo.
- Inicializamos el campo random y algunos elementos de diseño en el constructor (FormMainMenu()).
- Importamos la librería nativa user32.dll para arrastrar el formulario (ReleaseCapture() / SendMessage(System.IntPtr hWnd, int wMsg, int wParam, int lParam)).
- Creamos un método para seleccionar el color de tema (SelectThemeColor()).
- Creamos un método para activar/resaltar el botón y tema (ActivateButton(object btnSender)).
- Creamos un método para desactivar el botón (DisableButton()).
- Creamos un método para abrir formularios secundarios en el panel contenedor (OpenChildForm(Form childForm, object btnSender)).
- Creamos un metodo para reiniciar los valores por defecto del formulario (Reset()).
- Creamos los eventos click de los botones, en ello, invocamos el método abrir formulario hijo (btnProducts_Click…..).
- Creamos el evento MouseDown del panel barra de titulo para arrastrar el formulario, en ella invocamos los metodos de la librería nativa user32.dll (panelTitleBar_MouseDown(object sender, MouseEventArgs e))
- Finalmente creamos las funciones de cerrar, minimizar y maximizar/restaurar (btnClose_Click….).
public partial class FormMainMenu : Form { //Fields private Button currentButton; private Random random; private int tempIndex; private Form activeForm; //Constructor public FormMainMenu() { InitializeComponent(); random = new Random(); btnCloseChildForm.Visible = false; this.Text = string.Empty; this.ControlBox = false; this.MaximizedBounds = Screen.FromHandle(this.Handle).WorkingArea; } [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); //Methods private Color SelectThemeColor() { int index = random.Next(ThemeColor.ColorList.Count); while (tempIndex == index) { index = random.Next(ThemeColor.ColorList.Count); } tempIndex = index; string color = ThemeColor.ColorList[index]; return ColorTranslator.FromHtml(color); } private void ActivateButton(object btnSender) { if (btnSender != null) { if (currentButton != (Button)btnSender) { DisableButton(); Color color = SelectThemeColor(); currentButton = (Button)btnSender; currentButton.BackColor = color; currentButton.ForeColor = Color.White; currentButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 12.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); panelTitleBar.BackColor = color; panelLogo.BackColor = ThemeColor.ChangeColorBrightness(color, -0.3); ThemeColor.PrimaryColor = color; ThemeColor.SecondaryColor= ThemeColor.ChangeColorBrightness(color, -0.3); btnCloseChildForm.Visible = true; } } } private void DisableButton() { foreach (Control previousBtn in panelMenu.Controls) { if (previousBtn.GetType() == typeof(Button)) { previousBtn.BackColor = Color.FromArgb(51, 51, 76); previousBtn.ForeColor = Color.Gainsboro; previousBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); } } } private void OpenChildForm(Form childForm, object btnSender) { if (activeForm != null) activeForm.Close(); ActivateButton(btnSender); activeForm = childForm; childForm.TopLevel = false; childForm.FormBorderStyle = FormBorderStyle.None; childForm.Dock = DockStyle.Fill; this.panelDesktopPane.Controls.Add(childForm); this.panelDesktopPane.Tag = childForm; childForm.BringToFront(); childForm.Show(); lblTitle.Text = childForm.Text; } private void btnProducts_Click(object sender, EventArgs e) { OpenChildForm(new Forms.FormProduct(), sender); } private void btnOrders_Click(object sender, EventArgs e) { OpenChildForm(new Forms.FormOrders(), sender); } private void btnCustomers_Click(object sender, EventArgs e) { OpenChildForm(new Forms.FormCustomers(), sender); } private void btnReport_Click(object sender, EventArgs e) { OpenChildForm(new Forms.FormReporting(), sender); } private void btnNotifications_Click(object sender, EventArgs e) { OpenChildForm(new Forms.FormNotifications(), sender); } private void btnSetting_Click(object sender, EventArgs e) { OpenChildForm(new Forms.FormSetting(), sender); } private void btnCloseChildForm_Click(object sender, EventArgs e) { if (activeForm != null) activeForm.Close(); Reset(); } private void Reset() { DisableButton(); lblTitle.Text = "HOME"; panelTitleBar.BackColor = Color.FromArgb(0, 150, 136); panelLogo.BackColor = Color.FromArgb(39, 39, 58); currentButton = null; btnCloseChildForm.Visible = false; } private void panelTitleBar_MouseDown(object sender, MouseEventArgs e) { ReleaseCapture(); SendMessage(this.Handle, 0x112, 0xf012, 0); } private void btnClose_Click(object sender, EventArgs e) { Application.Exit(); } private void btnMaximize_Click(object sender, EventArgs e) { if (WindowState == FormWindowState.Normal) this.WindowState = FormWindowState.Maximized; else this.WindowState = FormWindowState.Normal; } private void bntMinimize_Click(object sender, EventArgs e) { this.WindowState = FormWindowState.Minimized; } }
Imports System.Runtime.InteropServices Public Class Form1 'FIELDS' Private currentButton As Button Private random As Random Private tempIndex As Integer Private activeForm As Form 'CONSTRUCTOR' Public Sub New() InitializeComponent() random = New Random() currentButton = New Button() Me.btnCloseChildForm.Visible = False Me.Text = String.Empty Me.ControlBox = False Me.MaximizedBounds = Screen.FromHandle(Me.Handle).WorkingArea End Sub 'METHODS' Private Function SelectThemeColor() As Color Dim index As Integer = random.[Next](ThemeColor.ColorList.Count) While tempIndex = index index = random.[Next](ThemeColor.ColorList.Count) End While tempIndex = index Dim color As String = ThemeColor.ColorList(index) Return ColorTranslator.FromHtml(color) End Function Private Sub ActivateButton(btnSender As Object) If btnSender IsNot Nothing Then If currentButton.Name <> CType(btnSender, Button).Name Then DisableButton() Dim color As Color = SelectThemeColor() currentButton = CType(btnSender, Button) currentButton.BackColor = color currentButton.ForeColor = Color.White currentButton.Font = New System.Drawing.Font("Microsoft Sans Serif", 12.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, (CByte((0)))) panelTitleBar.BackColor = color panelLogo.BackColor = ThemeColor.ChangeColorBrightness(color, -0.3) ThemeColor.PrimaryColor = color ThemeColor.SecondaryColor = ThemeColor.ChangeColorBrightness(color, -0.3) btnCloseChildForm.Visible = True End If End If End Sub Private Sub DisableButton() For Each previousBtn As Control In panelMenu.Controls If previousBtn.[GetType]() = GetType(Button) Then previousBtn.BackColor = Color.FromArgb(51, 51, 76) previousBtn.ForeColor = Color.Gainsboro previousBtn.Font = New System.Drawing.Font("Microsoft Sans Serif", 10.0F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, (CByte((0)))) End If Next End Sub Private Sub OpenChildForm(childForm As Form, btnSender As Object) If activeForm IsNot Nothing Then activeForm.Close() ActivateButton(btnSender) activeForm = childForm childForm.TopLevel = False childForm.FormBorderStyle = FormBorderStyle.None childForm.Dock = DockStyle.Fill Me.panelDesktopPane.Controls.Add(childForm) Me.panelDesktopPane.Tag = childForm childForm.BringToFront() childForm.Show() lblTitle.Text = childForm.Text End Sub Private Sub btnCloseChildForm_Click(sender As Object, e As EventArgs) Handles btnCloseChildForm.Click If (Not (activeForm) Is Nothing) Then activeForm.Close() End If Reset() End Sub Private Sub Reset() DisableButton() lblTitle.Text = "HOME" panelTitleBar.BackColor = Color.FromArgb(0, 150, 136) panelLogo.BackColor = Color.FromArgb(39, 39, 58) currentButton = New Button() btnCloseChildForm.Visible = False End Sub 'DRAG FORM' <DllImport("user32.DLL", EntryPoint:="ReleaseCapture")> Private Shared Sub ReleaseCapture() End Sub <DllImport("user32.DLL", EntryPoint:="SendMessage")> Private Shared Sub SendMessage(hWnd As IntPtr, wMsg As Integer, wParam As Integer, lParam As Integer) End Sub Private Sub panelTitleBar_MouseDown(sender As Object, e As MouseEventArgs) Handles panelTitleBar.MouseDown ReleaseCapture() SendMessage(Me.Handle, &H112&, &HF012&, 0) End Sub 'EVENTS Private Sub btnProducts_Click(sender As Object, e As EventArgs) Handles btnProducts.Click OpenChildForm(New FormProducts(), sender) End Sub Private Sub btnOrders_Click(sender As Object, e As EventArgs) Handles btnOrders.Click OpenChildForm(New FormOrders(), sender) End Sub Private Sub btnCustomers_Click(sender As Object, e As EventArgs) Handles btnCustomers.Click OpenChildForm(New FormCustomers(), sender) End Sub Private Sub btnReport_Click(sender As Object, e As EventArgs) Handles btnReport.Click OpenChildForm(New FormReports(), sender) End Sub Private Sub btnNotifications_Click(sender As Object, e As EventArgs) Handles btnNotifications.Click OpenChildForm(New FormNotifications(), sender) End Sub Private Sub btnSetting_Click(sender As Object, e As EventArgs) Handles btnSetting.Click OpenChildForm(New FormSetting(), sender) End Sub 'CLOSE, MAXIMIZE, MINIMIZE FORM MAIN' Private Sub bntMinimize_Click(sender As Object, e As EventArgs) Handles bntMinimize.Click Me.WindowState = FormWindowState.Minimized End Sub Private Sub btnMaximize_Click(sender As Object, e As EventArgs) Handles btnMaximize.Click If (WindowState = FormWindowState.Normal) Then Me.WindowState = FormWindowState.Maximized Else Me.WindowState = FormWindowState.Normal End If End Sub Private Sub btnClose_Click(sender As Object, e As EventArgs) Handles btnClose.Click Application.Exit() End Sub End Class
Diseño Formularios Secundarios (Hijo)
- Agregamos y diseñamos formularios secundarios.
Código Formularios Secundarios (Hijo)
- Creamos un método para cargar el color actual (tema) y aplicar al formulario secundario (LoadTheme()).
- Invocamos el método anterior en el evento load o constructor.
private void FormOrders_Load(object sender, EventArgs e) { LoadTheme(); } private void LoadTheme() { foreach (Control btns in this.Controls) { if (btns.GetType() == typeof(Button)) { Button btn = (Button)btns; btn.BackColor = ThemeColor.PrimaryColor; btn.ForeColor = Color.White; btn.FlatAppearance.BorderColor = ThemeColor.SecondaryColor; } } label4.ForeColor = ThemeColor.SecondaryColor; label5.ForeColor = ThemeColor.PrimaryColor; }
Public Class FormProducts Private Sub FormProducts_Load(sender As Object, e As EventArgs) Handles MyBase.Load LoadTheme() End Sub Private Sub LoadTheme() For Each btns As Control In Me.Controls If btns.[GetType]() = GetType(Button) Then Dim btn As Button = CType(btns, Button) btn.BackColor = ThemeColor.PrimaryColor btn.ForeColor = Color.White btn.FlatAppearance.BorderColor = ThemeColor.SecondaryColor End If Next label4.ForeColor = ThemeColor.SecondaryColor label5.ForeColor = ThemeColor.PrimaryColor End Sub End Class
Y eso es todo 🙂