代码之家  ›  专栏  ›  技术社区  ›  sgmoore

对话框有时隐藏在主窗体后面

  •  22
  • sgmoore  · 技术社区  · 15 年前

    我们的一些非技术用户遇到了这样的问题:应用程序中的一个对话框有时会显示在主窗体后面,而应用程序不接受任何输入,直到消息框(他们看不到)被取消。

    应用程序是用C语言编写的,消息框是标准的,例如代码可以像MessageBox.Show(message,caption)一样简单,MessageBox可以由主UI线程(即不是一些后台线程)创建。应用程序不必全屏运行,但我们90%的用户会全屏运行。

    大多数时候((也许>99%)消息框显示正确,我从来没有设法看到它是如何出错的,但我看到了一台机器何时出错。

    我注意到的一点是,如果您有一个显示对话框的应用程序,那么当您查看taskmanager时,您通常只能在应用程序列表中看到一个条目。每当messagebox被隐藏时,您将看到两个条目,一个是主应用程序条目,另一个是此messagebox条目。

    一旦你知道发生了什么事情,解决这个问题就很容易了,但是我们的一些非技术用户对此感到困惑,最终关闭了他们的电脑(而那些正在使用远程桌面的用户则更加困惑,因为这并不能解决问题)。

    我不认为它与操作系统有关,因为我在Vista中看到过这种情况,并且被告知它也发生在windows2003服务器上的终端会话中。

    有什么知道为什么会发生这种情况,更重要的是,是否可以采取任何措施来避免这种情况?

    5 回复  |  直到 15 年前
        1
  •  25
  •   Matt B    15 年前

    一些过载的 MessageBox.Show() IWin32Window 参数作为第一个参数。如果你把你的表格作为第一个论点传递,它应该可以防止这种情况发生。

        2
  •  1
  •   Kharlos Dominguez    15 年前

    是否总是相同的消息框(对于相同的消息?)以相同的形式出现?

    理想情况下,你应该设法找到一些方法来随意重现问题,或者至少是自动重现问题。这将使您的调试更容易,然后您可以确保您未来的更改将修复错误,而不必等待几周的用户反馈。

    如果总是相同的消息,在相同的窗口中,由相同的操作产生,如果从用户的角度来看MessageBox调用很容易触发,如果您的UI相对标准,那么您可以使用 AutoIT 脚本并让它在循环中运行,直到问题发生。

    和/或,您可以创建应用程序的“调试”构建,将其提供给一些用户(最好是那些似乎最常遇到问题的用户),这些用户将编写 StackFrame 每次调用MessageBox之前,都要将对象添加到日志文件或类似的内容中(您可以在MessageBox周围创建一个包装器,以简化此操作)。

    然后,当您的某个用户遇到问题时,您可以查看日志文件并查看它的来源(源代码文件、行、调用堆栈等)。您还可以将其与其他用户的日志进行比较,查看MessageBox是否每次都来自同一位置,或者是否不同。

    可能有更简单的解决方案(特别是如果你的应用程序有很多程序集)涉及到一些.Net调试器,当问题发生时,你可以附加到你的应用程序上,以便查看调用堆栈等,但到目前为止,我只对本机应用程序(使用OllyDbg)做了这些,而不是.Net。其他人也许可以进一步扩展这个想法。。。

        3
  •  1
  •   Stephan Bauer    7 年前

    1. 运行新任务并显示消息框
    2. 当任务仍在运行时,在主UI线程中-在执行DoEvents的循环中等待。像这样的

    昨天有问题。在我的例子中,要进行回购-最小化应用程序,会出现“等待”弹出窗口(在我们的例子中,它发生在空闲时间之后),然后在任务栏中单击主应用程序图标。这会“隐藏”弹出窗口,因此无法将其显示在屏幕上。下面的代码已经过测试并解决了问题。但我还是不明白发生了什么/为什么。

        private static DialogResult ShowMessageBox(
            string message, 
            string caption, 
            MessageBoxButtons buttons, 
            MessageBoxIcon icon)
        {
    
            var showMessageBoxTask = new Task<DialogResult>(() =>
            {
                var form = new Form() {TopMost = true};
    
                var result = MessageBox.Show(
                    form,
                    PrepareMessage(message),
                    caption,
                    buttons,
                    icon);
    
                form.Dispose();
    
                return result;
            });
    
            showMessageBoxTask.Start();
    
            while (!showMessageBoxTask.IsCompleted && !showMessageBoxTask.IsFaulted)
            {
                Application.DoEvents();
            }
    
            return showMessageBoxTask.Result;
        }
    
        4
  •  0
  •   MusiGenesis    15 年前

    你说“信息盒” 可以 MessageBox.Show

        5
  •  0
  •   Shwabster    6 年前

    在父窗体中,在 MessageBox.Show() :

    this.TopMost = false;