C#自动弹出窗口并定时自动关闭

最近作个小项目,用到一个小功能:后台线程定时查询数据库,不符合条件的记录弹出消息提醒(在窗口最前面),而且过几秒钟再自动关闭弹出的窗口。html

因此从网上找来资料,以下:数据库

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

Author: eaglet
      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 来关闭对话框,这里我使用 EndDialogpost

        [DllImport("user32.dll")]
        static extern bool EndDialog(IntPtr hDlg, out IntPtr nResult);


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

url

复制代码
        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 的定义以下:
   spa

复制代码
        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函数了,直接看代码吧.net

复制代码
复制代码
        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);
            }
        }
复制代码
复制代码
 
出处:http://www.cnblogs.com/XGLSummer/archive/2012/09/06/2673334.html
=============================================================================================
发现上面的代码是能够,但弹出的窗口没有在最前面,因此还须要继续找资料。

在屏幕的最前面弹一个消息框

有人要说了,弹一个ShowDialog不就完了吗?!或者MessageBox.Show("saaaaa");就能够达到目的。
但你要看到下面的状况,你就不这样说了。
我在C#中建立了一个Excel,每当我编辑一个值的时候,都会用C#代码判断这些值是不是有效的,当无效进就提醒他们。我用的就是MessageBox.Show("aaaaaaa");
但它不必定弹在最前面,由于它是C#的代码,故当Excel在最前面时,那个消息框是不能显示在最头面的。线程

用如下方法能够解决此问题:
MessageBox.Show("要弹的信息。", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information,MessageBoxDefaultButton.Button1, essageBoxOptions.DefaultDesktopOnly);code

呵呵,虽然仍是那个MessageBox.Show,但不少人都不知道呀。你们能够试试。orm

 
出处:http://www.cnblogs.com/pnljs/archive/2012/09/19/2694182.html
========================================================================================================
使用上面的代码,能够实现弹出窗口在最上面,可是结合第一段的代码,没法正常关闭,直接报错了。说明调用的static extern bool EndDialog(IntPtr hDlg, out IntPtr nResult);方法不能正常关闭窗口,那么我们再从新找个能够关闭窗口的API函数把。在网上找到以下代码:
    public const int WM_CLOSE = 0x10;
 
    [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SendMessageA")]
    public static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
private void button1_Click(object sender, System.EventArgs e) { IntPtr hwnd_win; hwnd_win = FindWindow(null, "要找的窗体名"); SendMessage(hwnd_win, WM_CLOSE, 0, 0); }

查找窗口函数:

        //查找窗体
        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        private static extern int FindWindow(string lpClassName, string lpWindowName);
        static void Main()
        {
             //@Form1根据窗体的Text文本值得到窗体
                int WINDOW_HANDLER = FindWindow(null, @"Form1");
         }

 

出处:http://bbs.csdn.net/topics/340065537/
=======================================================================================
 
经过以上几步,咱们如今能够正常的实现了咱们文章开头提到的功能了。