请高手帮忙,比如我做出一个响应,弹出一个MessageBox。

怎么做让它3秒后自动关闭,点击上面的确定也可以手动关闭、、、、、、、、、、、、、、、、、、、、?

谢谢


看网上有说写一个MessageBox继承System.Windows.Form,然后添加一个Timer。

能不能有点实例代码,学习一下。代码最好简洁点,要不然看的太乱了。

---------------

写好了,以下是截图和部分源码,完整的源码在附件中:

1.指定要弹出的消息以及定时的时间(单位秒)

C# MessageBox.Show()超时后 自动关闭_消息队列

2.弹出后,对话框上的确定按钮上会动态倒计时,当时间为0时自动关闭,也可以通过点击确定按钮关闭

C# MessageBox.Show()超时后 自动关闭_ico_02

核心代码:

 

 


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


 

=================================================================================



本文以一个简单的小例子,介绍如何让MessageBox弹出的对话框,在几秒钟内自动关闭。

特别是一些第三方插件(如:dll)弹出的对话框,最为适用。本文仅供学习分享使用,如有不足之处,还请指正。

概述

在程序中MessageBox弹出的对话框,用于向用户展示消息,这是一个模式窗口,可阻止应用程序中的其他操作,直到用户将其关闭。但是有时候在自动化程序中,如果弹出对话框,程序将会中断,等待人工的干预,这是一个非常不好的交互体验,如果程序能够自动帮我们点击其中一个按钮,让对话框消失,该有多好。

原理

通过对话框的标题查找对话框,获取对话框的句柄,然后对话框发送指令。

涉及知识点

  • MessageBox   显示消息窗口(也称为对话框)向用户展示消息。这是一个模式窗口,可阻止应用程序中的其他操作,直到用户将其关闭。System.Windows.Forms.MessageBox可包含通知并指示用户的文本、按钮和符号。
  • Thread 创建和控制线程,设置其优先级并获取其状态。本例子主要创建一个线程,查找弹出的窗口。
  • WIN32 API 也就是Microsoft Windows 32位平台的应用程序编程接口。每一个服务,就是一个函数,用于和Windows进行交互。
  • MessageBoxButtons 是一个Enum,表示对话框上显示哪些按钮。
  • PostMessage 是Windows API(应用程序接口)中的一个常用函数,用于将一条消息放入到消息队列中。消息队列里的消息通过调用GetMessage和PeekMessage取得。

示例截图如下:

C# MessageBox.Show()超时后 自动关闭_ico_03

关键代码

核心代码如下:


C# MessageBox.Show()超时后 自动关闭_窗口句柄_04C# MessageBox.Show()超时后 自动关闭_消息队列_05


C# MessageBox.Show()超时后 自动关闭_关闭窗口_06

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 }


C# MessageBox.Show()超时后 自动关闭_ico_07

View Code

 

备注

关于源码,请点击​​链接​​自行下载。

关于PostMessage和SendMessage的区分,请点​​链接​

 


 

====================================================

优化

根据上面的提醒,自己重新优化下,尽量让项目做较少的改动嘛!~

调用Win32的没有变化,只是把关闭窗口的方法精简了以些:


C# MessageBox.Show()超时后 自动关闭_窗口句柄_04C# MessageBox.Show()超时后 自动关闭_消息队列_05


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);
}
}
}

}

View Code

 

本文以一个简单的小例子,介绍如何让MessageBox弹出的对话框,在几秒钟内自动关闭。

特别是一些第三方插件(如:dll)弹出的对话框,最为适用。本文仅供学习分享使用,如有不足之处,还请指正。

概述

在程序中MessageBox弹出的对话框,用于向用户展示消息,这是一个模式窗口,可阻止应用程序中的其他操作,直到用户将其关闭。但是有时候在自动化程序中,如果弹出对话框,程序将会中断,等待人工的干预,这是一个非常不好的交互体验,如果程序能够自动帮我们点击其中一个按钮,让对话框消失,该有多好。

原理

通过对话框的标题查找对话框,获取对话框的句柄,然后对话框发送指令。

涉及知识点

  • MessageBox   显示消息窗口(也称为对话框)向用户展示消息。这是一个模式窗口,可阻止应用程序中的其他操作,直到用户将其关闭。System.Windows.Forms.MessageBox可包含通知并指示用户的文本、按钮和符号。
  • Thread 创建和控制线程,设置其优先级并获取其状态。本例子主要创建一个线程,查找弹出的窗口。
  • WIN32 API 也就是Microsoft Windows 32位平台的应用程序编程接口。每一个服务,就是一个函数,用于和Windows进行交互。
  • MessageBoxButtons 是一个Enum,表示对话框上显示哪些按钮。
  • PostMessage 是Windows API(应用程序接口)中的一个常用函数,用于将一条消息放入到消息队列中。消息队列里的消息通过调用GetMessage和PeekMessage取得。

示例截图如下:

C# MessageBox.Show()超时后 自动关闭_ico_03

关键代码

核心代码如下:


C# MessageBox.Show()超时后 自动关闭_窗口句柄_04C# MessageBox.Show()超时后 自动关闭_消息队列_05


C# MessageBox.Show()超时后 自动关闭_消息队列_13

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 }


C# MessageBox.Show()超时后 自动关闭_窗口标题_14

View Code

 

备注

关于源码,请点击​​链接​​自行下载。

关于PostMessage和SendMessage的区分,请点​​链接​