超时后 MessageBox 的默认 DialogResult
Default DialogResult for MessageBox after timeout
我需要在 C# Framework 3.5 中创建一个自定义 MessageBox,它显示一些 MesageBoxButton 和 returnDialogResult 值。如果没有用户反应,在一定的超时时间后,MessageBox 应该关闭,returning null.
我按照 DmitryG 的回答 here 做了一些小改动:
static DialogResult? dialogResult_ = null;
public AutoClosingMessageBox(string text, string caption, int timeout, MessageBoxButtons msbb)
{
_caption = caption;
_timeoutTimer = new System.Threading.Timer(OnTimerElapsed,
null, timeout, System.Threading.Timeout.Infinite);
dialogResult_ = MessageBox.Show(text, caption, msbb);
}
public static DialogResult? Show(string text, string caption, int timeout, MessageBoxButtons efb)
{
new AutoClosingMessageBox(text, caption, timeout, efb);
return dialogResult_;
}
void OnTimerElapsed(object state)
{
IntPtr mbWnd = FindWindow("#32770", _caption);
if (mbWnd != IntPtr.Zero)
{
SendMessage(mbWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
_timeoutTimer.Dispose();
}
dialogResult_ = null;
}
const int WM_CLOSE = 0x0010;
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
要创建 MessageBox,我们只需调用 Show 函数
AutoClosingMessageBox.Show("Show me sth", "capt", 3000, MessageBoxButtons.AbortRetryIgnore);
此方法在用户单击 MessageBox 中的按钮时 return dialogResult_ 值,但 WM_Close 消息在超时时间后不再关闭 MessageBox。
这是因为MessageBox还在等待Dialog Result吗?如果是,我该如何避免呢?我想避免必须在新线程中启动消息框并终止线程。
我同意其他评论,您应该制作自己的消息框表单。
就是说,如果您仍然想使用其他方法,您应该能够通过向已识别的对话框发送适当的消息来使其工作;例如"ignore".
的 Alt-I
这是您发布的执行此操作的代码版本:
class AutoClosingMessageBox
{
System.Threading.Timer _timeoutTimer;
string _caption;
static DialogResult? dialogResult_ = null;
private AutoClosingMessageBox(string text, string caption, int timeout, MessageBoxButtons msbb)
{
_caption = caption;
_timeoutTimer = new System.Threading.Timer(OnTimerElapsed,
null, timeout, System.Threading.Timeout.Infinite);
dialogResult_ = MessageBox.Show(text, caption, msbb);
}
public static DialogResult? Show(string text, string caption, int timeout, MessageBoxButtons efb)
{
new AutoClosingMessageBox(text, caption, timeout, efb);
return dialogResult_;
}
void OnTimerElapsed(object state)
{
IntPtr mbWnd = FindWindow("#32770", _caption);
if (mbWnd != IntPtr.Zero)
{
SetForegroundWindow(mbWnd);
SendKeys.SendWait("%I");
_timeoutTimer.Dispose();
}
dialogResult_ = null;
}
[DllImport("user32.dll", SetLastError = true)]
extern static IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
extern static IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
extern static bool SetForegroundWindow(IntPtr hwnd);
}
SendKeys
class 仅适用于当前活动的 window,因此我包含了对 SetForegroundWindow()
的调用以确保密钥到达正确的 [=33] =].
当然,上面硬编码了 Alt-I 的要求。如果您想要一个更通用的解决方案,您可以包含一个字典,将 MessageBoxButtons
值映射到关闭该对话框所需的适当 SendKeys
字符串 and/or 让调用者提供该信息(强制他们提供实际的 SendKeys
字符串或(更好)让他们传递一个枚举值,指示他们要使用哪个按钮关闭对话框,然后让您的实现将其映射到适当的字符串。
我需要在 C# Framework 3.5 中创建一个自定义 MessageBox,它显示一些 MesageBoxButton 和 returnDialogResult 值。如果没有用户反应,在一定的超时时间后,MessageBox 应该关闭,returning null.
我按照 DmitryG 的回答 here 做了一些小改动:
static DialogResult? dialogResult_ = null;
public AutoClosingMessageBox(string text, string caption, int timeout, MessageBoxButtons msbb)
{
_caption = caption;
_timeoutTimer = new System.Threading.Timer(OnTimerElapsed,
null, timeout, System.Threading.Timeout.Infinite);
dialogResult_ = MessageBox.Show(text, caption, msbb);
}
public static DialogResult? Show(string text, string caption, int timeout, MessageBoxButtons efb)
{
new AutoClosingMessageBox(text, caption, timeout, efb);
return dialogResult_;
}
void OnTimerElapsed(object state)
{
IntPtr mbWnd = FindWindow("#32770", _caption);
if (mbWnd != IntPtr.Zero)
{
SendMessage(mbWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
_timeoutTimer.Dispose();
}
dialogResult_ = null;
}
const int WM_CLOSE = 0x0010;
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
要创建 MessageBox,我们只需调用 Show 函数
AutoClosingMessageBox.Show("Show me sth", "capt", 3000, MessageBoxButtons.AbortRetryIgnore);
此方法在用户单击 MessageBox 中的按钮时 return dialogResult_ 值,但 WM_Close 消息在超时时间后不再关闭 MessageBox。
这是因为MessageBox还在等待Dialog Result吗?如果是,我该如何避免呢?我想避免必须在新线程中启动消息框并终止线程。
我同意其他评论,您应该制作自己的消息框表单。
就是说,如果您仍然想使用其他方法,您应该能够通过向已识别的对话框发送适当的消息来使其工作;例如"ignore".
的 Alt-I这是您发布的执行此操作的代码版本:
class AutoClosingMessageBox
{
System.Threading.Timer _timeoutTimer;
string _caption;
static DialogResult? dialogResult_ = null;
private AutoClosingMessageBox(string text, string caption, int timeout, MessageBoxButtons msbb)
{
_caption = caption;
_timeoutTimer = new System.Threading.Timer(OnTimerElapsed,
null, timeout, System.Threading.Timeout.Infinite);
dialogResult_ = MessageBox.Show(text, caption, msbb);
}
public static DialogResult? Show(string text, string caption, int timeout, MessageBoxButtons efb)
{
new AutoClosingMessageBox(text, caption, timeout, efb);
return dialogResult_;
}
void OnTimerElapsed(object state)
{
IntPtr mbWnd = FindWindow("#32770", _caption);
if (mbWnd != IntPtr.Zero)
{
SetForegroundWindow(mbWnd);
SendKeys.SendWait("%I");
_timeoutTimer.Dispose();
}
dialogResult_ = null;
}
[DllImport("user32.dll", SetLastError = true)]
extern static IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
extern static IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
extern static bool SetForegroundWindow(IntPtr hwnd);
}
SendKeys
class 仅适用于当前活动的 window,因此我包含了对 SetForegroundWindow()
的调用以确保密钥到达正确的 [=33] =].
当然,上面硬编码了 Alt-I 的要求。如果您想要一个更通用的解决方案,您可以包含一个字典,将 MessageBoxButtons
值映射到关闭该对话框所需的适当 SendKeys
字符串 and/or 让调用者提供该信息(强制他们提供实际的 SendKeys
字符串或(更好)让他们传递一个枚举值,指示他们要使用哪个按钮关闭对话框,然后让您的实现将其映射到适当的字符串。