請高手幫忙,比如我做出一個響應,彈出一個MessageBox。
怎么做讓它3秒后自動關閉,點擊上面的確定也可以手動關閉、、、、、、、、、、、、、、、、、、、、?
謝謝
看網上有說寫一個MessageBox繼承System.Windows.Form,然后添加一個Timer。
能不能有點實例代碼,學習一下。代碼最好簡潔點,要不然看的太亂了。
---------------
寫好了,以下是截圖和部分源碼,完整的源碼在附件中:
1.指定要彈出的消息以及定時的時間(單位秒)
2.彈出后,對話框上的確定按鈕上會動態倒計時,當時間為0時自動關閉,也可以通過點擊確定按鈕關閉
核心代碼:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
public
partial
class
TimingMessageBox : Form
{
// 自動關閉的時間限制,如3為3秒后自動關閉
private
int
second;
// 計數器,用以判斷當前窗口彈出后持續的時間
private
int
counter;
// 構造函數
public
TimingMessageBox(
string
message,
int
second)
{
InitializeComponent();
// 顯示消息
this
.labelMessage.Text = message;
// 獲得時間限制
this
.second = second;
// 初始化計數器
this
.counter = 0;
// 初始化按鈕的文本
this
.buttonOK.Text =
string
.Format(
"確定({0})"
,
this
.second -
this
.counter);
// 激活並啟動timer,設置timer的觸發間隔為1000毫秒(1秒)
this
.timer1.Enabled =
true
;
this
.timer1.Interval = 1000;
this
.timer1.Start();
}
private
void
timer1_Tick(
object
sender, EventArgs e)
{
// 如果沒有到達指定的時間限制
if
(
this
.counter <=
this
.second)
{
// 刷新按鈕的文本
this
.buttonOK.Text =
string
.Format(
"確定({0})"
,
this
.second -
this
.counter);
this
.Refresh();
// 計數器自增
this
.counter++;
}
// 如果到達時間限制
else
{
// 關閉timer
this
.timer1.Enabled =
false
;
this
.timer1.Stop();
// 關閉對話框
this
.Close();
}
}
private
void
buttonOK_Click(
object
sender, EventArgs e)
{
// 單擊確定按鈕,關閉對話框
this
.Close();
}
}
|
然后在主窗體中調用:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public
partial
class
Form1 : Form
{
public
Form1()
{
InitializeComponent();
}
private
void
buttonShowMessageBox_Click(
object
sender, EventArgs e)
{
string
message =
this
.textBoxMessage.Text.Trim();
int
second = Convert.ToInt32(
this
.textBoxSecond.Text.Trim());
TimingMessageBox messageBox=
new
TimingMessageBox(message,second);
messageBox.ShowDialog();
}
}
|
TimingMessageBox.zip大小:52.33K|所需財富值:5
出處:https://zhidao.baidu.com/question/575559071.html
=================================================================================
本文以一個簡單的小例子,介紹如何讓MessageBox彈出的對話框,在幾秒鍾內自動關閉。
特別是一些第三方插件(如:dll)彈出的對話框,最為適用。本文僅供學習分享使用,如有不足之處,還請指正。
概述
在程序中MessageBox彈出的對話框,用於向用戶展示消息,這是一個模式窗口,可阻止應用程序中的其他操作,直到用戶將其關閉。但是有時候在自動化程序中,如果彈出對話框,程序將會中斷,等待人工的干預,這是一個非常不好的交互體驗,如果程序能夠自動幫我們點擊其中一個按鈕,讓對話框消失,該有多好。
原理
通過對話框的標題查找對話框,獲取對話框的句柄,然后對話框發送指令。
涉及知識點
- MessageBox 顯示消息窗口(也稱為對話框)向用戶展示消息。這是一個模式窗口,可阻止應用程序中的其他操作,直到用戶將其關閉。System.Windows.Forms.MessageBox可包含通知並指示用戶的文本、按鈕和符號。
- Thread 創建和控制線程,設置其優先級並獲取其狀態。本例子主要創建一個線程,查找彈出的窗口。
- WIN32 API 也就是Microsoft Windows 32位平台的應用程序編程接口。每一個服務,就是一個函數,用於和Windows進行交互。
- MessageBoxButtons 是一個Enum,表示對話框上顯示哪些按鈕。
- PostMessage 是Windows API(應用程序接口)中的一個常用函數,用於將一條消息放入到消息隊列中。消息隊列里的消息通過調用GetMessage和PeekMessage取得。
示例截圖如下:

關鍵代碼
核心代碼如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Drawing; 4 using System.Linq; 5 using System.Runtime.InteropServices; 6 using System.Text; 7 using System.Threading; 8 using System.Threading.Tasks; 9 10 namespace DemoMessageBox 11 { 12 /// <summary> 13 /// 作者:Alan.hsiang 14 /// 日期:2018-04-18 15 /// 描述:通過WinAPI進行查找窗口,並對窗口進行操作 16 /// </summary> 17 public class MessageBoxHelper 18 { 19 /// <summary> 20 /// 查找窗口 21 /// </summary> 22 /// <param name="hwnd">窗口句柄</param> 23 /// <param name="title">窗口標題</param> 24 /// <returns></returns> 25 [DllImport("user32.dll", CharSet = CharSet.Auto)] 26 static extern IntPtr FindWindow(IntPtr hwnd, string title); 27 28 /// <summary> 29 /// 移動窗口 30 /// </summary> 31 /// <param name="hwnd">窗口句柄</param> 32 /// <param name="x">起始位置X</param> 33 /// <param name="y">起始位置Y</param> 34 /// <param name="nWidth">窗口寬度</param> 35 /// <param name="nHeight">窗口高度</param> 36 /// <param name="rePaint">是否重繪</param> 37 [DllImport("user32.dll", CharSet = CharSet.Auto)] 38 static extern void MoveWindow(IntPtr hwnd, int x, int y, int nWidth, int nHeight, bool rePaint); 39 40 /// <summary> 41 /// 獲取窗口矩形 42 /// </summary> 43 /// <param name="hwnd">窗口句柄</param> 44 /// <param name="rect"></param> 45 /// <returns></returns> 46 [DllImport("user32.dll", CharSet = CharSet.Auto)] 47 static extern bool GetWindowRect(IntPtr hwnd, out Rectangle rect); 48 49 /// <summary> 50 /// 向窗口發送信息 51 /// </summary> 52 /// <param name="hwnd">窗口句柄</param> 53 /// <param name="msg">信息</param> 54 /// <param name="wParam">高字節</param> 55 /// <param name="lParam">低字節</param> 56 /// <returns></returns> 57 [DllImport("user32.dll", CharSet = CharSet.Auto)] 58 static extern int PostMessage(IntPtr hwnd, int msg, uint wParam, uint lParam); 59 60 public const int WM_CLOSE = 0x10; //關閉命令 61 62 public const int WM_KEYDOWN = 0x0100;//按下鍵 63 64 public const int WM_KEYUP = 0x0101;//按鍵起來 65 66 public const int VK_RETURN = 0x0D;//回車鍵 67 68 public static bool IsWorking = false; 69 70 /// <summary> 71 /// 對話框標題 72 /// </summary> 73 public static string[] titles = new string[4] { "請選擇", "提示", "錯誤", "警告" }; 74 75 /// <summary> 76 /// 查找和移動窗口 77 /// </summary> 78 /// <param name="title">窗口標題</param> 79 /// <param name="x">起始位置X</param> 80 /// <param name="y">起始位置Y</param> 81 public static void FindAndMoveWindow(string title, int x, int y) 82 { 83 Thread t = new Thread(() => 84 { 85 IntPtr msgBox = IntPtr.Zero; 86 while ((msgBox = FindWindow(IntPtr.Zero, title)) == IntPtr.Zero) ; 87 Rectangle r = new Rectangle(); 88 GetWindowRect(msgBox, out r); 89 MoveWindow(msgBox, x, y, r.Width - r.X, r.Height - r.Y, true); 90 }); 91 t.Start(); 92 } 93 94 /// <summary> 95 /// 查找和關閉窗口 96 /// </summary> 97 /// <param name="title">標題</param> 98 private static void FindAndKillWindow(string title) 99 { 100 IntPtr ptr = FindWindow(IntPtr.Zero, title); 101 if (ptr != IntPtr.Zero) 102 { 103 int ret = PostMessage(ptr, WM_CLOSE, 0, 0); 104 Thread.Sleep(1000); 105 ptr = FindWindow(IntPtr.Zero, title); 106 if (ptr != IntPtr.Zero) 107 { 108 PostMessage(ptr, WM_KEYDOWN, VK_RETURN, 0); 109 PostMessage(ptr, WM_KEYUP, VK_RETURN, 0); 110 } 111 } 112 } 113 114 /// <summary> 115 /// 查找和關閉窗口 116 /// </summary> 117 public static void FindAndKillWindow() 118 { 119 Thread t = new Thread(() => 120 { 121 while (IsWorking) 122 { 123 //按標題查找 124 foreach (string title in titles) 125 { 126 FindAndKillWindow(title); 127 } 128 Thread.Sleep(3000); 129 } 130 }); 131 t.Start(); 132 } 133 } 134 }
備注
關於源碼,請點擊鏈接自行下載。
關於PostMessage和SendMessage的區分,請點鏈接
出處:https://www.cnblogs.com/hsiang/p/8878093.html
====================================================
優化
根據上面的提醒,自己重新優化下,盡量讓項目做較少的改動嘛!~
調用Win32的沒有變化,只是把關閉窗口的方法精簡了以些:
public class Win32Helper { /*先調用GetForegroundWindow然后調用GetWindowFromHwnd*/ //GetForegroundWindow API [DllImport("user32.dll")] static extern IntPtr GetForegroundWindow(); //從Handle中獲取Window對象 private static Form GetWindowFromHwnd(IntPtr hwnd) { return Form.FromHandle(hwnd) as Form; } /// <summary> /// 獲取當前頂級窗體,若獲取失敗則返回主窗體 /// </summary> public static Form GetTopWindow() { var hwnd = GetForegroundWindow(); if (hwnd == IntPtr.Zero) { Process p = Process.GetCurrentProcess(); hwnd = p.MainWindowHandle; } return GetWindowFromHwnd(hwnd); } /// <summary> /// 查找窗口 /// </summary> /// <param name="hwnd">窗口句柄</param> /// <param name="title">窗口標題</param> /// <returns></returns> [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr FindWindow(IntPtr hwnd, string title); public const int WM_CLOSE = 0x10; //關閉命令 public const int WM_KEYDOWN = 0x0100;//按下鍵 public const int WM_KEYUP = 0x0101;//按鍵起來 public const int VK_RETURN = 0x0D;//回車鍵 /// <summary> /// 向窗口發送信息 /// </summary> /// <param name="hwnd">窗口句柄</param> /// <param name="msg">信息</param> /// <param name="wParam">高字節</param> /// <param name="lParam">低字節</param> /// <returns></returns> [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int PostMessage(IntPtr hwnd, int msg, uint wParam, uint lParam); } //彈出消息框 public class MsgBoxHelper { private static log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public static DialogResult ShowDialog(string msg, IWin32Window win = null, TimeSpan? outTime = null, MessageBoxButtons messageBoxButtons = MessageBoxButtons.OK, MessageBoxIcon messageBoxIcon = MessageBoxIcon.Information) { DialogResult dr = DialogResult.None; var fm = Win32Helper.GetTopWindow(); if (fm.InvokeRequired) { fm.Invoke(new EventHandler(delegate { ShowDialog(msg, win, outTime, messageBoxButtons, messageBoxIcon); })); } else { string strTitle = "消息"; win = win == null ? fm : win; outTime = outTime == null ? TimeSpan.FromSeconds(5) : outTime; new Thread(() => { _log.Info($"ShowDialog : 已啟動超時退出。超時時間:{outTime.Value.TotalSeconds}"); Thread.Sleep((int)outTime.Value.TotalMilliseconds); FindAndKillWindow(strTitle); }).Start(); _log.Info("ShowDialog : Title = " + strTitle + Environment.NewLine + "Msg = " + msg); dr = MessageBox.Show(win, msg, strTitle, messageBoxButtons, messageBoxIcon, MessageBoxDefaultButton.Button1); } return dr; } /// <summary> /// 查找和關閉窗口 /// </summary> /// <param name="title">標題</param> private static void FindAndKillWindow(string title) { IntPtr ptr = Win32Helper.FindWindow(IntPtr.Zero, title); _log.Info($"FindAndKillWindow : 查找窗口標題 = {title},窗口句柄 = " + ptr); if (ptr != IntPtr.Zero) { int ret = Win32Helper.PostMessage(ptr, Win32Helper.WM_CLOSE, 0, 0); Thread.Sleep(1000); ptr = Win32Helper.FindWindow(IntPtr.Zero, title); _log.Info($"FindAndKillWindow : 發送關閉窗口命令結果 = {ret},再次查找[{title}]窗口結果 = " + ptr); if (ptr != IntPtr.Zero) { Win32Helper.PostMessage(ptr, Win32Helper.WM_KEYDOWN, Win32Helper.VK_RETURN, 0); Win32Helper.PostMessage(ptr, Win32Helper.WM_KEYUP, Win32Helper.VK_RETURN, 0); } } } }



