Как прикрепить сообщения из формы, показанной с ShowDialog к Application2? - PullRequest
4 голосов
/ 24 июня 2010

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

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

Однако, если в любой момент вы вызываете mySecondForm.ShowDialog(), это диалоговое окно не получает свои сообщения, отфильтрованные через приложение 2..* Есть ли способ (без плохих побочных эффектов) заставить сообщения на 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 ]

2 голосов
/ 24 июня 2010

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

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

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

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

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

0 голосов
/ 24 июня 2010

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

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

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

...