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

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

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

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

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

FYI, я использую этот класс - обертку , чтобы создать 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 doh и ничего не происходит.

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

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

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

Ответов (4)

Решение

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

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

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

Вы тестировали этот код на чем-то другом, кроме 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; }
}