public class MessageBoxAutoClose
{
    [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);

    string _caption;
    int _timeout;
    Timer _timer = new Timer();
    IntPtr _dlg;

    private void ShowMessageBoxTimeout(string text, string caption, int timeout)
    {
        _caption = caption;
        _timeout = timeout;

        _timer.Interval = 1000;
        _timer.Enabled = true;
        _timer.Tick += Timer_Tick;
        
        ThreadPool.QueueUserWorkItem(new WaitCallback(CloseMessageBox), new CloseState(caption, timeout * 1000));

        //这里线程挂起20ms,也可以循环每次挂起10ms
        new Task(() =>
        {
            while (_dlg == IntPtr.Zero)
            {
                Thread.Sleep(10);
                _dlg = FindWindow(null, _caption);
            }
            ChangeMessageBoxButtonText(_dlg, _timeout);
        }).Start();
        //new Task(() => { Thread.Sleep(20); ChangeMessageBoxButtonText(_dlg, _timeout); }).Start();
        DialogResult dialogResult = MessageBox.Show(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Information);
        if(dialogResult==DialogResult.OK || dialogResult == DialogResult.Cancel)
        {
            if (_timer.Enabled)
            {
                _timer.Enabled = false;
                _timer.Dispose();
            } 
        }
    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        ChangeMessageBoxButtonText(_dlg, --_timeout);
    }

    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);
        if (_timer.Enabled) //如果定时器还在开,说明窗体没有被手动关闭
        {
            IntPtr dlg = FindWindow(null, closeState.Caption);
            if (dlg != IntPtr.Zero)
            {
                IntPtr result;
                EndDialog(dlg, out result);
            }
            _timer.Enabled = false;
            _timer.Dispose();
        }
    }

    private void ChangeMessageBoxButtonText(IntPtr dlg, int time)
    {
        //IntPtr dlg = FindWindow(null, _caption);
        IntPtr h = NativeWin32API.GetWindow(dlg, NativeWin32API.GW_CHILD);
        if (h != IntPtr.Zero)
        {
            if (NativeWin32API.GetWindowClassName(h).Equals("Button"))
            {
                NativeWin32API.SetWindowText(h, string.Format("关闭({0})", time));
            }
        }
    }

    public static void Show(string text, string caption, int timeout)
    {
        MessageBoxAutoClose messageBoxAutoClose = new MessageBoxAutoClose();
        messageBoxAutoClose.ShowMessageBoxTimeout(text, caption, timeout);
    }
}


public class NativeWin32API
{
    public const int GW_CHILD = 5;

    public const int GW_HWNDNEXT = 2;

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int Width, int Height, int flags);
    [DllImport("user32.dll")]
    public static extern IntPtr GetWindow(IntPtr hWnd, int wCmd);
    [DllImport("user32.dll")]
    public static extern bool SetWindowText(IntPtr hWnd, string lpString);
    [DllImport("user32.dll")]
    public static extern int GetClassNameW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount);

    public static string GetWindowClassName(IntPtr handle)
    {
        StringBuilder sb = new StringBuilder(256);

        GetClassNameW(handle, sb, sb.Capacity); //得到窗口类名并保存在strClass中
        return sb.ToString();
    }
}

 

效果图:

MessageBox自动关闭,并改变MessageBox按钮文字_类名