MessageBox que se cierra tras X segundos en C#

Tamaño de letra:

Con contador incluido. Versión 1.0.3

MessageBox temporalHoy os traigo un código que he estado escribiendo esta tarde en C#, que a mí me ha resultado bastante útil y que permite crear un MessageBox con un contador.
Las características principales son las siguientes:

Boliche verde Muestra un MessageBox durante XX segundos (he puesto un máximo de 99 seg)
Boliche verde Muestra un contador (o no) de los segundos que van quedando
Boliche verde Cuando termina el contador, el MessageBox se cierra automáticamente

Pienso que es un código muy interesante que puedes implantar tanto en C# como en VB.NET. En las siguientes líneas te explicaré un poco cómo lo he creado, cómo se usa y algún problemilla que he tenido.

Cómo funciona

El funcionamiento es muy sencillo y a grandes rasgos hace lo siguiente:

  • Muestra un MessageBox
  • Crea un System.Threading.Timer que servirá para invocar al método "EjecutaCada1Segundo" cada 1 segundo.
  • Para encontrar el handle del texto del MessageBox se usan las API FindWindow y FindWindowEx
  • El handle es necesario para cambiar el texto con la API SetWindowText.
  • Tras terminar el contador, el MessageBox se cierra automáticamente con SendMessage y WM_CLOSE.

Puedes dejar el código más claro usando:
using System.Threading;

Si no quieres usar SetWindowText, puedes hacerlo con SendMessage y el mensaje WM_SETTEXT.

Cómo utilizarlo

Primero tienes que copiar el código de más abajo y pegarlo en tu código fuente (observa que es una nueva clase). Después debes llamar en tu código al MessageBoxTemporal de este modo:

MessageBoxTemporal.Show("Texto", "Titulo", 8, false);

Donde:

  • Texto: Es el texto que se mostrará en el cuerpo del MessageBox
  • Titulo: Es el título del MessageBox
  • 8: Son los segundos que durará el mensaje. No puedes poner más de 99 segundos.
  • false: true o false, bool que muestra o no el contador.
    False: aparecerá el MessageBox, se cerrará a los X segundos pero no aparecerá ninguna cadena de texto que diga: "Este mensaje se cerrará en X segundos".
    True: aparecerá el MessageBox, se cerrará a los X segundos y aparecerá un mensaje con un contador ("Este mensaje se cerrará en X segundos.")

Curiosidades

Debes saber que si modificas el código, no puedes, por defecto, añadir más caracteres de texto en el MessageBox con SetWindowText. Por eso verás que en el código he añadido tres puntos de más (...) para indicarlo por si falla.

En un MessageBox ha sido sencillo encontrar el handle del texto del mismo, ya que solo existe un control "Static", si no tendría que haber seguido con el proceso y con GW_HWNDNEXT.

Se añade automáticamente un texto -que tú puedes modificar-: "Este mensaje se cerrará dentro de X segundos."

Por ejemplo, si pones en tu código esto:

MessageBoxTemporal.Show("Mensaje de prueba para karmany.NET", "Título", 22, true);

La primera imagen que aparecerá será esta:

MessageBox temporal: 22 segundos

Y el contador de 22 segundos irá disminuyendo segundo a segundo hasta llegar a 0:

MessageBox temporal: 1 segundo

Momento en el que el MessageBox se cerrará automáticamente.

Y creo que no se me olvida nada más...

Código

Si veis algún fallo comentarlo...

 
public class MessageBoxTemporal
    {
        System.Threading.Timer IntervaloTiempo;
        string TituloMessageBox;
        string TextoMessageBox;
        int TiempoMaximo;
        IntPtr hndLabel = IntPtr.Zero;
        bool MostrarContador;
 
        MessageBoxTemporal(string texto, string titulo, int tiempo, bool contador)
        {
            TituloMessageBox = titulo;
            TiempoMaximo = tiempo;
            TextoMessageBox = texto;
            MostrarContador = contador;
 
            if (TiempoMaximo > 99) return; //Máximo 99 segundos
            IntervaloTiempo = new System.Threading.Timer(EjecutaCada1Segundo,
                null, 1000, 1000);
            if (contador)
            {
                DialogResult ResultadoMensaje = MessageBox.Show(texto + "\r\nEste mensaje se cerrará dentro de " +
                    TiempoMaximo.ToString("00") + " segundos ...", titulo);
                if (ResultadoMensaje == DialogResult.OK) IntervaloTiempo.Dispose();
            }
            else
            {
                DialogResult ResultadoMensaje = MessageBox.Show(texto + "...", titulo);
                if (ResultadoMensaje == DialogResult.OK) IntervaloTiempo.Dispose();
            }
        }
        public static void Show(string texto, string titulo, int tiempo, bool contador)
        {
            new MessageBoxTemporal(texto, titulo, tiempo, contador);
        }
        void EjecutaCada1Segundo(object state)
        {
            TiempoMaximo--;
            if (TiempoMaximo <= 0)
            {
                IntPtr hndMBox = FindWindow(null, TituloMessageBox);
                if (hndMBox != IntPtr.Zero)
                {
                    SendMessage(hndMBox, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
                    IntervaloTiempo.Dispose();
                }
            }
            else if(MostrarContador)
            {
                // Ha pasado un intervalo de 1 seg:
                if (hndLabel != IntPtr.Zero)
                {
                    SetWindowText(hndLabel, TextoMessageBox +
                        "\r\nEste mensaje se cerrará dentro de " +
                        TiempoMaximo.ToString("00") + " segundos");
                }
                else
                {
                    IntPtr hndMBox = FindWindow(null, TituloMessageBox);
                    if (hndMBox != IntPtr.Zero)
                    {
                        // Ha encontrado el MessageBox, busca ahora el texto
                        hndLabel = FindWindowEx(hndMBox, IntPtr.Zero, "Static", null);
                        if (hndLabel != IntPtr.Zero)
                        {
                            // Ha encontrado el texto porque el MessageBox
                            // solo tiene un control "Static".
                            SetWindowText(hndLabel, TextoMessageBox +
                                "\r\nEste mensaje se cerrará dentro de " +
                                TiempoMaximo.ToString("00") + " segundos");
                        }
                    }
                }
            }
        }
        const int WM_CLOSE = 0x0010;
        [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        [System.Runtime.InteropServices.DllImport("user32.dll",
            CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
        [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true,
            CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter,
            string lpszClass, string lpszWindow);
        [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true,
            CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        static extern bool SetWindowText(IntPtr hwnd, string lpString);
    }
 

Si el código te resulta útil, no cuesta nada agradecerlo con un mensaje...

Versiones

1.0.1 - 28 de julio de 2013

Primer código.

1.0.2 - 06 de agosto de 2013

Se repara el error por el que al aparecer el MessageBox y pulsar el botón Aceptar, el Timer no era liberado de memoria y no realizaba después correctamente la cuenta atrás.

1.0.3 - 17 de noviembre de 2013

Corregido error (Una instrucción incrustada no puede ser una declaración o una instrucción con etiqueta) comentado por el usuario David.

Última actualización: Domingo, 17 Noviembre 2013
Comentarios  
+1 # Victor 30-09-2023 17:57
Excelente, yo estaba buscando como ocultar la x del mensaje encontré este ejemplo. Fantástico
Responder | Responder con una citación | Citar
0 # Editor 30-09-2023 18:10
Gracias por tu comentario. Un saludo Víctor!!!
Responder | Responder con una citación | Citar
0 # Editor 30-09-2023 18:24
Víctor público tu mensaje sin email. Yo lo guardo y lo miraré:
"Si existe algún ejemplo para ocultar la X del messagebox favor dejar en un comentario " gracias.
Responder | Responder con una citación | Citar
+1 # MOISES 09-09-2023 11:21
GRACIAS :D
Responder | Responder con una citación | Citar
0 # Editor 09-09-2023 11:29
Un saludo MOISES
Responder | Responder con una citación | Citar
0 # JBB 26-01-2023 09:47
Muy util, muchas gracias!
Responder | Responder con una citación | Citar
+1 # Luis 20-10-2022 15:11
No sabes lo groso que sos, mil veces gracias
Responder | Responder con una citación | Citar
+1 # Geovanny Badilla Al 26-08-2021 22:37
Gracias amigo, tras que me ayudo un montón, no tuve problemas.
Mil gracias y un sin fin de Likes.
Responder | Responder con una citación | Citar
+1 # Rek 26-02-2020 21:10
EL DETALLE QUE CUANDO NO INGRESO POR ERRO UN DATO EN LA TABLA, ME SALEN LOS MENSAJES QUE INDICAN QUE DEBO DE INGRESAR VALORES, PERO UNA VEZ HECHO SE MANTIENEN LOS MENSAJES DE ERROR Y NO DESAPARECEN UNA VEZ INGRESADO LOS DATOS CORRECTAMENTE, AÚN CUANDO INGRESO UN NUEVO DATO SE MANTIENE EL MENSAJE DE ERROR ESPERO ME AYUDEN
Responder | Responder con una citación | Citar
+1 # KuroiPepe 11-09-2018 22:42
Gracias me ha sido muy útil el código.
Responder | Responder con una citación | Citar
0 # andresham 10-08-2018 17:46
gaGraciasGracia s `ppor el codigo , es muy utilk
Responder | Responder con una citación | Citar
+1 # Rodo76 23-02-2018 04:35
Hola me podrán ayudar por favor, porque lo pase a VB.Net con un convertidor de código, pero en muchas lineas de código me marca error. Alguien lo tiene bien hecho en VB.Net ?

Gracias !
Responder | Responder con una citación | Citar
0 # Editor 23-02-2018 22:37
He estado echando un vistazo y efectivamente el código en VB.NET no es tan sencillo de ejecutar porque da varios fallos. He intentado repararlos pero llevo tiempo sin usar VBNET y no me resulta de rápida solución.
Si puedo sacar algo de tiempo, lo analizaré y adaptaré para VB.NET pero realmente no es una prioridad porque prefiero C#. A ver si algún usuario es capaz de adaptarlo.
Un saludo.
Responder | Responder con una citación | Citar
0 # Jorge Caldera 19-09-2017 23:29
Funciona Perfecto Gracias
Responder | Responder con una citación | Citar
0 # pp 02-06-2017 20:25
No se puede hacer lo mismo pero que el message box sea del tipo yesNo?
Responder | Responder con una citación | Citar
0 # Editor 03-06-2017 13:23
Pero no entiendo el sentido. Por poder hacerse sí que se podría (no lo he probado) pero ¿qué diferencia habría entre pulsar sí o no?
Un saludo
Responder | Responder con una citación | Citar
0 # pp 05-06-2017 19:09
Es q en mi caso lo que necesito es que si pulsa si el contador se detenga y siga el flujo normal del programa y si pulsa no pues q se cierre todo de inmediato y si no hace nada q se cierre al terminar el lapso de tiempo pero lo he adaptado me sale el msj y logro que se cierre pero al acabar el tiempo no hace nada :/
Responder | Responder con una citación | Citar
0 # edwin 10-05-2017 07:25
Gracias Hermano me sirvio muchas gracias
Responder | Responder con una citación | Citar
0 # maugsi 24-02-2017 02:00
Gracias, funcionó perfecto.
Responder | Responder con una citación | Citar
0 # Poncho 26-01-2017 22:13
26-01-2017 Funciona correctamente! muy buen aporte!
Responder | Responder con una citación | Citar
0 # karmany 26-01-2017 23:26
Gracias por comprobarlo y comentar.
Un saludo
Responder | Responder con una citación | Citar
0 # Jorge 09-08-2016 11:43
Genio, la verdad muy util. gracias.
Responder | Responder con una citación | Citar
0 # Jhon 19-05-2016 01:04
Estimado:

Tengo problemas al convertirlo a vb.net

Public Shared Sub Show(texto As String, titulo As String, tiempo As Integer, contador As Boolean)
New MessageBoxTempo ral(texto, titulo, tiempo, contador)
End Sub

error de sintaxis en new

favor su apoyo gracias por compartir el codigo.

saludos :-)
Responder | Responder con una citación | Citar
0 # HOBY 11-01-2018 21:01
PUDISTES SOLUCIONAR EL PROBLEMA AMIGO..
Responder | Responder con una citación | Citar
0 # Gariel 26-04-2018 16:59
Dim MessageBoxTempo ral As New MessageBoxTempo ral(texto, titulo, tiempo, contador)
Responder | Responder con una citación | Citar
+1 # PecoroNero667 12-05-2016 19:38
Les comento que este código me ha sido de mucha utilidad, le hice algunas modificaciones para que pueda aceptar botones (Si, No, Cancelar, etc) y un icono (alert, error, info, etc); y que permita regresar el resultado del botón presionado por el usuario.

Lamentablemente no lo puedo publicar en este comentario porque en estos momentos me quedan menos de 636 caracteres, pero lo dejo en mi blog con una referencia a este sitio como fuente.

https://pecoronero667.wordpress.com/

Saludos a todos.
Responder | Responder con una citación | Citar
0 # karmany 12-05-2016 20:41
Seguro que nos será muy útil a muchos. Muchas gracias por comentar y tu aporte. Le echaré un vistazo.
Un saludo
Responder | Responder con una citación | Citar
0 # Manuel 21-10-2015 16:15
Muchas gracias, yo lo use en un hilo, muy intereasnte.
Responder | Responder con una citación | Citar
0 # DrUalcman 26-08-2015 06:42
Muy bueno este ejemplo. Voy a intentar mejorarlo un poquito haciendo que este centrado con respecto del formulario padre que es otra cosita que me gusta, si lo consigo os lo comento en esta misma pagina.
Responder | Responder con una citación | Citar
0 # Editor 26-08-2015 10:57
Ok. Lo añadiré al artículo.
Gracias
Responder | Responder con una citación | Citar
0 # Alex 11-05-2015 19:26
Muy buena, muchas Gracias.
Responder | Responder con una citación | Citar
0 # Santo Almonte 29-10-2014 04:41
Muchisimas gracias esta genial
Responder | Responder con una citación | Citar
0 # karmany 29-10-2014 17:44
Gracias a ti por comentar, un saludo...
Responder | Responder con una citación | Citar
0 # Gabo1276 06-05-2014 23:41
Estimado muy buen post lo felicito, mi duda es que lo estoy utilizando pero solo puedo invocarlo 1 ves, ya q que la segunda invocación ya no vuelve a aparecer el mensaje. Ojala me pudieses ayudar. Saludos
Responder | Responder con una citación | Citar
0 # karmany 07-05-2014 16:42
Umm! qué extraño, voy a echar un vistazo al código para ver que sigue bien y no se ha borrado nada.
Muchas veces al usar editores para escribir, estos modifican el código HTML.

De todos modos, voy a probarlo y luego te cuento...
Responder | Responder con una citación | Citar
0 # karmany 07-05-2014 19:06
Acabo de probar el código y funciona correctamente. Da más datos para ver dónde puede estar el error.
Responder | Responder con una citación | Citar
0 # SAul 01-04-2014 19:47
perdon es en la linea new MessageBoxTempo ral(texto, titulo, tiempo, contador); lo estoy pasando a vb.net
Responder | Responder con una citación | Citar
0 # Aitor 01-04-2014 21:44
Qué error te marca?
Responder | Responder con una citación | Citar
0 # SAul 01-04-2014 19:38
Me marca error en la linea New AutoClosingMess ageBox(text, caption, timeout) lo estoy convirtiendo a vb.net
Responder | Responder con una citación | Citar
0 # Omar 31-01-2014 17:46
Que buen post! Muchas gracias!
Responder | Responder con una citación | Citar
+2 # David 16-11-2013 22:29
me marca el siguiente error al copilar requiero algo mas

Error 1 Una instrucción incrustada no puede ser una declaración o una instrucción con etiqueta C:\Users\GNARCIA\Dropbox\Desarrollo\C\MS\Contabilidad\Contabilidad\frmFacturacionCFD.cs 928 17 Contabilidad

esta es la linea:
DialogResult ResultadoMensaj e = MessageBox.Show (texto + "\r\nEste mensaje se cerrará dentro de " +
TiempoMaximo.To String("00") + " segundos ...", titulo);
if (ResultadoMensaj e == DialogResult.OK ) IntervaloTiempo .Dispose();
Responder | Responder con una citación | Citar
0 # karmany 17-11-2013 00:30
Muchas gracias David por comentar el error.
No sé cómo ha ocurrido pero desaparecieron 2 corchetes: {}

Ya lo he reparado y puedes volver a copiar el código.
Saludos
Responder | Responder con una citación | Citar
+4 # karmany 06-08-2013 21:01
Hoy se ha actualizado el código a la versión 1.0.2
Esto corrige un problema al pulsar el botón Aceptar del MessageBox.
Responder | Responder con una citación | Citar
0 # WiNSoCk 31-07-2013 12:01
Chulisimo el post, me encanta la explicación, y como has ido buscando la forma de modificar el mensaje en caliente. Te ha quedado muy muy chulo.
Responder | Responder con una citación | Citar
+1 # karmany 31-07-2013 15:45
Muchas gracias por tu comentario. Ya vi tu ponencia en Albacete, queda mucho todavía y no sé si iré pero hay muchos temas interesantes.
Un saludo...
Responder | Responder con una citación | Citar
+1 # WiNSoCk 01-08-2013 01:31
Para mi, es un honor si te pasas a verlas, seguramente la mía te sabrá a poco, pero la de los compañeros son geniales, y hay algún que otro de la lista. Si haces un hueco, no dudes en avisar, para tomarnos algo!!
Responder | Responder con una citación | Citar
0 # karmany 01-08-2013 16:17
Los temas que se tratan son muy interesantes. Cuando vaya llegando la fecha, ya te diré si voy. Lo que no he visto en la web son los precios por ir a las conferencias.
Responder | Responder con una citación | Citar
0 # WiNSoCk 04-08-2013 18:09
¡Claro! ¡Es que es gratis! Funcionan con patrocinadores (Creo que siguen buscando). Intentan compartir conocimiento de forma gratuita. Ponencias de mucho nivel,además gratis, buen ambiente, y gente de lo más simpática.
Responder | Responder con una citación | Citar
0 # karmany 04-08-2013 18:20
¡¡Ahh!! Otro punto positivo más para intentar sacar tiempo para ir... Genial...
Responder | Responder con una citación | Citar
Escribir un comentario
Antes de publicar un comentario, usted debe aceptar nuestras condiciones de uso: Condiciones de uso. Debido al spam, todos los comentarios serán moderados. Normalmente se responde en unos minutos, refresca los comentarios para comprobarlo.



 
Visitas: 8495851