Должен ли Form.ShowDialog(IWin32Window) работать с любым дескриптором окна?

StackOverflow https://stackoverflow.com/questions/581855

Вопрос

Когда используешь System.Windows.Forms.ShowDialog(IWin32Window), смогу ли я пройти IWin32Window представляет любой дескриптор окна и является ли он модальным по отношению к этому окну?

В рамках расширения Internet Explorer 7 я пытаюсь открыть модальное окно относительно вкладки Internet Explorer.Это не выбранная в данный момент вкладка, но я могу получить ее управление ОК.Однако, когда я передаю это ShowDialog, моя форма отображается, но она не является модальной по отношению к чему-либо:Я по-прежнему могу что-то делать в Internet Explorer, в том числе на вкладке, которая должна принадлежать владельцу.Моя форма отображается над окнами Internet Explorer и остается сверху, поэтому она не просто открыта как обычная форма, но и не является модальной.

С использованием Шпион++, я могу найти свою форму, и ее дескриптор владельца установлен правильно.

Означает ли это, что что-то пошло не так или я что-то делаю не так?Как сделать форму правильно модальной?

К вашему сведению, я использую этот класс-оболочку для создания IWin32Window из hwnd (Спасибо Райан!):

/// <summary>
/// Wrapper class so that we can return an IWin32Window given a hwnd
/// </summary>
public class WindowWrapper : System.Windows.Forms.IWin32Window
{
    public WindowWrapper(IntPtr handle)
    {
        _hwnd = handle;
    }

    public IntPtr Handle
    {
        get { return _hwnd; }
    }

    private IntPtr _hwnd;
}

ОБНОВЛЯТЬ:Использование Internet Explorer 7 и .NET 2.0.

ОБНОВЛЯТЬ:Поигравшись еще немного со Spy++ и его дескрипторами, я обнаружил, что если я использую другой hwnd тогда я могу сделать свое окно модальным для вкладки:

Я использовал вкладку hwnd как было предложено Документ IWebBrowser2.HWND, который в Spy++ отображается как класс TabWindowClass.У него есть дочерний элемент класса Shell DocObject View, у которого есть дочерний элемент Internet_Explorer_Server.Если я использую hwnd принадлежащий Internet Explorer_Server то работает корректно, например когда я кликаю мышкой по другим вкладкам, Internet Explorer реагирует нормально.Когда я нажимаю мышкой на интересующую вкладку, он воспроизводит звук windows d'oh и ничего не делает.

Я пока не знаю, как программно получить Internet_Explorer_Server. hwnd, но это должно быть возможно.

Кроме того, как бы то ни было, играя с другими дескрипторами окон, я обычно мог сделать свою форму модальной для других приложений и диалогов.Поэтому я думаю, что ответ на мой вопрос: «многие, но не все ручки»…возможно это зависит от приложения?

ОБНОВЛЯТЬ:Еще одно примечание:Первоначальная причина, по которой я хотел сделать форму модальной для вкладки, а не для всего окна, заключалась в том, что при открытии MessageBox из моей формы, передав форму в качестве владельца, MessageBox не всегда открывался поверх моей формы.Если новая вкладка Internet Explorer только что была открыта, но не была активна, MessageBox будет скрыт, и эта вкладка начнет мигать.Однако, поскольку Internet Explorer был отключен, а моя форма открылась в модальном режиме, переключиться на эту вкладку было невозможно, поэтому Internet Explorer зависал.Я думал, что открытие модальной формы на вкладке решит эту проблему, но я нашел другое решение — избегать использования MessageBox:если я использую вторую форму и ShowDialog(this) из моей первой формы, то вторая форма правильно открывается вперед.Так что кажется, что Form.ShowDialog() работает лучше, чем MessageBox.Show() в некоторых случаях.Больше обсуждения в Проблемы с модальными диалогами и окнами сообщений.

Это было полезно?

Решение

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

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

Другие советы

ShowDialog() делает две важные вещи.Он начинает создавать цикл сообщений и действует модально по отношению к вызывающему коду.И он отключает любые другие окна в приложении с помощью API-вызова EnableWindow(false).Последнее - это то, чего не происходит в вашем случае.Это не совсем удивительно, учитывая, что окно, которое нужно отключить, не является окном WF.

Возможно, вам придется самостоятельно вызвать EnableWindow().Обязательно включите его повторно, прежде чем диалоговое окно закроется, иначе Windows начнет искать окно другого приложения, чтобы переключить на него фокус.

Вот более краткая версия кода WindowWrapper Райана/Рори:

internal class WindowWrapper : IWin32Window
{
    public IntPtr Handle { get; private set; }
    public WindowWrapper(IntPtr hwnd) { Handle = hwnd; }
}

Я никогда не пробовал это из расширения IE, но у меня есть подозрение, что IE может не «уважать» модальное окно в стиле Win32 так же, как он делает модальное окно, созданное из Javascript с помощью window.open().

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top