我正在使用Visual Studio 2012在C#中编写Windows窗体,我想在几秒钟之后打开MessageBox的多个实例并自动关闭它们。
我在这里找到(并赞成)这个答案:SO: Close a MessageBox after several seconds。
然而,如果我一次只打开1(一个)MessageBox,这是有效的,因为它使用了函数FindWindow
,而我的MessageBox的多个实例将具有所有相同的窗口标题(标题)
[可选] 此外,我想向用户显示倒计时,例如此对话框将在5秒后关闭,此[.. 。]在4秒内,这[...]在3秒内,...,这[...]在1秒内然后终于关闭MessageBox。
有没有办法独特地引用我的多个MessageBox并自动关闭它们(使用System.Timers.Timer
或System.Threading.Timer
或System.Windows.Forms.Timer
- 最适合此解决方案的一个)一段时间(比如5秒)?
答案 0 :(得分:4)
我建议不要使用MessageBox来执行此任务。相反,制作自己的自定义表单。使它成为你想要的尺寸,形状和外观。然后,在其代码隐藏文件中,您可以创建一个对该窗口本身唯一的计时器。这样,您可以根据需要生成尽可能多的计时器,并且他们将管理自己的计时器并自行关闭,而您无需执行任何操作,例如查找窗口。可以使Form看起来非常像MessageBox。因为你可以调用ShowDialog,你可以使它们的行为与MessageBoxes类似(虽然这会产生一定的反作用,因为你一次只能与一个对话框进行交互)。
答案 1 :(得分: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 );
但是,你应该考虑一下你的设计。根据定义,消息框会阻止您的对话框,因此多个消息框没有意义。如果您发布实际问题,可能有更好的解决方案。
答案 2 :(得分:1)
以下代码可用作起点。它基于我最近给出的related answer。
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.");
}