En este tutorial les voy a mostrar cómo realizar un formulario Login de Usuario utilizando el lenguaje de programación C# .NET en Visual Studio 2022. Utilizaremos el NET FRAMEWORK 4.8, componentes de ADO.NET, como base de datos usaremos SQL Server 2019. El desarrollo de la aplicación tendrá una Arquitectura en Capas (Entidades, Acceso a Datos, Negocio y Presentación) . Además, diseñaremos una interfaz moderna con las librerías MetroFramework + FontAwesome Icons.

Extra:

  1. Envío de datos de sesión a formulario principal.
  2. Hasheo de password utilizando el algoritmo de encriptación SHA2 512

Estructura del Proyecto


1. Creación de la Base de Datos

	

USE master
GO
IF EXISTS (
    SELECT [name]
        FROM sys.databases
        WHERE [name] = N'Trujillosoft'
)
DROP DATABASE Trujillosoft
GO
CREATE DATABASE Trujillosoft
GO

1.1 Creación de Tabla Usuario

	

USE Trujillosoft
GO
CREATE TABLE dbo.Usuario (
  id int NOT NULL IDENTITY (1, 1),
  idUsuario varchar(10) NOT NULL PRIMARY KEY,
  dsUsuario varchar(100) NULL,
  dsPassword binary(64) NULL,
  idEstado char(1) NOT NULL,
  idUsuCreacion varchar(10) NOT NULL,
  feCreacion datetime NOT NULL,
  idUsuModificacion varchar(10) NOT NULL,
  feModificacion datetime NOT NULL
)
GO

1.2 Insertando Datos en la Tabla Usuario

	

INSERT INTO [dbo].[Usuario]
( -- Columnas
 idUsuario,dsUsuario,dsPassword,idEstado,idUsuCreacion,feCreacion,idUsuModificacion,feModificacion
)
VALUES
( -- Valores
 'ADM','Administrador',HASHBYTES('SHA2_512','123456'),'A','ADM',GETDATE(),'ADM',GETDATE()
)
GO

1.3 Creando Procedimiento Almacenado de Validación de Login

	

CREATE PROCEDURE dbo.uspUsuarioLogin
(
    @idUsuario varchar(10),
    @dsPassword varchar(50)
)
AS
BEGIN
    SET NOCOUNT ON

    SELECT id,idUsuario,dsUsuario,dsPassword,idEstado,idUsuCreacion,feCreacion,idUsuModificacion,feModificacion
    FROM dbo.Usuario
    WHERE idUsuario = @idUsuario
    AND dsPassword = HASHBYTES('SHA2_512',@dsPassword)
    AND idEstado = 'A'
END
GO

2. Capa de Entidades

2.1 E_Usuario.cs

Clase que contendrá las propiedades de la entidad Usuario

	

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Entidades
{
    public class E_Usuario
    {
        public int id { get; set; } 
        public string idUsuario { get; set; }
        public string dsUsuario { get; set; }
        public string dsPassword { get; set; }
        public string idEstado { get; set; }
        public string idUsuCreacion { get; set; }
        public DateTime feCreacion { get; set; }
        public string idUsuModificacion { get; set; }
        public DateTime feModificacion { get; set; }
        
    }

}

3. Capa de Acceso a Datos

En esta capa se debe agregar la referencia a la capa de Entidades. Además, se debe tener instalado la librería de System.Data.SqlClient desde el administrador de paquetes NuGet



3.1 D_Base.cs

Clase base que tendrá la cadena de conexión a la base de datos SQL Server

	

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Datos
{
    public class D_Base
    {
        public static string strCadenaConexion = @"
            SERVER = LAPTOP-JS5QEV6S\SQL2019EXPRESS;
            DATABASE = Trujillosoft;
            USER ID= userbd;
            PASSWORD= userbd
        ";
    }
}

3.2 D_Usuario.cs

Clase que contendrá la función de validación de login a través de un procedimiento almacenado, de ser exitoso el inicio de sesión, retornará datos del usuario logueado.

	

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Entidades;
using System.Data;
using System.Data.SqlClient;

namespace Datos
{
    public class D_Usuario: D_Base
    {
        public static E_Usuario Login(string strUsuario, string strPassword)
        {
            try
            {
                using (SqlConnection cn = new SqlConnection(strCadenaConexion))
                {
                    cn.Open();
                    using (SqlCommand cmd = new SqlCommand("uspUsuarioLogin", cn))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@idUsuario",strUsuario);
                        cmd.Parameters.AddWithValue("@dsPassword", strPassword);

                        using (SqlDataReader dr = cmd.ExecuteReader())
                        {
                            E_Usuario Usuario;
                            List<E_Usuario> lstUsuario = new List<E_Usuario>();
                            while (dr.Read())
                            {
                                Usuario = new E_Usuario();
                                Usuario.id = Convert.ToInt32(dr["id"]);
                                Usuario.idUsuario = Convert.ToString(dr["idUsuario"]);
                                Usuario.dsUsuario = Convert.ToString(dr["dsUsuario"]);
                                lstUsuario.Add(Usuario);
                            }
                            return lstUsuario.FirstOrDefault();
                        }

                    }

                }
            }
            catch (Exception ex)
            {

                throw ex;
            }

        }
    }
}


4. Capa de Negocio

En esta capa se debe agregar la referencia a la capa de Datos y Entidades

4.1 N_Usuario.cs

	

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Entidades;
using Datos;


namespace Negocio
{
    public class N_Usuario
    {
        public static E_Usuario Login(string strUsuario, string strPassword)
        {
            return D_Usuario.Login(strUsuario,strPassword);
        }
    }
}

5. Capa de Presentación

En esta capa se debe agregar la referencia a la capa de Negocio y Entidades. Además, debe estar configurado como proyecto de inicio.

5.1 Requisitos

Instalar desde el administrador de paquetes NuGet:




5.2 Diseño Login



5.3 frmLogin.cs

Clase que contendrá la lógica de interfaz de usuario de login

	

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MetroFramework.Forms;
using MetroFramework;
using FontAwesome.Sharp;
using System.Drawing;
using Entidades;
using Negocio;
using System.Windows.Forms;


namespace Presentacion
{
    public class frmLogin: MetroForm
    {
        private IconPictureBox pbxLogin;
        private MetroFramework.Controls.MetroPanel pnlLineaSuperior;
        private MetroFramework.Controls.MetroPanel pnlLineaInferior;
        private MetroFramework.Controls.MetroLabel lblUsuario;
        private MetroFramework.Controls.MetroLabel lblPassword;
        private MetroFramework.Controls.MetroTextBox txtUsuario;
        private MetroFramework.Controls.MetroTextBox txtPassword;
        private IconButton btnIniciarSesion;
        private MetroFramework.Controls.MetroPanel pnlLateral;

        public frmLogin() {
            InitializeComponent();
            CargarIconos();
        }

        #region Diseño
        private void InitializeComponent()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmLogin));
            this.pnlLateral = new MetroFramework.Controls.MetroPanel();
            this.pbxLogin = new FontAwesome.Sharp.IconPictureBox();
            this.pnlLineaSuperior = new MetroFramework.Controls.MetroPanel();
            this.pnlLineaInferior = new MetroFramework.Controls.MetroPanel();
            this.lblUsuario = new MetroFramework.Controls.MetroLabel();
            this.lblPassword = new MetroFramework.Controls.MetroLabel();
            this.txtUsuario = new MetroFramework.Controls.MetroTextBox();
            this.txtPassword = new MetroFramework.Controls.MetroTextBox();
            this.btnIniciarSesion = new FontAwesome.Sharp.IconButton();
            ((System.ComponentModel.ISupportInitialize)(this.pbxLogin)).BeginInit();
            this.SuspendLayout();
            // 
            // pnlLateral
            // 
            this.pnlLateral.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pnlLateral.BackgroundImage")));
            this.pnlLateral.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
            this.pnlLateral.HorizontalScrollbarBarColor = true;
            this.pnlLateral.HorizontalScrollbarHighlightOnWheel = false;
            this.pnlLateral.HorizontalScrollbarSize = 10;
            this.pnlLateral.Location = new System.Drawing.Point(0, 4);
            this.pnlLateral.Name = "pnlLateral";
            this.pnlLateral.Size = new System.Drawing.Size(460, 500);
            this.pnlLateral.TabIndex = 0;
            this.pnlLateral.VerticalScrollbarBarColor = true;
            this.pnlLateral.VerticalScrollbarHighlightOnWheel = false;
            this.pnlLateral.VerticalScrollbarSize = 10;
            // 
            // pbxLogin
            // 
            this.pbxLogin.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))));
            this.pbxLogin.ForeColor = System.Drawing.SystemColors.ControlText;
            this.pbxLogin.IconChar = FontAwesome.Sharp.IconChar.UserShield;
            this.pbxLogin.IconColor = System.Drawing.SystemColors.ControlText;
            this.pbxLogin.IconFont = FontAwesome.Sharp.IconFont.Auto;
            this.pbxLogin.IconSize = 132;
            this.pbxLogin.Location = new System.Drawing.Point(568, 63);
            this.pbxLogin.Name = "pbxLogin";
            this.pbxLogin.Size = new System.Drawing.Size(139, 132);
            this.pbxLogin.TabIndex = 1;
            this.pbxLogin.TabStop = false;
            // 
            // pnlLineaSuperior
            // 
            this.pnlLineaSuperior.BackColor = System.Drawing.Color.Gray;
            this.pnlLineaSuperior.HorizontalScrollbarBarColor = true;
            this.pnlLineaSuperior.HorizontalScrollbarHighlightOnWheel = false;
            this.pnlLineaSuperior.HorizontalScrollbarSize = 10;
            this.pnlLineaSuperior.Location = new System.Drawing.Point(487, 249);
            this.pnlLineaSuperior.Name = "pnlLineaSuperior";
            this.pnlLineaSuperior.Size = new System.Drawing.Size(300, 1);
            this.pnlLineaSuperior.TabIndex = 2;
            this.pnlLineaSuperior.UseCustomBackColor = true;
            this.pnlLineaSuperior.VerticalScrollbarBarColor = true;
            this.pnlLineaSuperior.VerticalScrollbarHighlightOnWheel = false;
            this.pnlLineaSuperior.VerticalScrollbarSize = 10;
            // 
            // pnlLineaInferior
            // 
            this.pnlLineaInferior.BackColor = System.Drawing.Color.Gray;
            this.pnlLineaInferior.HorizontalScrollbarBarColor = true;
            this.pnlLineaInferior.HorizontalScrollbarHighlightOnWheel = false;
            this.pnlLineaInferior.HorizontalScrollbarSize = 10;
            this.pnlLineaInferior.Location = new System.Drawing.Point(487, 412);
            this.pnlLineaInferior.Name = "pnlLineaInferior";
            this.pnlLineaInferior.Size = new System.Drawing.Size(300, 1);
            this.pnlLineaInferior.TabIndex = 3;
            this.pnlLineaInferior.UseCustomBackColor = true;
            this.pnlLineaInferior.VerticalScrollbarBarColor = true;
            this.pnlLineaInferior.VerticalScrollbarHighlightOnWheel = false;
            this.pnlLineaInferior.VerticalScrollbarSize = 10;
            // 
            // lblUsuario
            // 
            this.lblUsuario.AutoSize = true;
            this.lblUsuario.Location = new System.Drawing.Point(507, 277);
            this.lblUsuario.Name = "lblUsuario";
            this.lblUsuario.Size = new System.Drawing.Size(56, 20);
            this.lblUsuario.TabIndex = 4;
            this.lblUsuario.Text = "Usuario";
            // 
            // lblPassword
            // 
            this.lblPassword.AutoSize = true;
            this.lblPassword.Location = new System.Drawing.Point(507, 318);
            this.lblPassword.Name = "lblPassword";
            this.lblPassword.Size = new System.Drawing.Size(66, 20);
            this.lblPassword.TabIndex = 5;
            this.lblPassword.Text = "Password";
            // 
            // txtUsuario
            // 
            this.txtUsuario.BackColor = System.Drawing.Color.LightGray;
            // 
            // 
            // 
            this.txtUsuario.CustomButton.Image = null;
            this.txtUsuario.CustomButton.Location = new System.Drawing.Point(167, 2);
            this.txtUsuario.CustomButton.Name = "";
            this.txtUsuario.CustomButton.Size = new System.Drawing.Size(27, 27);
            this.txtUsuario.CustomButton.Style = MetroFramework.MetroColorStyle.Blue;
            this.txtUsuario.CustomButton.TabIndex = 1;
            this.txtUsuario.CustomButton.Theme = MetroFramework.MetroThemeStyle.Light;
            this.txtUsuario.CustomButton.UseSelectable = true;
            this.txtUsuario.CustomButton.Visible = false;
            this.txtUsuario.DisplayIcon = true;
            this.txtUsuario.FontSize = MetroFramework.MetroTextBoxSize.Medium;
            this.txtUsuario.Lines = new string[0];
            this.txtUsuario.Location = new System.Drawing.Point(590, 270);
            this.txtUsuario.MaxLength = 32767;
            this.txtUsuario.Name = "txtUsuario";
            this.txtUsuario.PasswordChar = '\0';
            this.txtUsuario.PromptText = "Ingrese usuario";
            this.txtUsuario.ScrollBars = System.Windows.Forms.ScrollBars.None;
            this.txtUsuario.SelectedText = "";
            this.txtUsuario.SelectionLength = 0;
            this.txtUsuario.SelectionStart = 0;
            this.txtUsuario.ShortcutsEnabled = true;
            this.txtUsuario.Size = new System.Drawing.Size(197, 32);
            this.txtUsuario.TabIndex = 6;
            this.txtUsuario.UseCustomBackColor = true;
            this.txtUsuario.UseSelectable = true;
            this.txtUsuario.WaterMark = "Ingrese usuario";
            this.txtUsuario.WaterMarkColor = System.Drawing.Color.FromArgb(((int)(((byte)(109)))), ((int)(((byte)(109)))), ((int)(((byte)(109)))));
            this.txtUsuario.WaterMarkFont = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Pixel);
            // 
            // txtPassword
            // 
            this.txtPassword.BackColor = System.Drawing.Color.LightGray;
            // 
            // 
            // 
            this.txtPassword.CustomButton.Image = null;
            this.txtPassword.CustomButton.Location = new System.Drawing.Point(167, 2);
            this.txtPassword.CustomButton.Name = "";
            this.txtPassword.CustomButton.Size = new System.Drawing.Size(27, 27);
            this.txtPassword.CustomButton.Style = MetroFramework.MetroColorStyle.Blue;
            this.txtPassword.CustomButton.TabIndex = 1;
            this.txtPassword.CustomButton.Theme = MetroFramework.MetroThemeStyle.Light;
            this.txtPassword.CustomButton.UseSelectable = true;
            this.txtPassword.CustomButton.Visible = false;
            this.txtPassword.DisplayIcon = true;
            this.txtPassword.FontSize = MetroFramework.MetroTextBoxSize.Medium;
            this.txtPassword.Lines = new string[0];
            this.txtPassword.Location = new System.Drawing.Point(590, 311);
            this.txtPassword.MaxLength = 32767;
            this.txtPassword.Name = "txtPassword";
            this.txtPassword.PasswordChar = '●';
            this.txtPassword.PromptText = "Ingrese password";
            this.txtPassword.ScrollBars = System.Windows.Forms.ScrollBars.None;
            this.txtPassword.SelectedText = "";
            this.txtPassword.SelectionLength = 0;
            this.txtPassword.SelectionStart = 0;
            this.txtPassword.ShortcutsEnabled = true;
            this.txtPassword.Size = new System.Drawing.Size(197, 32);
            this.txtPassword.TabIndex = 7;
            this.txtPassword.UseCustomBackColor = true;
            this.txtPassword.UseSelectable = true;
            this.txtPassword.UseSystemPasswordChar = true;
            this.txtPassword.WaterMark = "Ingrese password";
            this.txtPassword.WaterMarkColor = System.Drawing.Color.FromArgb(((int)(((byte)(109)))), ((int)(((byte)(109)))), ((int)(((byte)(109)))));
            this.txtPassword.WaterMarkFont = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Pixel);
            // 
            // btnIniciarSesion
            // 
            this.btnIniciarSesion.BackColor = System.Drawing.Color.DodgerBlue;
            this.btnIniciarSesion.FlatAppearance.BorderColor = System.Drawing.Color.Aqua;
            this.btnIniciarSesion.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
            this.btnIniciarSesion.ForeColor = System.Drawing.Color.White;
            this.btnIniciarSesion.IconChar = FontAwesome.Sharp.IconChar.ArrowCircleRight;
            this.btnIniciarSesion.IconColor = System.Drawing.Color.White;
            this.btnIniciarSesion.IconFont = FontAwesome.Sharp.IconFont.Auto;
            this.btnIniciarSesion.IconSize = 28;
            this.btnIniciarSesion.ImageAlign = System.Drawing.ContentAlignment.MiddleRight;
            this.btnIniciarSesion.Location = new System.Drawing.Point(590, 353);
            this.btnIniciarSesion.Name = "btnIniciarSesion";
            this.btnIniciarSesion.Size = new System.Drawing.Size(197, 37);
            this.btnIniciarSesion.TabIndex = 8;
            this.btnIniciarSesion.Text = "Iniciar Sesion";
            this.btnIniciarSesion.UseVisualStyleBackColor = false;
            this.btnIniciarSesion.Click += new System.EventHandler(this.btnIniciarSesion_Click);
            // 
            // frmLogin
            // 
            this.ClientSize = new System.Drawing.Size(800, 500);
            this.Controls.Add(this.btnIniciarSesion);
            this.Controls.Add(this.txtPassword);
            this.Controls.Add(this.txtUsuario);
            this.Controls.Add(this.lblPassword);
            this.Controls.Add(this.lblUsuario);
            this.Controls.Add(this.pnlLineaInferior);
            this.Controls.Add(this.pnlLineaSuperior);
            this.Controls.Add(this.pbxLogin);
            this.Controls.Add(this.pnlLateral);
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = "frmLogin";
            this.Resizable = false;
            this.TopMost = true;
            ((System.ComponentModel.ISupportInitialize)(this.pbxLogin)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion


        private void CargarIconos()
        {
            var imgUsuario = IconChar.User.ToBitmap(Color.DodgerBlue, 28);
            var imgPassword = IconChar.Lock.ToBitmap(Color.DodgerBlue, 28);

            txtUsuario.Icon = imgUsuario;
            txtPassword.Icon = imgPassword; 
        }

        private void btnIniciarSesion_Click(object sender, EventArgs e)
        {
            if (!ValidarUsuario())
                return;

            string strUsuario = txtUsuario.Text.Trim();
            string strPassword = txtPassword.Text.Trim();

            E_Usuario Usuario = N_Usuario.Login(strUsuario,strPassword);

            if (Usuario != null)
            {
                this.Hide();
                frmPrincipal frm = new frmPrincipal();
                frm.SESION_USUARIO = Usuario;
                frm.Show();
            }
            else
            {
                MetroMessageBox.Show(this, "Usuario o clave incorrecto", "Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);

            }
        }

        private bool ValidarUsuario()
        {
            if (string.IsNullOrEmpty(txtUsuario.Text.Trim()))
            {
                MetroMessageBox.Show(this, "Ingrese usuario", "Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                txtUsuario.Focus();
                return false;
            }
            if (string.IsNullOrEmpty(txtPassword.Text.Trim()))
            {
                MetroMessageBox.Show(this, "Ingrese password", "Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                txtPassword.Focus();
                return false;
            }
            return true;
        }
    }
}


5.4 Diseño Formulario Principal



5.5 frmPrincipal.cs

Clase que contendrá la lógica de interfaz del formulario principal. En este formulario se recibirán los datos de inicio de sesión

	

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MetroFramework.Forms;
using Entidades;
using System.Windows.Forms;

namespace Presentacion
{
    public class frmPrincipal: MetroForm
    {
        public E_Usuario SESION_USUARIO { get; set; }

        private MetroFramework.Controls.MetroLabel lblUsuario;
        private MetroFramework.Controls.MetroLabel metroLabel1;

        public frmPrincipal()
        {
            InitializeComponent();
        }

        #region Diseño
        private void InitializeComponent()
        {
            this.metroLabel1 = new MetroFramework.Controls.MetroLabel();
            this.lblUsuario = new MetroFramework.Controls.MetroLabel();
            this.SuspendLayout();
            // 
            // metroLabel1
            // 
            this.metroLabel1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.metroLabel1.AutoSize = true;
            this.metroLabel1.FontWeight = MetroFramework.MetroLabelWeight.Bold;
            this.metroLabel1.Location = new System.Drawing.Point(653, 47);
            this.metroLabel1.Name = "metroLabel1";
            this.metroLabel1.Size = new System.Drawing.Size(87, 20);
            this.metroLabel1.TabIndex = 0;
            this.metroLabel1.Text = "Bienvenido";
            // 
            // lblUsuario
            // 
            this.lblUsuario.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.lblUsuario.AutoSize = true;
            this.lblUsuario.FontWeight = MetroFramework.MetroLabelWeight.Bold;
            this.lblUsuario.Location = new System.Drawing.Point(758, 47);
            this.lblUsuario.Name = "lblUsuario";
            this.lblUsuario.Size = new System.Drawing.Size(80, 20);
            this.lblUsuario.TabIndex = 1;
            this.lblUsuario.Text = "lblUsuario";
            // 
            // frmPrincipal
            // 
            this.ClientSize = new System.Drawing.Size(1000, 800);
            this.Controls.Add(this.lblUsuario);
            this.Controls.Add(this.metroLabel1);
            this.MinimumSize = new System.Drawing.Size(750, 500);
            this.Name = "frmPrincipal";
            this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.frmPrincipal_FormClosing);
            this.Load += new System.EventHandler(this.frmPrincipal_Load);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private void frmPrincipal_Load(object sender, EventArgs e)
        {
            lblUsuario.Text = SESION_USUARIO.dsUsuario;
        }

        private void frmPrincipal_FormClosing(object sender, FormClosingEventArgs e)
        {
            Application.Exit();
        }
    }
}


5.6 Program.cs

Configuramos la aplicación con el formulario de inicio frmLogin

	

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Presentacion
{
    internal static class Program
    {
        /// 
        /// Punto de entrada principal para la aplicación.
        /// 
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new frmLogin());
        }
    }
}

Video completo del tutorial en mi canal


Copyright © 2021 TRUJILLOSOFT