WinForm 下我们可以调用MessageBox.Show 来显示一个消息对话框,提示用户确认等操作。在有些应用中我们需要通过程序来自动关闭这个消息对话框而不是由用户点击确认按钮来关闭。然而.Net framework 没有为我们提供自动关闭MessageBox 的方法,要实现这个功能,我们需要使用Window API 来完成。
首先我们需要找到这个消息对话框的窗口句柄,一个比较简单的方法就是用 FindWindow API 来查找对应的窗体句柄。
第一种方法:
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
有了这两个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函数了,直接看代码吧
//注意提示出现的是、否按钮 不能自动关闭
//例如这个提示就不能自动关闭:
//if (MessageBox.Show("是否接听?", "来电:" + num, MessageBoxButtons.YesNo, //MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button2) == DialogResult.Yes) // {}
//以下是源码
[DllImport("coredll.dll", EntryPoint = "FindWindow", CharSet = CharSet.Auto)] private extern static IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("coredll.dll", CharSet = CharSet.Auto)] public static extern int PostMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); public const int WM_CLOSE = 0x10; private string _caption;//标题名字
//在弹出提示窗体,需为这个变量赋值
例如:
if (MessageBox.Show("是否接听?", "来电:" + num, MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button2) == DialogResult.Yes) {}
赋值就是:
_caption="来电:" + num;//明白
[System.Runtime.InteropServices.DllImport("coredll")]
public static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);//参数:窗体句柄
public const int SW_MINIMIZE = 6;
public static string CodePath = "";
//这个方法直接调用就行,直接关闭当前show出的界面,根据那个标题名字
private void KillMessageBox() { try { //查找MessageBox的弹出窗口,注意对应标题 IntPtr ptr = FindWindow(null, this._caption); if (ptr != IntPtr.Zero) { //查找到窗口则关闭 PostMessage(ptr, WM_CLOSE, IntPtr.Zero, IntPtr.Zero); } } catch (Exception ex) { MessageBox.Show("关闭show"+ex.ToString()); } }