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/
=======================================================================================
 
經過以上幾步,咱們如今能夠正常的實現了咱們文章開頭提到的功能了。
相關文章
相關標籤/搜索