强制以编程方式关闭MessageBox

NYK*_*NYK 15 .net c# messagebox winforms

我来给你一个背景.

我们有一个应用程序(中等大小),它在各个地方(数百个)使用MessageBox.Show(....).

这些消息框是工作流程的一部分,用于通知,警告或从用户获取输入.如果没有活动,应用程序应该在一定时间后自动注销.我们要求在注销应用程序时,只是为了清理会话数据,清除视图并隐藏自身,以便在下次启动时,它不必执行启动过程,这在时间上是昂贵的.

一切正常,但是在屏幕上有一些消息框并且用户离开机器而没有响应消息框然后由于没有活动使应用程序退出的情况下.问题是消息框不会消失.

如何在隐藏应用程序时关闭打开的消息框(如果有的话)?

Sim*_*ier 9

这是一段基于UIAutomation(一个很酷但仍未使用的API)的代码,它试图关闭当前进程的所有模态窗口(包括用MessageBox打开的窗口):

    /// <summary>
    /// Attempt to close modal windows if there are any.
    /// </summary>
    public static void CloseModalWindows()
    {
        // get the main window
        AutomationElement root = AutomationElement.FromHandle(Process.GetCurrentProcess().MainWindowHandle);
        if (root == null)
            return;

        // it should implement the Window pattern
        object pattern;
        if (!root.TryGetCurrentPattern(WindowPattern.Pattern, out pattern))
            return;

        WindowPattern window = (WindowPattern)pattern;
        if (window.Current.WindowInteractionState != WindowInteractionState.ReadyForUserInteraction)
        {
            // get sub windows
            foreach (AutomationElement element in root.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window)))
            {
                // hmmm... is it really a window?
                if (element.TryGetCurrentPattern(WindowPattern.Pattern, out pattern))
                {
                    // if it's ready, try to close it
                    WindowPattern childWindow = (WindowPattern)pattern;
                    if (childWindow.Current.WindowInteractionState == WindowInteractionState.ReadyForUserInteraction)
                    {
                        childWindow.Close();
                    }
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

例如,如果你有一个WinForms应用程序,当你按下某个按钮1时弹出一个MessageBox,你仍然可以使用Windows"关闭窗口"菜单关闭应用程序(右键单击任务栏):

    private void button1_Click(object sender, EventArgs e)
    {
        MessageBox.Show("Don't click me. I want to be closed automatically!");
    }

    protected override void WndProc(ref System.Windows.Forms.Message m)
    {
        const int WM_SYSCOMMAND = 0x0112;
        const int SC_CLOSE = 0xF060;

        if (m.Msg == WM_SYSCOMMAND) // this is sent even if a modal MessageBox is shown
        {
            if ((int)m.WParam == SC_CLOSE)
            {
                CloseModalWindows();
                Close();
            }
        }
        base.WndProc(ref m);
    }
Run Code Online (Sandbox Code Playgroud)

您可以在代码中的其他位置使用CloseModalWindows,这只是一个示例.


Bra*_*avo 7

MSDN论坛上的此链接显示了如何通过使用FindWindow和发送WM_CLOSE消息来关闭消息框.虽然问题是.NET/WindowsCE,但它可能会解决您的问题,值得一看

  • 我认为,至少添加一些关于链接页面如何解决问题的附加信息(而不仅仅是发布裸链接)是一种良好的做法.我希望你不介意我添加了一个简短的描述.+1无论如何,这可能是一个有用的资源. (2认同)

V-S*_*SHY 7

请参阅“几秒钟后关闭消息框”中的 DmitryG 帖子

超时后自动关闭消息框

using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

    public class AutoClosingMessageBox
    {
        System.Threading.Timer _timeoutTimer;
        string _caption;
        AutoClosingMessageBox(string text, string caption, int timeout)
        {
            _caption = caption;
            _timeoutTimer = new System.Threading.Timer(OnTimerElapsed,
                null, timeout, System.Threading.Timeout.Infinite);
            MessageBox.Show(text, caption);
        }
        public static void Show(string text, string caption, int timeout)
        {
            new AutoClosingMessageBox(text, caption, timeout);
        }
        void OnTimerElapsed(object state)
        {
            IntPtr mbWnd = FindWindow(null, _caption);
            if (mbWnd != IntPtr.Zero)
                SendMessage(mbWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
            _timeoutTimer.Dispose();
        }
        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);
    }
Run Code Online (Sandbox Code Playgroud)

并通过调用它

AutoClosingMessageBox.Show("Content", "Title", TimeOut);
Run Code Online (Sandbox Code Playgroud)


Mar*_*rco 1

假设您可以编辑调用该 MessageBox.Show()方法的代码,我建议不要使用 MessageBox。相反,只需使用您自己的自定义表单,调用ShowDialog() 它来执行与 MessageBox 类基本相同的操作。然后,您就拥有了表单本身的实例,并且可以调用Close()该实例来关闭它。

这里有一个很好的例子。