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); }