HowTo: Crear una pantalla de inicio (splash screen)

Nota: Otro post en respuesta a una pregunta bastante habitual en los foros MSDN: ¿Cómo crear una pantalla de inicio para mi aplicación?

He creado un pequeño proyecto de ejemplo, que pueda servir como plantilla base para que cada uno se lo personalice para su aplicación. Este proyecto tiene lo básico: Un formulario sin bordes con una imagen, una barra de progreso, una etiqueta para el título, otra para ir mostrando mensajes, y un botón por si se desea cancelar la carga del programa (al estilo Office 2010).

SplashScreen

Él proyecto es muy sencillo y lo podéis descargar desde aquí:

La pantalla de inicio utiliza un thread para mostrar los diferentes mensajes al cargar, ya que así no se bloquea la aplicación (y la barra de progreso). Esto es así porque en el proyecto de ejemplo, al cargar la pantalla de inicio se lanza un segundo hilo que llama a un método ‘initApplication’, y desde éste método simulamos varios procesos largos (en realidad de un segundo cada uno), y cada vez que se inicia uno de ellos hay que cambiar el mensaje:

public void initApplication()

{

    Thread.Sleep(DEFAULT_TIME);

    this.Invoke((MethodInvoker)(() => setMessage("Searching for updates...")));

    Thread.Sleep(DEFAULT_TIME);

    this.Invoke((MethodInvoker)(() => setMessage("Connectiong to database...")));

    Thread.Sleep(DEFAULT_TIME);

    this.Invoke((MethodInvoker)(() => setMessage("Connectiong to webservices...")));

    Thread.Sleep(DEFAULT_TIME);

    this.Invoke((MethodInvoker)(() => setMessage("Loading settings...")));

    Thread.Sleep(DEFAULT_TIME);

    this.Invoke((MethodInvoker)(() => setMessage("Loading user preferences...")));

    Thread.Sleep(DEFAULT_TIME);

    this.Invoke((MethodInvoker)(() => setMessage("Starting application...")));

    Thread.Sleep(DEFAULT_TIME);

    if (this.InvokeRequired) this.Invoke(new Action(finishProcess));

}

Recordar que desde un hilo que no sea el hilo principal, en .NET no se puede actualizar la interfaz de usuario directamente. En su lugar debemos usar el método Invoke. En el ejemplo anterior llamamos a un método ‘setMessage’ que se encarga de mostrar el texto en la etiqueta correspondiente. Para poder llamar a este método mediante Invoke tenemos dos opciones: Podemos usar un MethodInvoker o un Action, en nuestro caso usaremos el primero, ya que un Action se usa cuando no hay paso de parámetros, y este método precisa de un parámetro con el mensaje a mostrar:

public void setMessage(string msg)

{

    messageLabel.Text = msg;

}

Una vez finalizado el proceso de carga, se cierra el formulario y se devuelve un DialogResult = Ok. Por otro lado si en cualquier momento de la carga el usuario ha pulsado el botón ‘close’, se hace lo mismo pero devolviendo un DialogResult = Cancel:

private void finishProcess()

{

    this.DialogResult = System.Windows.Forms.DialogResult.OK;

    this.Close();

}

void closeButton_Click(object sender, EventArgs e)

{

    this.DialogResult = System.Windows.Forms.DialogResult.Cancel;

    this.Close();

}

Como veis el proyecto es muy sencillo, sólo debéis recordar un detalle importante: En una aplicación WinForms el punto de entrada a la misma se define en el método estático Main del Program.cs, y aquí hay una línea que inicializa el formulario inicial de nuestra aplicación:

Application.Run(new fMain());

Lo primero que solemos pensar es que aquí deberíamos lanzar el formulario fSplashScreen, y al cerrarlo mostrar el formulario principal, verdad? Pues no, no podemos hacer eso. El motivo no es otro que este formulario inicial va a definir el ciclo de vida de nuestra aplicación, y si lo cerramos, cerramos la aplicación. Ya se que en VB puede cambiarse este comportamiento, pero entre nosotros… hacerlo siempre me ha parecido una chapuza 🙂

Así pues, aquí lanzaremos el formulario principal, y éste, al cargarse (mientras todavía no es visible) lanzará la pantalla de inicio de forma modal y esperará el valor de retorno. Si al cerrarse la pantalla de bienvenida el valor de retorno es Ok, continúa la carga y muestra el formulario principal, en caso contrario cierra el formulario principal y con por ende la aplicación:

void fMain_Load(object sender, EventArgs e)

{

    showSplashScreen();

}

 

private void showSplashScreen()

{

    using (fSplashScreen fsplash = new fSplashScreen())

    {

        if (fsplash.ShowDialog() == System.Windows.Forms.DialogResult.Cancel) this.Close();

    }

}

Espero que sirva como ejemplo a todos aquellos que desean tener una pantalla de inicio para sus aplicaciones. Un saludo!

Andorra, Noviembre 2010

Leave a Reply

Your email address will not be published. Required fields are marked *


*