Диалог MessageBox иногда скрывается за основной формой - PullRequest
23 голосов
/ 12 августа 2010

У некоторых наших нетехнических пользователей возникают проблемы, когда диалоговое окно MessageBox в нашем приложении иногда может отображаться за основной формой, и приложение не принимает никаких входных данных до тех пор, пока окно сообщений (которое они не могут видеть) закрыто.

Приложение написано на C #, и окна сообщений являются стандартными, например, код может быть таким же простым, как MessageBox.Show (сообщение, заголовок), а окна сообщений могут создаваться основным потоком пользовательского интерфейса (т.е. не каким-либо фоновым потоком). Приложение не нужно запускать в полноэкранном режиме, но 90% наших пользователей запускают его в полноэкранном режиме.

Большую часть времени ((возможно,> 99%) ящики сообщений отображаются правильно, и мне никогда не удавалось увидеть, как это работает, но я видел машину, когда она работала неправильно.

Одна вещь, которую я заметил, это то, что если у вас есть приложение, которое отображает диалоговое окно, то когда вы смотрите на менеджер задач, вы обычно видите только одну запись в списке приложений. Всякий раз, когда окно сообщения скрыто, вы увидите две записи: одну для основного приложения и другую запись для этого окна сообщения.

Достаточно легко решить проблему, если вы знаете, что произошло, но некоторые наши нетехнические пользователи смущены этим и в конечном итоге отключают свои компьютеры. (А те, кто использует удаленный рабочий стол, еще больше запутываются, когда это не решает проблему).

Я не думаю, что это связано с операционной системой, поскольку я видел, что это происходит в Vista, и мне сказали, что это также происходит в терминальной сессии на сервере Windows 2003.

Кто-нибудь знает, почему это происходит, и что более важно, если что-то можно сделать, чтобы избежать этого?

Ответы [ 5 ]

21 голосов
/ 12 августа 2010

Некоторые перегрузки метода MessageBox.Show() принимают параметр IWin32Window в качестве первого аргумента.Если вы передадите свою форму в качестве первого аргумента, это должно предотвратить это.

1 голос
/ 16 декабря 2015

Подтвердите проблему. Что мы делаем, чтобы исправить это следующим образом:

  1. Запустить новую задачу и отобразить окно сообщения
  2. В главном потоке пользовательского интерфейса, пока задача еще выполняется - подождите в цикле, который выполняет DoEvents. Как то так

ОБНОВЛЕНО 2015-12-17. Воспроизводится проблема вчера. Чтобы сделать репо в моем случае - сверните приложение, всплывающее окно «ожидания» (в нашем случае это происходит после некоторого времени простоя), затем в панели задач нажмите на значок основного приложения. Это «скрывает» всплывающее окно, поэтому вывести его на экран невозможно. Код ниже был проверен и решает проблему. Но я до сих пор не понимаю, что / почему это происходит.

    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;
    }
1 голос
/ 12 августа 2010

Всегда ли одно и то же окно сообщения (для одного и того же сообщения?) Приходит одной и той же формы?

В идеале вы должны попытаться найти способ воспроизвести проблему по желанию или, по крайней мере, автоматически.Это облегчит вашу отладку, и вы сможете быть уверены, что ваши будущие изменения исправят ошибку, вместо того, чтобы ждать отзывов пользователей в течение нескольких недель.

Если оно всегда одинаковосообщение и в том же окне, в результате того же действия, и если вызов MessageBox достаточно легко вызвать с точки зрения пользователя, и если ваш пользовательский интерфейс является относительно стандартным, вы можете автоматизировать пользовательский интерфейс с помощью AutoIT сценарий и запуск его в цикле, пока проблема не возникнет.

И / или вы можете создать «отладочную» сборку ваших приложений, которую вы могли бы предоставить некоторым пользователям (предпочтительно тем, которыекоторые, как представляется, чаще всего сталкиваются с проблемой), которые записывают содержимое объекта StackFrame в файл журнала или что-то подобное каждый раз перед вызовом MessageBox (вы можете создать оболочку вокруг MessageBox, чтобы сделать этопроще).

Затем, когда проблема возникнет у одного из ваших пользователей, вы можете посмотреть журнали посмотрите, откуда он (файл исходного кода, строка, стек вызовов и т. д.).Вы также можете сравнить это с журналами других пользователей и посмотреть, приходит ли каждый раз MessageBox из одного и того же местоположения или меняется.Это покажет вам, откуда вызывается проблемный MessageBox и где.

Могут быть более простые решения (особенно если в вашем приложении много сборок), включающие отладчик .Net, который вы подключаете к своему приложению, когдапроблема возникает для того, чтобы увидеть стек вызовов и т. д., но пока я делал это только с нативными приложениями (использующими OllyDbg), а не с .Net.Другие могут расширить эту идею ...

0 голосов
/ 10 июля 2018

В родительской форме добавьте это перед MessageBox.Show ():

this.TopMost = false;

0 голосов
/ 12 августа 2010

Вы говорите "ящики сообщений могут быть созданы основным потоком пользовательского интерфейса", что, как я предполагаю, означает, что они не всегда создаются основным потоком пользовательского интерфейса. Ваша проблема звучит так, как будто MessageBox.Show иногда вызывается из другого потока.

...