Archivo de la etiqueta: c#

Hacer ping con visual C#

h-pingLa forma más fácil de comprobar que un equipo esta “vivo” en nuestra red es haciendo un ping. Lo que hace este comando es enviar un paquete ICMP al equipo que queremos verificar, el equipo al recibir este paquete devuelve una confirmación de recepción. Con esta acción ya hemos comprobado que el equipo esta funcionando y conectado.

Cuando nuestro programa en Visual C# tiene que conectarse a cualquier otro equipo, nos puede interesar antes de ejecutar las funciones de conexión es si ese equipo esta disponible o no. Podemos confirmarlo fácilmente haciéndole un ping.

Hacer ping con Visual C#

En la biblioteca de .Net “System.Net.NetworkInformation” tenemos disponible una función que nos hará ese trabajo. Para poder usarla tendremos que agregar a nuestro proyecto la siguiente referencia “System.Net”, podemos agregar tambien el namespace “System.Net.NetworkInformation” para facilitar el trabajo con las funciones.

Para hacer ping tendremos que crear dos objetos, un objeto “ping” como tal, este el que enviara el paquete ICMP. Y el objeto PingReply, este manejara la información devuelta.

Ejemplo de uso:

Ping HacerPing = new Ping();
int iTiempoEspera = 5000;
PingReply RespuestaPing;
string sDireccion;
sDireccion = txtIP.Text;
RespuestaPing = HacerPing.Send(sDireccion, iTiempoEspera);
if (RespuestaPing.Status == IPStatus.Success)
{
    txtLog.AppendText("Ping a " +
        sDireccion.ToString() +
        "[" +
        RespuestaPing.Address.ToString() +
        "]" +
        " Correcto" +
        " Tiempo de respuesta = " +
        RespuestaPing.RoundtripTime.ToString() +
        " ms" +
        "\n")
}
 else
{
    txtLog.AppendText("Error: Ping a " +
        sDireccion.ToString() +
        "\n");
}

Explicación:

Creamos el objeto Ping.

Creamos una variable de tipo “int” para almacenar el tiempo de espera, este valor esta en milisegundos.

Creamos el objeto PingReply para el manejo de la respuesta del ping.

Variable de tipo “string” donde guardaremos la dirección IP del equipo que queremos verificar.

Hacemos el Ping, le pasamos como parámetros los la dirección Ip que queremos comprobar y el valor de tiempo de espera en milisegundos, este ultimo parámetro es opcional, indicándole la dirección Ip o el nombre del equipo seria suficiente. La respuesta se la pasamos al objeto PingReply.

Para comprobar el estado comprobamos el valor que nos devuelve PingReply.Status, este valor es del tipo “IPStatus”. Para saber si ha sido satisfactorio solo tenemos que comprobar que el estado es “IPStatus.Success”. Si se ha producido un error podemos comprobar el tipo de estado devuelto del “IPStatus”. Más información sobre “IPStatus” en la librería de MSDN

Desde el objeto PingReply podemos obtener otras informaciones, como puede ser la dirección Ip de la maquina remota, el tiempo que se ha tardado en realizar, valor devuelto en milisegundos, opciones que se ha utilizado para el envio del paquete ICMP o el buffer de los datos recibidos por el ICMP.

Personalizar la serialización de tipos en XML

Serialización con XML
Serialización con XML

Cuando queremos guardar en fichero XML alguna estructura de datos podemos recurrir a la serialización.

Con las funciones actuales disponibles para el manejo de XML en C# la serialización de estructuras de datos es relativamente sencilla. Pero el problema nos surge cuando en la estructura de datos hay algún tipo de objeto que, o no nos interesa el modo en que hace la conversión, por la razón que sea, o por que la serialización de ese objeto no esta soportada.

Para solucionar este problema C# nos proporciona los atributos [XMLIgnore], para indicarle al proceso de serialización que ignore ese objeto, y [XmlElement], donde le indicamos como se va ha convertir ese objeto.

Para indicar al proceso de serialización del XML que ese objeto lo ignore, solo tendremos que anteponer el atributo [XMLIgnore] delante del objeto que queremos. Por ejemplo:

[XmlIgnore]
public Image Imagen { get; set; }

En este caso el tipo “Image” no soporta serialización, por lo que la conversión la tendremos que realizar nosotros mismos.

Una que le hemos dicho que ignore ese objeto le tenemos que indicar como vamos a convertirlo. Para ello tendremos que crear nuestra función de conversión he indicarle que la use en para ese elemento. Para indicarle que objeto vamos a utilizar solo tenemos que utilizar el atributo [XmlElement(“Nombre_del_objeto”], le indicamos el nombre que le hemos dado al objeto, no el tipo. Por ejemplo:

[XmlElement("Imagen")]
public byte[] ConvertImageToByte
{
    // Devolvemos una cadena de byte cuando nos pasan la imagen
    get
        {
            byte[] ImagenByte = null;
            // Si el valor pasado es distinto a null, pasamos la conversión, sino pasamos null
            if (Imagen != null)
            {
                // Convertimos la imagen en un array de byte[]
                ImageConverter ConvertirImagen = new ImageConverter();
                ImagenByte = (byte[])ConvertirImagen.ConvertTo(Imagen, typeof(byte[]));
            }
        return ImagenByte;
    }

    // Devolvemos una imagen cuando nos pasan una cadena de byte[]
    set
    {
        // Si el valor pasado es null
        if (value == null)
        {
            // Devolvemos otro null
            Imagen = null;
        }
        else
        {
            // Convertimos el array de bytes[] en una imagen
            ImageConverter ConvertirImagen = new ImageConverter();
            Imagen = (Image)ConvertirImagen.ConvertFrom(value);
        }
    }
}

En el ejemplo se utiliza el objeto “Imagen” del ejemplo anterior que es de tipo “Image”, que no esta soportado por la serialización de XML. Lo que hacemos es convertilo en un array de byte para poderlo guardar en el fichero.

La parte del “get” la serialización de XML la utilizara cuando va ha grabar los datos, leeremos desde el objeto “Imagen” la imagen que queremos y con ayuda de la función “ImageConverter” la convertimos en un array de byte, le indicamos el formato que vamos a utilizar en el segundo parámetro que le pasamos a la función en este caso “typeof(byte[]).

ImageConverter ConvertirImagen = new ImageConverter();

ImagenByte = (byte[])ConvertirImagen.ConvertTo(Imagen, typeof(byte[]));

La parte del “set” la serialización de XML la usa cuando lee los datos desde el fichero de XML. Le pasara la cadena de byte que tiene grabada y cargara en la variable “Imagen” la imagen es su formato correcto, tipo “Image”. Para la conversión volvemos a utilizar la función “ImageConverter”, en este caso nos devolverá un objeto, para pasárselo a la variable solo tenemos que indicar que ese objeto es de tipo “Image”

ImageConverter ConvertirImagen = new ImageConverter();
Imagen = (Image)ConvertirImagen.ConvertFrom(value);

Si lo aplicamos a un objeto que es de un tipo soportado por la serialización de XML, lo que hará, sera ignorar su método de serialización y utilizar el que le indiquemos.

Si tienes alguna sugerencia sera bienvenida, deja un comentario.

Ajustar color de la fuente según el color de fondo en Visual C#

En ocasiones podemos necesitar ajustar el color de la fuente según el color del fondo del control. Por ejemplo poner el color de la fuente a blanco, por que el color del fondo es negro, o de cualquier otro color oscuro.

Esto se puede hacer calculando en nivel del color. Para este calculo yo utilizo la siguiente formula.

double coefienteOscuridad = 0.2126 * color.R + 0.7152 * color.G + 0.0722 * color.B;

Lo que hacemos es crear un coeficiente multiplicando cada valor de los calores básico por un coeficiente, ya que según el color básico hará que el color final sea mas o menos oscuro. Y por ultimo sumamos los resultado.

Según el valor devuelto podemos jugar con el color que deseemos.

Por ejemplo, si el coeficiente “coefienteOscuridad” es superior a 100, el color de la fuente sera negro, y por el contrario si el coeficiente es inferior el color de la fuente lo pongo a blanco.

El valor 100 lo he sacado de probar diferentes colores y ver como se distingue el texto.

Podemos jugar con el para ajustar el color de la fuente al color que más se ajuste a nuestras necesidades.

Ejemplo completo, en este ejemplo ajusta el color de la fuente, ha blanco o negro, de una celda de un dataGridView según el color de fondo de la celda:

// Calculamos el color de fondo para ajustar el color de la fuente
Color color = e.CellStyle.BackColor;
double coefienteOscuridad = 0.2126 * color.R + 0.7152 * color.G + 0.0722 * color.B;
// Indice de oscuridad
if ( coefienteOscuridad > 100)
{
// si el color es claro, el texto lo ponemos de color negro
e.CellStyle.ForeColor = Color.Black;
}
else
{
// si el color es oscuro, el texto lo ponemos de color blanco
e.CellStyle.ForeColor = Color.White;
}

Y con esto ya tendríamos ajustado el color de nuestra fuente para que sea totalmente legible, independientemente del color del fondo.

Si tienes alguna sugerencia o duda, no tengas ningún reparo en escribir un comentario.

Ejecutar aplicaciones con permisos de administrador en Visual Studio c#

En algunas ocasiones necesitamos que nuestras aplicaciones se ejecuten con lo privilegios de administrador. Para hacer esto en una aplicación desarrollada con Visual C# tenemos que añadir a nuestro proyecto un fichero de “Archivo de manifiesto de aplicación”. Para agregar el fichero, accedemos “Proyecto” – “Agregar nuevo elemento”, y seleccionamos “Archivo de manifiesto de aplicación”.

Captura_Agregar_Nuevo_Elemento

Esto nos creara el fichero “app.manifest”.

Captura_Archivo_manifiesto_aplicacion
Este fichero contiene varias opciones de configuración, pero las opciones que nos interesan son:

<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">

<!-- Opciones del manifiesto de Control de cuentas de usuario

Si desea cambiar el nivel de Control de cuentas de usuario de Windows, reemplace el

nodo requestedExecutionLevel por alguno de los siguientes.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
La especificación del nodo requestedExecutionLevel deshabilitará la virtualización de archivos y del Registro.

Si desea usar la virtualización de archivos y del Registro para la compatibilidad

con versiones anteriores, elimine el nodo requestedExecutionLevel.

-->

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

</requestedPrivileges>

requestedPrivileges
En la parte comentada nos muestra los niveles disponibles:

asInvoke: Nivel de seguridad por defecto.

requireAdministrator: Nivel de seguridad como administrador.

highestAvailable: Nivel de seguridad el mayor posible.

Para indicar que nuestra aplicación va a trabajar con nivel de seguridad de administrador, solo tenemos que copiar la linea:

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

requestedExecutionLevel_administrador
de la parte comentada, y sobre escribir:

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

de la parte no comentada.

requestedExecutionLevel_administrador_sobreescrito
Después de guardar los cambios, si le damos al botón de “Inicar”, el Visual Studio se reiniciara para ejecutarse con permisos de administrado.

Si ejecutamos el ejecutable de la aplicación nos mostrar la típica ventana para aceptar los privilegios de administrador.

Como recorrer todos los componentes de un form o un panel

En determinadas ocasiones tenemos que realizar una misma operación en todos los componentes, ya sean iguales o distintos, que están en un formulario, dentro de un panel, etc.

Lo mas fácil seria ir uno por uno haciendo el cambio deseado, si son unos pocos, no seria mucho problemas, pero cuando son muchos esto puede ser un engorro, pudiendo llevarnos a introducir errores en nuestros código.

Otra opción es ir recorriendo todos los componentes que están dentro de nuestro formulario y comprobar de que clase es, y si es del tipo que tenemos que hacer el cambio, entonces pasamos a hacérselo.

Esto lo podemos hacer de la siguiente forma:

Para saber cuantos componentes tiene nuestro formulario utilizaremos la opción “Controls”.  Este tiene varios parámetros que nos indican cuantos “controles” hay en nuestro formulario, el tipo, etc. Con esta información que nos facilita “Controls” podemos recorrer todos los componentes que hay.

foreach (Control cComprobar in fFormulario.Controls)
{
    // Codigo de control para el componente
}

Este código nos permite recorrer todos los controles que tenemos situados en nuestro formulario.

Ahora tenemos que saber de que tipo es el control, para ello solo tenemos que preguntárselo.

if (cComprobar is PictureBox) 
{
     // Si es del tipo que queremos lo procesamos
}

En este caso queremos saber si es un “PictureBox”, pero si queremos saber si es de otro tipo, por ejemplo, si queremos modificar un “TextBox”, cambiamos el “PictureBox” por “TextBox”. Y así según el tipo deseado.

Ejemplo:

foreach (Control cComponente in fFormulario.Controls)
{
    if (cComponente is PictureBox)
    {
        cComponente.Image = Image.FromFile(sNuevaImagen);
    }
}

Pero puede suceder que no a todos los componentes que tenenos en nuestro formulario queramos modificarlos. Para esto, yo me aprovecho de la opción “Tag” que tienen todos los controles. En esta opción podemos introducir  el texto que deseemos. Solo tengo que marcar todos los controles que no quiero modificar y cuando lo recorro comprobar que quiero cambiarlo.

if ((string)cComponente.Tag != "estono")
{
    // Este control si lo quiero modificar
}

y con esto ya podemos realizar cualquier cambio a nuestros controles, sin tener que repetir el código para cada unos de ellos.

Y tu, si utilizas otro método puedes compartirlo con nosotros, solo tienes que dejar un comentario.

Hacer que un Label sea realmente transparente en C#

En ocasiones necesitamos que en los “label” se vea el fondo, por que es una foto, cambia de color y no queremos ir cambiando el fondo de cada label, etc.

En la opción de color de fondo del “label”, en la pestaña de web, podemos elegir que el fondo sea transparente, que fácil, pongo el color en transparente y listo, ya podemos cambiar el fondo cuando queramos.

Opcion BackColor del Label
Parámetro para seleccionar el color de fondo
Color transparente Label
Poner el color del fondo en transparente

Pues no, esto funciona si lo que cambiamos es el fondo de formulario, pero si tenemos un “picturebox” o un “panel” o cualquier otra cosa que no sea el fondo del formulario, esto no funciona.

Esto se debe a que cuando añadimos un nuevo componente a nuestro formulario, este es automáticamente propiedad del formulario, y por ello el “label”, toma por defecto el color de fondo de su dueño.

Esto nos da la solución, si el color de fondo es el del propietario, lo que tenemos que hacer, para que nos funcione, es decirle quien es el dueño de nuestro “label” para que este, pueda coger el fondo que nosotros deseamos.

// Asignamos el propietario del label al picturebox
label1.parent = picturebox1;

Esto, para la mayoría de los casos, funciona, pero si el “label” lo vamos a mover por el formulario en tiempo de ejecución, este método nos puede causar un error. Debido a que el “label” esta fuera de su dueño.

Para solucionarlo tenemos que controlar en cada momento por donde movemos el “label”, y si esta fuera del “panel” o del “picturebox”, etc. bloquearlo y que no salga.

Para este problema se puede utilizar componentes externos al C#. pero como no era mi caso, no los he probado.

Otra cosa, si lo que queremos es hacer una especie de “OSD” para un vídeo (poner un texto y que se vea el vídeo por detrás), esto tampoco funciona. Los componentes de vídeo, ya sea el media player o VLC, son una especie de derivados de un panel, por lo que si le pasamos como propietaria a nuestro “label” el componente de vídeo, este tomara el color del fondo del componente que soporta el vídeo, es decir, el color del panel.

Aun así, con todos los “peros”, este método es la solución para el 90% de los casos.

Si tienes otra solución puedes compartirla en los comentarios.

 

 

Conocer la duración del video en VideoLan (VLC) con C#

VLMC-IconTrasteando un poco con el activeX del VLC no encontraba como podía obtener la duración del vídeo que estaba reproduciendo. No tenia que ser muy difícil, es su reproductor se muestra, así que por algún lado tenia que haber una función  que devolviera el dichoso valor.  Encontré una que te devolvía todos los metadatos del vídeo, e incluso la posición actual en la que esta la reproducción del vídeo. Pero nada sobre la duración.

Después de darle varias vueltas, encontré una que, una vez que ha comenzado ha reproducirse el vídeo, nos devuelve esa información. Mientras tanto devuelve 0, lo que me engaño vilmente.

Para poder ver el valor tenemos que capturar el evento.

vVideoLan.MediaPlayerPlaying += vVideoLan_MediaPlayerPlaying;

Este evento salta cuando se pone a reproducir el vídeo.

Dentro de este evento podemos llamar a la función que ya nos devuelve la duración del vídeo.

TimeSpan tDuracionVideo = TimeSpan.FromMilliseconds(vVideoLan.input.Length);

La función “input.Legnth” nos devuelve la duración del vídeo en milisegundos.

Una vez que conocemos la duración del vídeo, podemos pasar ha obtener la posición actual de la reproducción. Esto es más fácil, solo tenemos que capturar el evento.

vVideoLan.MediaPlayerTimeChanged += vVideoLan_MediaPlayerTimeChanged;

Este evento se producirá cada vez que la posición del vídeo cambie, para saber la posición solo tenemos que poner.

int tPosicion = e.time;

Teniendo estos datos, ya se puede hacer la típica barra de progreso para saber cuanto falta para terminar el vídeo.

Pero resulta que tenemos un problema, no se, si es una fallo del VLC o que, pero el valor de “input.Length” y el valor final de “e.time” no son el mismo. El valor final de “e.time”, y todas la variantes que se puede obtener para sacar la misma información que he encontrada en el VLC, es unos milisegundos superior. Por lo que si lo ponemos de esta forma en una barra de progresos.

double max = fVideoLan.vVideoLan.input.Length;
pbPlay.Minimum = 0;
pbPlay.Maximum = (int)max;

// en MediaPlayerTimeChanged
pbPlay.Value = (int)fVideoLan.vVideoLan.input.Time;

Al llegar al final del vídeo, nos genera un error que le valor el superior al valor maximo. La diferencia es pequeña, no llega un segundo, por las pruebas que he hecho, ronda los 500 – 800 milisegundos, varia con cada video, no es fija. Por lo que, antes de pasar el valor actual de la posición del vídeo a la barra de progreso, compruebo que el valor sea igual o inferior.

if ( pbPlay.Maximum > vVideoLan.input.Time )
{
    pbPlay.Value = (int)vVideoLan.input.Time;
}

Y así es como lo he solucionado, si alguien sabe como obtener la duración del vídeo de otra forma o como solucionar el problema del desfase de la duración puede dejar un comentario.

Abrir un Form en cualquier pantalla utlizando C#

Virt7En la actualidad es bastante habitual el tener más de una pantalla conectado a nuestro ordenador, ya sea dos pantallas, pantalla y televisión, etc.

Esto lo podemos aprovecharlo para mostrar diferentes ventanas de nuestros programa en cada una de las pantallas.

Windows maneja los multimonitores como si fuera uno con la resolución de la suma de todos ellos, es decir, si tenemos 2 monitores con una resolución de 1024×768 cada uno, para windows la resolución de la pantalla sera de 2048×768.

Con lo que, para poder posicionar nuestro nuevo formulario en el otro monitor, le sumaríamos  la resolución de nuestro monitor al parámetro “left” de nuestro nuevo Form. Si solo utilizamos 2 monitores no hay problema, pero cuando son varios monitores y con distintas resoluciones cada uno, se complica la cosa.

Para hacernos la vida mas fácil, C#  dispone de una clase llamada “Screen” de donde podemos obtener mucha información de las pantallas que tenemos instaladas en nuestro equipo. Una de estas funciones que hay en “Screen” es “Bound”, esta función nos devuelve la posición de la esquina superior izquierda, es decir, “Left” y “Top” donde empieza cada una de las pantallas.

Declaración de la variable

// Declaramos una variable para manejar los monitores
Screen[] sMonitores;
sMonitores = Screen.AllScreens;

Funcionamiento

// Posicion del formulario
fNuevo.Left = sMonitores[1].Bounds.Left;
fNuevo.Top = sMonitores[ 1].Bounds.Top;

Como siempre, cuando hacemos referencia a una lista la posición siempre empieza por “0”. Si queremos referirnos al monitor 2, tendríamos que por 1.

Este ejemplo abriría nuestro nuevo formulario en la posición 0, 0 de la pantalla 2.

Si queremos posicionarlo en otro lugar de la pantalla que fuese la 0, 0, sumaríamos el desplazamiento correspondiente tanto al parámetro “Left” como al “Top”.

// Posicion del formulario
fNuevo.Left = sMonitores[2].Bounds.Left + 200;
fNuevo.Top = sMonitores[2].Bounds.Top + 100;

En este otro ejemplo, el formulario se abriría en la posición 200×100 del monitor 3.

Para saber cuantos monitores tenemos funcionando en nuestro equipo podemos utilizar la siguiente función.

NumMonitoresFuncionando = sMonitor.Rank + 1

Y ya esta con esto podemos abrir nuestro Form en cualquier monitor sin preocuparnos que resolución tiene cada uno.

Preguntar antes de cerrar un programa en C#

[singlepic id=5 w=320 h=240 float=right]Muchas veces cuando cerramos nuestro programa en C# necesitamos verificar que realmente se quiere cerrar el programa. Para hacer esto solo necesitamos utilizar la función “FormClosing”

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    DialogResult dialogo = MessageBox.Show("¿Desea cerrar el programa?",
               "Cerrar el programa", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
    if (dialogo == DialogResult.No)
    {
        e.Cancel = true;
    }
    else
    {
        e.Cancel = false;
    }
}

Para cancelar el cierre de la aplicación solo tenemos que poner a “true” la función “e.cancel”, esto hará que se cancele el cierre del programa.

A si de fácil y sencillo o no?

Verificar en C# el formato de una dirección de e-mail

[singlepic id=4 w=320 h=240 float=right]Cuando queremos que el usuario introduzca una dirección de e-mail en nuestro programa en C#, siempre nos queda la duda si la dirección es correcta o no. El siguiente código en C# nos permite comprobar que la dirección de e-mail que se introduzca este por lo menos en su formato correcto, es decir, “nombre”@”Dominio”.”extensión”. Esta comprobación no asegura que la dirección sea valida, solo que el formato introducido es el correcto.

Para hacer la comprobación nos ayudamos de la clase Regex, esta función permite mediante un patrón verificar si una cadena cumple con ese patrón  Para poder utilizar la clase Regex tenemos que añadir el siguiente nombre de espacio

using System.Text.RegularExpressions;

Código  que comprueba el formato del e-mail introducido:

public static bool ComprobarFormatoEmail(string sEmailAComprobar)
{ 
    String sFormato; 
    sFormato = "\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
    if (Regex.IsMatch(seMailAComprobar, sFormato)) 
    {
        if (Regex.Replace(seMailAComprobar, sFormato, String.Empty).Length == 0) 
        { 
            return true; 
        } 
        else
        { 
            return false; 
        } 
    } 
    else
    { 
        return false;
    }
}

La función nos devolverá “true”, si el formato del email es correcto, o “false” si el formato del email es incorrecto. Ejemplo de como trabajar con la función.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

// Para la función regex
using System.Text.RegularExpressions;

namespace Verificar_Correo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public static bool ComprobarFormatoEmail(string seMailAComprobar)
        { 
            String sFormato; 
            sFormato = "\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
            if (Regex.IsMatch(seMailAComprobar, sFormato)) 
            {
                if (Regex.Replace(seMailAComprobar, sFormato, String.Empty).Length == 0) 
                { 
                    return true; 
                } 
                else
                { 
                    return false; 
                } 
            } 
            else
            { 
                return false;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (ComprobarFormatoEmail(tbEmail.Text) == false)
            {
                lEmailCorrecto.Text = "Dirección no valida";
                lEmailCorrecto.ForeColor = Color.Red;
            }
            else
            {
                lEmailCorrecto.Text = "Dirección valida";
                lEmailCorrecto.ForeColor = Color.Green;
            }
        }
    }
}

Puedes descargar todos los ficheros desde aquí.

 

Y esto es todo, sabiendo que el formato del email  es correcto, la siguiente comprobación seria saber si la dirección es valida, es decir, si pertenece a una cuenta real. Pero eso sera para otro post.