2009-02-24 3 views
2

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

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

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

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

FYI, я использую этот класс-обертку для создания IWin32Window из hwnd (спасибо Ryan!):

/// <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; 
} 

UPDATE: Использование Internet Explorer,   .NET 2.0

UPDATE: Играя еще немного со Spy ++ и ручками, которые он предоставляет, я считаю, что если я использую другой hwnd, то я могу сделать свое окно модальным на вкладку:

Я использовал вкладку hwnd, как предложено IWebBrowser2.HWND doc, которое в Spy ++ появляется как класс TabWindowClass. Он имеет дочерний класс Shell DocObject View, у которого есть дочерний объект Internet_Explorer_Server. Если я использую hwndInternet Explorer_Server, то он работает правильно, например, когда я нажимаю мышью на других вкладках, Internet   Explorer реагирует нормально. Когда я нажимаю мышью на интересующей вкладке, он воспроизводит звук в окнах и ничего не делает.

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

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

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

+0

Какая версия IE вы используете? – JaredPar

+0

ie7 - я должен был сказать. – Rory

ответ

2

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

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

+0

Я не думаю, что вы говорите о резьбе, совершенно правильно. Если я использую hwnd, скажем, в окне «Блокнот», тогда он отлично работает. Если это не так, что между потоками в одном процессе и потоках в другом процессе. Мне кажется, что каждое окно делает что-то умное, если оно заблокировано. – Rory

+0

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

0

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

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

5

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

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

2

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

internal class WindowWrapper : IWin32Window 
{ 
    public IntPtr Handle { get; private set; } 
    public WindowWrapper(IntPtr hwnd) { Handle = hwnd; } 
} 
Смежные вопросы