WinForm 下我们可以调用MessageBox.Show 来显示一个消息对话框,提示用户确认等操作。在有些应用中我们需要通过程序来自动关闭这个消息对话框而不是由用户点击确认按钮来关闭。然而.Net framework 没有为我们提供自动关闭MessageBox 的方法,要实现这个功能,我们需要使用Window API 来完成。
首先我们需要找到这个消息对话框的窗口句柄,一个比较简单的方法就是用 FindWindow API 来查找对应的窗体句柄。
- [DllImport("user32.dll", SetLastError = true)]
- static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
这个API调用可以通过窗口的类名或者窗口标题的名字来查找窗口句柄。
接下来我们还需要找到一个 API 来关闭对话框,这里我使用 EndDialog
- [DllImport("user32.dll")]
- static extern bool EndDialog(IntPtr hDlg, out IntPtr nResult);
有了这两个API函数,我们就可以来关闭消息对话框了。思路是在调用MessageBox.Show 前启动一个后台工作线程,这个工作线程等待一定时间后开始查找消息对话框的窗口句柄,找到后调用EndDialog API 函数关闭这个消息对话框。不过这个方法有个问题,就是如果同时又多个同名的消息对话框(可能不一定是这个应用的),这样做可能会关错窗口,如何解决这个问题,我还没有想出比较好的方法,如果大家有更好的方法解决这个问题,不妨一起讨论讨论。
我根据这个思路编写了延时关闭消息对话框的函数
- public void ShowMessageBoxTimeout(string text, string caption,
- MessageBoxButtons buttons, int timeout)
- {
- ThreadPool.QueueUserWorkItem(new WaitCallback(CloseMessageBox),
- new CloseState(caption, timeout));
- MessageBox.Show(text, caption,buttons);
- }
这个函数中timeout 参数单位是毫秒,其他参数和MessageBox.Show的参数含义是一样的,这里不再详细说明。
这个函数中首先利用线程池调用一个工作线程 CloseMessageBox ,并将对话框的标题和延时时间通过CloseState这个类传递给CloseMessageBox函数。
CloseState 的定义如下:
- private class CloseState
- {
- private int _Timeout;
- /**//// <summary>
- /// In millisecond
- /// </summary>
- public int Timeout
- {
- get
- {
- return _Timeout;
- }
- }
- private string _Caption;
- /**//// <summary>
- /// Caption of dialog
- /// </summary>
- public string Caption
- {
- get
- {
- return _Caption;
- }
- }
- public CloseState(string caption, int timeout)
- {
- _Timeout = timeout;
- _Caption = caption;
- }
- }
最后就是CloseMessageBox函数了,直接看代码吧
- private void CloseMessageBox(object state)
- {
- CloseState closeState = state as CloseState;
- Thread.Sleep(closeState.Timeout);
- IntPtr dlg = FindWindow(null, closeState.Caption);
- if (dlg != IntPtr.Zero)
- {
- IntPtr result;
- EndDialog(dlg, out result);
- }
- }