1

I am coding Windows Forms in C# under Visual Studio 2012 and I would like to open multiple instances of MessageBox and automatically close them after several seconds.

I have found (and upvoted) this answer here: SO: Close a MessageBox after several seconds.

However, this works if I only open 1 (one) MessageBox at a time, since it makes use of the function FindWindow, and the multiple instances of my MessageBox shall have all the same window title (caption).

[Optionally] In addition, I would like to present the user with a countdown, like This dialog will close in 5 seconds, This [...] in 4 seconds, This [...] in 3 seconds, ..., This [...] in 1 seconds and then finally close the MessageBox.

Is there a way to uniquely reference my multiple MessageBoxes and automatically close them (either using System.Timers.Timer or System.Threading.Timer or System.Windows.Forms.Timer - whichever is the best fit for this solution) after a certain period of time (say 5 seconds)?

2
  • Are you sure that message boxes are the right solution here? It sounds like you're trying to re-implement notifications. Commented Feb 4, 2014 at 15:07
  • Hi @Damien_The_Unbeliever, I have thought about and looked into notifications, but in my case I really need messageboxes... (: Commented Feb 4, 2014 at 15:08

3 Answers 3

4

I suggest not using a MessageBox for this task. Instead, make your own custom form. Make it the size, shape, and look you want. Then, in its code-behind file, you can create a timer, unique to that window itself. That way, you can spawn as many of them as you want, and they will manage their own timers and closing themselves, and you don't have to do anything like finding the window. It's possible to make a Form look very much like a MessageBox. And because you can call ShowDialog, you can make them behave similarly to MessageBoxes as well (though that would be somewhat counterproductive, because you can only interact with one dialog at a time).

Sign up to request clarification or add additional context in comments.

3 Comments

Hi @Curtis Rutland thank you for your thoughts and the idea of simulating a MessageBox by using a custom form. I will definitly explore this idea further!
I've accepted this answer because it is really hassle free to implement (with the counter and also with my optional requirement to display / count down the time in seconds). Thanks again, @Curtis Rutland!
Glad to help. I find that more often than not, a second perspective gives you simple solutions you otherwise wouldn't have thought of, especially when you're going down the rabbit hole in a different direction.
1

There is an undocumented MessageBoxTimeout function in windows that you could use: MessageBoxTimeout in user32.dll (use via PInvoke).

Example:

public class MessageBoxWithTimeout
{
  [DllImport("user32.dll", SetLastError = true)]
  [return: MarshalAs(UnmanagedType.U4)]
  private static extern uint MessageBoxTimeout(IntPtr hwnd,
    [MarshalAs(UnmanagedType.LPTStr)]  String text,
    [MarshalAs(UnmanagedType.LPTStr)] String title,
    [MarshalAs(UnmanagedType.U4)] uint type, 
    Int16 wLanguageId, 
    Int32 milliseconds);

  public static uint Show(IntPtr hWnd, string message, string caption, uint messageBoxOptions,Int32 timeOutMilliSeconds)
  {
     return MessageBoxTimeout(hWnd, message, caption, messageBoxOptions, 0, timeOutMilliSeconds);
  }
}

In your code:

MessageBoxWithTimeout.Show( your parameters here );

However, you should think about your design. A message box by definition is blocking your dialog, so multiple messageboxes do not make sense. If you post your actual problem, maybe there is a better solution.

1 Comment

Hi @nvoigt, thank you for you answer and code example. My applications has two modes of operation: 1) user actively makes input to a form, and 2) applications runs automatically (watches a folder for changes). In both modes, I need to show a dialog (MessageBox). When the app is in mode 1), the user needs to confirm to carry on. When in mode 2), the dialog should close in 5 seconds automatically. Hence, I am happy with a MessageBox blocking my dialog (this is wanted), all other tasks are run in the background using Threads... I will play with your code snippet for sure (:
1

The following code can be used a as a starting point. It's based on the related answer I gave recently.

async void MainForm_Load(object sender, EventArgs e)
{
    Func<Func<Form>, Task<Form>> showAsync = (createForm) =>
    {
        var tcs = new TaskCompletionSource<Form>();
        var form = createForm();
        form.Tag = Task.Factory.StartNew(
            () => form.ShowDialog(), 
            CancellationToken.None, 
            TaskCreationOptions.None,
            TaskScheduler.FromCurrentSynchronizationContext());
        form.Load += (sIgnore, eIgnore) =>
            tcs.TrySetResult(form);
        return tcs.Task;
    };

    var forms = new Stack<Form>();
    for (var i = 0; i < 4; i++)
        forms.Push(await showAsync((() =>
            new Form { Text = "Hello #" + i })));

    var closeFormTasks = forms.Select((form) => (Task)form.Tag);

    var delay = Task.Delay(5000);
    var task = await Task.WhenAny(delay, Task.WhenAll(closeFormTasks));

    if (task == delay)
    {
        while (forms.Any())
        {
            var form = forms.Pop();
            form.Close();
            await (Task)form.Tag;
        }
    }

    MessageBox.Show("All closed.");
}

1 Comment

Hi @Noseratio, thank you very much for sharing this piece of code! I really like the concept. However, I will go with the solution Curtis Rutland has suggested (mimicking MessageBoxes with plain old forms).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.