Как прикрепить сообщения из формы, показанной с ShowDialog к Application2?

Я пытаюсь использовать код из этой статьи, который позволяет узнать, когда ваше приложение бездействует.

Этот код прекрасно работает, если ваше приложение имеет только одну форму. Ты звонишь Application2.Run(myOnlyForm) на нем и все сообщения маршрутизируются через фильтры в Application2.

Однако если в любой момент вы позвоните mySecondForm.ShowDialog() этот диалог не фильтрует свои сообщения через Application2.

Есть ли способ (без плохих побочных эффектов), чтобы получить сообщения на mySecondForm пройти через фильтры событий `Application2'?

Я пытался:

  1. изменения mySecondForm.ShowDialog в Application2.Run(mySecondForm),
    • Это приводит к тому, что окно не очищается, когда оно выходит из области видимости, и не отображается при необходимости.
  2. изменения mySecondForm.ShowDialog в Application2.ShowDialog(mySecondForm),
    • Это вызывает главное меню на mySecondForm не работать (нажатие не имеет никакого эффекта, только звуковые сигналы).
      • Это похоже на то, что я должен использовать, но мне нужно иметь меню на своих экранах. Похоже, что это общая проблема с OpenNETCF.
      • Пункт меню не сломан. Использование горячей клавиши для меню все еще работает. Простое нажатие на меню не работает.
  3. изменения mySecondForm.ShowDialog в Application2.ShowDialog(mySecondForm, true) (true = очистить диалоговое окно).
    • Это не работает, потому что мне нужно получить доступ к диалоговому окну после его закрытия несколько раз.

В идеале я хотел бы, чтобы способ прикрепить форму к сообщениям способностей Application2.

Но я приветствую любые предложения.


Изменить: Основываясь на предложении для ctacke, это то, что я сделал:

public static DialogResult ShowDialog2(this Form form)
{
    //form.Activated += InsertMenu;
    //Application2.ShowDialog(form);
    form.Show();
    try
    {
        do
        {
            Application2.DoEvents();
        } while (form.Visible);
    }
    catch (ObjectDisposedException)
    {
        // This just means that the form was closed.  Not a big deal.
    }
    return form.DialogResult;

}

В итоге я вызываю ShowDialog2, а не ShowDialog

2 ответа

Решение

Я могу объяснить поведение, хотя, возможно, не предложить прямого решения.

Когда вы вызываете Show в любой форме, события формы обрабатываются насосом сообщений по умолчанию (который настраивается при вызове Run). Когда вы вызываете ShowDialog, целевая форма получает свой собственный отдельный насос сообщений.

Теперь добавленный вами фильтр находится в главном насосе сообщений и просматривает все сообщения там, но вызов ShowDialog обходит это - сообщения, отправляемые в диалоговое окно, никогда не достигнут фильтра.

Теперь мы добавили вызов Application2.ShowDialog как попытку обойти эту проблему, но, если честно, хотя я написал полную реализацию Application.Run/IMEssageFilter, я не делал обходной путь ShowDialog, и я действительно не знаю, как хорошо это было реализовано. Основываясь на вашем отчете, я рискну догадаться, что "не хорошо", хотя решить эту проблему непросто. Корень этой проблемы в том, что SDF не контролирует то, что происходит в BCL, когда вы вызываете Show и ShowDialog - мы просто пытаемся сидеть над ним и обеспечивать наилучшее поведение, которое мы можем. В этом случае это проблематично.

Можете ли вы, случайно, не использовать вызов ShowDialog, а просто использовать Show вместе с чем-то вроде сохранения формы TopMost? Это позволило бы фильтру получать все сообщения для псевдо-диалога. Другой вариант, который я могу придумать сразу, - это базовый класс для диалогов, который будет уведомлять механизм фильтрации, но который становится действительно сложным для контроля.

Извините за вопрос, но почему вы переживаете все это безумное количество неприятностей из-за чего-то такого простого? Глядя на статью, которую вы связали, все, что он делает, это запускает таймер и сбрасывает его каждый WM_KEYUP, WM_MOUSEMOVE или же WM_LBUTTONUP событие.

Вы можете добиться того же, переопределив WndProc или же PreProcessMessage в вашей форме и позволяя ей сделать вещь сброса таймера. Вы даже можете создать базовую форму (*), которая выполняет функцию таймера / сброса и извлекает из нее все ваши формы. И для реального глобального решения, сделайте таймер статическим.

(*) Не отмечайте это как абстрактное, иначе дизайнер форм бросит шипение.

Другие вопросы по тегам