Autoclose Message Box

There are times when you may want to display a MessageBox and after X seconds, if a user has not closed the message box, automatically close it.

Below is a simple example of how this may be achieved by creating a thread that runs an anonymous method. This anonymous method can directly access the outer-scope variables, in particular the EventWaitHandle used for signalling. The end result is a simple static method.

NOTE: There are many examples on the web for how this may be achieved, but nearly all of them require a class to hold state information.

public static MessageBoxAutoClose
{
  /// <summary>
  /// Displays a MessageBox to the user.
  /// </summary>
  /// <param name="title">The title for the MessageBox.</param>
  /// <param name="message">The message for the MessageBox.</param>
  /// <param name="autoCloseTimeSpan">The time to wait prior to auto-closing the message box.</param>
  public static void Show(string title, string message, TimeSpan autoCloseTimeSpan) 
  {
    // Create a thread that will auto-close the MessageBox 
    // after a period of time if a user hasn't clicked it.
    EventWaitHandle wait_handle = new AutoResetEvent(false);
    Thread auto_close_thread = new Thread(delegate()
    {
      try
      {
          // Wait to be signalled that the MessageBox is closed.
          if (!wait_handle.WaitOne(autoCloseTimeSpan))
          {
              // User failed to click okay - attempt to auto-close dialogue.
              IntPtr message_box_handle = Native.FindWindow(null, title);
              if (message_box_handle != IntPtr.Zero)
              {
                  Native.SendMessage(
                    message_box_handle, 
                    Native.WM_CLOSE, 
                    IntPtr.Zero, 
                    IntPtr.Zero);
              }
          }
      }
      catch
      {
          // Swallow all thread exceptions
      }
    });
  
    // Start the auto-close thread.
    auto_close_thread.Start();

    // Show the error message box.
    MessageBox.Show(message, title);

    // Notify the auto-close thread that we have shut-down the MessageBox.
    wait_handle.Set();
    auto_close_thread.Join();
    wait_handle.Dispose();
  }
}

This can be easily extended to match all the MessageBox.Show signatures.

For completeness, the Native methods are shown below.

/// <summary>
/// Wrapper class for the native method calls.
/// </summary>
internal class Native
{
  /// <summary>
  /// Retrieves a handle to the top-level window whose class name and window name
  /// match the specified strings. This function does not search child windows. 
  /// This function does not perform a case-sensitive search..
  /// </summary>
  /// <param name="className">Name of the class. If className is NULL, it finds any window
  /// whose title matches the windowName parameter. </param>
  /// <param name="windowName">Name of the window.</param>
  /// <returns>If the function succeeds, the return value is a handle to the window
  /// that has the specified class name and window name. If the function fails, the return value is NULL.</returns>
  [DllImport("user32.dll", SetLastError = true)]
  internal static extern IntPtr FindWindow(string className, string windowName);
  
  /// <summary>
  /// Sends the specified message to a window or windows.
  /// </summary>
  /// <param name="hwnd">A handle to the window whose window procedure will receive the message.</param>
  /// <param name="msg">The message to be sent.</param>
  /// <param name="wparam">Additional message-specific information wparam.</param>
  /// <param name="lparam">Additional message-specific information lparam.</param>
  /// <returns>The return value specifies the result of the message processing; it depends on the message sent.</returns>
  [DllImport("user32.dll", CharSet = CharSet.Auto)]
  internal static extern IntPtr SendMessage(IntPtr hwnd, uint msg, IntPtr wparam, IntPtr lparam);
}

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>