WinForm 下实现一个自动关闭的MessageBox

WinForm 下实现一个自动关闭的MessageBox

Author: eaglet
      WinForm 下我们可以调用MessageBox.Show 来显示一个消息对话框,提示用户确认等操作。在有些应用中我们需要通过程序来自动关闭这个消息对话框而不是由用户点击确认按钮来关闭。然而.Net framework 没有为我们提供自动关闭MessageBox 的方法,要实现这个功能,我们需要使用Window API 来完成。
      首先我们需要找到这个消息对话框的窗口句柄,一个比较简单的方法就是用 FindWindow API 来查找对应的窗体句柄。

WinForm 下实现一个自动关闭的MessageBox        [DllImport("user32.dll", SetLastError = true)]
WinForm 下实现一个自动关闭的MessageBox        
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
WinForm 下实现一个自动关闭的MessageBox

      这个API调用可以通过窗口的类名或者窗口标题的名字来查找窗口句柄。

      接下来我们还需要找到一个 API 来关闭对话框,这里我使用 EndDialog
WinForm 下实现一个自动关闭的MessageBox        [DllImport("user32.dll")]
WinForm 下实现一个自动关闭的MessageBox        
static extern bool EndDialog(IntPtr hDlg, out IntPtr nResult);

      有了这两个API函数,我们就可以来关闭消息对话框了。思路是在调用MessageBox.Show 前启动一个后台工作线程,这个工作线程等待一定时间后开始查找消息对话框的窗口句柄,找到后调用EndDialog API 函数关闭这个消息对话框。不过这个方法有个问题,就是如果同时又多个同名的消息对话框(可能不一定是这个应用的),这样做可能会关错窗口,如何解决这个问题,我还没有想出比较好的方法,如果大家有更好的方法解决这个问题,不妨一起讨论讨论。
     
      我根据这个思路编写了延时关闭消息对话框的函数

WinForm 下实现一个自动关闭的MessageBox
WinForm 下实现一个自动关闭的MessageBox        public void ShowMessageBoxTimeout(string text, string caption, 
WinForm 下实现一个自动关闭的MessageBox            MessageBoxButtons buttons, 
int timeout)
WinForm 下实现一个自动关闭的MessageBox        
{
WinForm 下实现一个自动关闭的MessageBox            ThreadPool.QueueUserWorkItem(
new WaitCallback(CloseMessageBox), 
WinForm 下实现一个自动关闭的MessageBox                
new CloseState(caption, timeout));
WinForm 下实现一个自动关闭的MessageBox            MessageBox.Show(text, caption,buttons);
WinForm 下实现一个自动关闭的MessageBox        }
WinForm 下实现一个自动关闭的MessageBox

   这个函数中timeout 参数单位是毫秒,其他参数和MessageBox.Show的参数含义是一样的,这里不再详细说明。
   这个函数中首先利用线程池调用一个工作线程 CloseMessageBox ,并将对话框的标题和延时时间通过CloseState这个类传递给CloseMessageBox函数。
   CloseState 的定义如下:
   
WinForm 下实现一个自动关闭的MessageBox
WinForm 下实现一个自动关闭的MessageBox        private class CloseState
WinForm 下实现一个自动关闭的MessageBox        
{
WinForm 下实现一个自动关闭的MessageBox            
private int _Timeout;
WinForm 下实现一个自动关闭的MessageBox
WinForm 下实现一个自动关闭的MessageBox            
/// <summary>
WinForm 下实现一个自动关闭的MessageBox            
/// In millisecond
WinForm 下实现一个自动关闭的MessageBox            
/// </summary>

WinForm 下实现一个自动关闭的MessageBox            public int Timeout
WinForm 下实现一个自动关闭的MessageBox            
{
WinForm 下实现一个自动关闭的MessageBox                
get
WinForm 下实现一个自动关闭的MessageBox                
{
WinForm 下实现一个自动关闭的MessageBox                    
return _Timeout;
WinForm 下实现一个自动关闭的MessageBox                }

WinForm 下实现一个自动关闭的MessageBox            }

WinForm 下实现一个自动关闭的MessageBox
WinForm 下实现一个自动关闭的MessageBox            
private string _Caption;
WinForm 下实现一个自动关闭的MessageBox
WinForm 下实现一个自动关闭的MessageBox            
/// <summary>
WinForm 下实现一个自动关闭的MessageBox            
/// Caption of dialog
WinForm 下实现一个自动关闭的MessageBox            
/// </summary>

WinForm 下实现一个自动关闭的MessageBox            public string Caption
WinForm 下实现一个自动关闭的MessageBox            
{
WinForm 下实现一个自动关闭的MessageBox                
get
WinForm 下实现一个自动关闭的MessageBox                
{
WinForm 下实现一个自动关闭的MessageBox                    
return _Caption;
WinForm 下实现一个自动关闭的MessageBox                }

WinForm 下实现一个自动关闭的MessageBox            }

WinForm 下实现一个自动关闭的MessageBox
WinForm 下实现一个自动关闭的MessageBox            
public CloseState(string caption, int timeout)
WinForm 下实现一个自动关闭的MessageBox            
{
WinForm 下实现一个自动关闭的MessageBox                _Timeout 
= timeout;
WinForm 下实现一个自动关闭的MessageBox                _Caption 
= caption;
WinForm 下实现一个自动关闭的MessageBox            }

WinForm 下实现一个自动关闭的MessageBox        }
WinForm 下实现一个自动关闭的MessageBox

最后就是CloseMessageBox函数了,直接看代码吧
WinForm 下实现一个自动关闭的MessageBox
WinForm 下实现一个自动关闭的MessageBox        private void CloseMessageBox(object state)
WinForm 下实现一个自动关闭的MessageBox        
{
WinForm 下实现一个自动关闭的MessageBox            CloseState closeState 
= state as CloseState;
WinForm 下实现一个自动关闭的MessageBox
WinForm 下实现一个自动关闭的MessageBox            Thread.Sleep(closeState.Timeout);
WinForm 下实现一个自动关闭的MessageBox            IntPtr dlg 
= FindWindow(null, closeState.Caption);
WinForm 下实现一个自动关闭的MessageBox
WinForm 下实现一个自动关闭的MessageBox            
if (dlg != IntPtr.Zero)
WinForm 下实现一个自动关闭的MessageBox            
{
WinForm 下实现一个自动关闭的MessageBox                IntPtr result;
WinForm 下实现一个自动关闭的MessageBox                EndDialog(dlg, 
out result);
WinForm 下实现一个自动关闭的MessageBox            }

WinForm 下实现一个自动关闭的MessageBox        }
WinForm 下实现一个自动关闭的MessageBox



完整可用代码

WinForm 下实现一个自动关闭的MessageBoxWinForm 下实现一个自动关闭的MessageBox

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace _7.messagebox自动关闭
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        [DllImport("user32.dll")]
        static extern bool EndDialog(IntPtr hDlg, out IntPtr nResult);


        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);
        }
        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;
            }
        }
        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);
            }
        }
        private void button1_Click(object sender, EventArgs e)
        {
            ShowMessageBoxTimeout("text","caption",MessageBoxButtons.OK,1000);
        }
    }
}