1

我在 Visual Studio 2012 下使用 C# 编写 Windows 窗体,我想打开多个 MessageBox 实例并在几秒钟后自动关闭它们。

我在这里找到(并赞成)这个答案:SO: Close a MessageBox after few seconds

但是,如果我一次只打开 1(一个)MessageBox,则此方法有效,因为它使用 function FindWindow,并且我的 MessageBox 的多个实例应具有所有相同的窗口标题(标题)。

[可选]另外,我想给用户一个倒计时,比如这个对话框将在 5 秒内关闭这个 [...] 在 4 秒内这个 [...] 在 3 秒内,...,这 [...] 在 1 秒内最后关闭 MessageBox。

有没有办法唯一地引用我的多个 MessageBox 并在一段时间(比如 5 秒)后自动关闭它们(使用System.Timers.TimerSystem.Threading.Timer或- 最适合此解决方案的任何一个)?System.Windows.Forms.Timer

4

3 回答 3

4

我建议不要为此任务使用 MessageBox。相反,制作您自己的自定义表单。使其具有您想要的大小、形状和外观。然后,在其代码隐藏文件中,您可以创建一个计时器,该计时器是该窗口本身独有的。这样,您可以根据需要生成任意数量的它们,它们将管理自己的计时器并自行关闭,而您无需执行任何操作,例如查找窗口。可以使 Form 看起来非常像 MessageBox。并且因为您可以调用 ShowDialog,您也可以使它们的行为类似于 MessageBoxes(尽管这会适得其反,因为您一次只能与一个对话框交互)。

于 2014-02-04T15:10:22.327 回答
1

下面的代码可以作为起点。它基于我最近给出的相关答案。

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.");
}
于 2014-02-04T16:35:40.373 回答
1

您可以在 Windows 中使用未记录的 MessageBoxTimeout 函数:user32.dll 中的 MessageBoxTimeout(通过PInvoke使用)。

例子:

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

在您的代码中:

MessageBoxWithTimeout.Show( your parameters here );

但是,您应该考虑您的设计。根据定义,消息框会阻止您的对话框,因此多个消息框没有意义。如果您发布实际问题,也许有更好的解决方案。

于 2014-02-04T15:14:16.923 回答