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

Обычное поведение WinForms с модальными диалогами кажется проблематичным в приложениях с несколькими окнами верхнего уровня. Мне любопытно, разработал ли кто-нибудь более эффективный подход. Позволь мне объяснить…

Ситуация:

Когда вы выполняете dialog.ShowDialog (parent), любая попытка пользователя щелкнуть или активировать это родительское окно приводит к активации модального диалогового окна и его миганию, так что в нем четко говорится: «Сначала вы должны разобраться с этим». Большой.

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

Если вместо этого пользователь использует панель задач, чтобы выбрать одно из других окон верхнего уровня, теперь оно БУДЕТ перемещать его на передний план! Он по-прежнему не активируется, но теперь он, вероятно, полностью закрывает модальное диалоговое окно. Любая попытка взаимодействия с этим окном верхнего уровня терпит неудачу. Вроде заперли. Итак, многие пользователи решили, что наше приложение заблокировано ... они в конечном итоге убивают наше приложение в диспетчере задач и перезапускают! И сообщает нам об этом как об ошибке. Когда на самом деле они только что открыли модальный диалог и должны были вернуться к нему.

Вопросы:

Есть ли способ щелкнуть или активировать любое окно в нашем приложении, чтобы модальное диалоговое окно отображалось на переднем плане и мигало (как теперь будет его родительское окно)?

Могу ли я каким-то образом связать группу окон?

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

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


person Brian Kennedy    schedule 11.03.2016    source источник
comment
Я думаю, что лучше всего было бы просто минимизировать количество отображаемых отдельных окон и модальных диалогов, чтобы это не стало проблемой.   -  person poke    schedule 12.03.2016


Ответы (2)


Вы можете обрабатывать _ 1_ ваших форм, а затем с помощью _ 2_ проверьте, открыта ли модальная форма, а модальная форма не является текущей, затем активируйте модальную форма:

private void Form1_Activated(object sender, EventArgs e)
{
    var f = Application.OpenForms.Cast<Form>().Where(x => x.Modal).LastOrDefault();
    if (f != null && f != this)
    {
        if (f.WindowState == FormWindowState.Minimized)
            f.WindowState = FormWindowState.Normal;

        f.Activate(); 
    }
}

Вы можете поместить логику в свою базовую форму или при открытии формы прикрепить такой обработчик к ее событию Activated.

person Reza Aghaei    schedule 12.03.2016
comment
Спасибо за это! Это привело меня к только что опубликованному решению, которое, похоже, работает нормально. (С вашим кодом как есть, некоторые формы, которые были активированы модальным диалогом, но сами НЕ являются модальными, будут отображаться сломанными ... перестанут отвечать.) Но ваш ответ дал мне ключевые ингредиенты, которых мне не хватало. Тогда спасибо!! - person Brian Kennedy; 12.03.2016

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

    /// <summary>
    /// Looks for the last Modal Form in OpenForms that is AFTER justActivatedForm;
    /// if it finds it, then it Activates it and returns it. Otherwise, it returns null.
    /// </summary>
    /// <param name="justActivatedForm">The Form that was just Activated, prompting this check for Modal.</param>
    /// <returns>Returns the last Modal Form AFTER justActivatedForm; or null if no such exists.</returns>
    public static Form ActivateLastModalForm(Form justActivatedForm)
    {
        // Is there a Modal Form after justActivatedForm?  If so, get the last Modal Form.
        Form lastModal = null;
        bool foundJustActivatedForm = false;
        foreach (Form form in Application.OpenForms)
        {
            if (foundJustActivatedForm)
            {
                if (form.Modal)
                    lastModal = form;
            }
            else if (form == justActivatedForm)
            {
                foundJustActivatedForm = true;
            }
        }

        // If last Modal Form is found after justActivatedForm, Activate it
        if (lastModal != null)
        {
            LOG.Focus("Found Modal Form. Activating it...");
            if (lastModal.WindowState == FormWindowState.Minimized)
                lastModal.WindowState = FormWindowState.Normal;
            lastModal.Activate();
        }

        return lastModal;
    }

Сообщите нам, если вы заметите какие-либо недостатки в этом решении!

person Brian Kennedy    schedule 12.03.2016