WebBrowser и активация формы

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

Mleha
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 146
Зарегистрирован: 06.10.2004 (Ср) 7:49
Откуда: Ангарск

WebBrowser и активация формы

Сообщение Mleha » 26.04.2012 (Чт) 17:50

Проблема в следующем:
На форме размещен браузер, в нем листаются страницы.
Часто на страницах есть вызов javascript функции focus()
Это заставляет форму переместиться поверх всех остальных и взять на себя фокус, что раздражает.

Как можно это отловить и предотвратить?

P.S. найденное решение не работает (по крайне мере в Windows 7).

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 26.04.2012 (Чт) 18:23

Выложи код вместе со страницей (или url).

Mleha
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 146
Зарегистрирован: 06.10.2004 (Ср) 7:49
Откуда: Ангарск

Re: WebBrowser и активация формы

Сообщение Mleha » 27.04.2012 (Пт) 1:52

Код тестового приложения:
Код: Выделить всё
Imports System.Security.Permissions

Public Class Form1

  Public Const WM_NCACTIVATE As UInt32 = &H86
  Public Const WM_SYSTIMER As UInt32 = &H118
  Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    WebBrowser1.Navigate("http://192.168.1.5/test.html")
  End Sub

  Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    Dim messageHandled As Boolean = False
    If m.Msg = WM_NCACTIVATE Then
      '// add logic here to determine user action, losing focus etc and set
      '// messageHandled and m.Result only when user action is not the cause
      '// of triggering WM_NCACTIVATE
      m.Result = IntPtr.Zero
      messageHandled = True
    End If

    If m.Msg = WM_SYSTIMER Then
      m.Result = IntPtr.Zero
      messageHandled = True

    End If

    If (Not messageHandled) Then
      MyBase.WndProc(m)
      'Debug.Print(m.Msg)
    End If

  End Sub

  Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    'Me.CreateParams.ExStyle = CreateParams.ExStyle Or ExtendedWindowStyles.WS_EX_NOACTIVATE Or ExtendedWindowStyles.WS_EX_TOOLWINDOW
    Application.AddMessageFilter(New MyMessageFilter(Me.Handle))
  End Sub
End Class

<SecurityPermission(SecurityAction.LinkDemand, Flags:=SecurityPermissionFlag.UnmanagedCode)>
Public Class MyMessageFilter
  Implements IMessageFilter

  Public Const WM_SYSTIMER As UInt32 = &H118

  ' an application can have many windows, only filter for one window at the time
  Private FilteredHwnd As IntPtr = IntPtr.Zero

  Public Sub New(hwnd As IntPtr)
    Me.FilteredHwnd = hwnd
  End Sub

  Public Function PreFilterMessage(ByRef m As Message) As Boolean Implements IMessageFilter.PreFilterMessage

    'If m.Msg = WM_SYSTIMER Then
    If Me.FilteredHwnd = m.HWnd AndAlso m.Msg = WM_SYSTIMER Then
      Return True
    Else
      ' stop handling the message further
      Return False
    End If
    ' all other msgs: handle them
  End Function
End Class


Тестовая страница висит на внутреннем WEB сервере, ее код такой:
Код: Выделить всё
<html>
<head>
<script language="JavaScript" type="text/javascript">
foc();
function foc(){
   focus();                 
   setTimeout("foc()",5000);
}
</script>
</head>
<body>BODY</body>
</html>

burik
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 514
Зарегистрирован: 03.11.2005 (Чт) 22:04
Откуда: Беларусь, Рогачев

Re: WebBrowser и активация формы

Сообщение burik » 27.04.2012 (Пт) 9:43

Вообще-то, в найденном тобой примере речь идет не об активации окна, а о его мигании на таскбаре (в результате вызова FlashWindow). Т.е. в вопросе речь идет об активации, а в ответе, что ты пробуешь использовать - о мигании.

Автор вопроса написал найденное им решение (если его можно так назвать) в своем же вопросе (см. Update):
I've found a temporary answer to my problem.

When the WebBrowser's parent Form's Deactive event is fired, I remove the WebBrowser from its container, and re-add it when its old parent form is activated again.

It's kind of hacky, but it works. I'm open to any better suggestions, though.


А вообще, по-моему, стоит упомянуть о том, что окно перемещается поверх остальных только в пределах процесса. Т. е. если поверх окна с WebBrowser поместить окно другого приложения, то подобного поведения наблюдаться не будет.
Между слухов, сказок, мифов,
просто лжи, легенд сомнений
мы враждуем жарче скифов
за несходство заблуждений
Игорь Губерман

Mleha
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 146
Зарегистрирован: 06.10.2004 (Ср) 7:49
Откуда: Ангарск

Re: WebBrowser и активация формы

Сообщение Mleha » 27.04.2012 (Пт) 10:57

С миганием - действительно мигания не наблюдается с фильтром)

burik писал(а):А вообще, по-моему, стоит упомянуть о том, что окно перемещается поверх остальных только в пределах процесса. Т. е. если поверх окна с WebBrowser поместить окно другого приложения, то подобного поведения наблюдаться не будет.

Как раз нет. Окно выскакивает поверх всех остальных. Предыдущее активное окно теряет фокус.
Даже скрытое состояние окна Visilble = False не мешает ему отнять фокус у активного окна(

Предложенное временное решение с отключением родителя у браузера - не подходит.

Реально ли поймать и отфильтровать сообщение окну об активации?
Или может можно установить какой класс окну, чтобы оно не могло получить фокус и всплыть поверх всех?

burik
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 514
Зарегистрирован: 03.11.2005 (Чт) 22:04
Откуда: Беларусь, Рогачев

Re: WebBrowser и активация формы

Сообщение burik » 27.04.2012 (Пт) 11:54

Mleha писал(а):Как раз нет. Окно выскакивает поверх всех остальных. Предыдущее активное окно теряет фокус.
Даже скрытое состояние окна Visilble = False не мешает ему отнять фокус у активного окна(


Подобное поведение у меня воспроизвести не получилось. У меня акно с WebBrowser переходит на передний план только в том случае, если в данный момент активным является одно из окон приложения. Если же активным является, скажем, окно SQL Management Studio, то ничего не происходит. Запускаю под Win 7 x64, VS 2010 v4.0.30319 SP1. Проект WinForms.
Между слухов, сказок, мифов,
просто лжи, легенд сомнений
мы враждуем жарче скифов
за несходство заблуждений
Игорь Губерман

Mleha
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 146
Зарегистрирован: 06.10.2004 (Ср) 7:49
Откуда: Ангарск

Re: WebBrowser и активация формы

Сообщение Mleha » 27.04.2012 (Пт) 15:10

В тестовом приложении всего одна форма. И все равно она выскакивает наверх всего.
Собрал проект, burik, посмотри пожалуйста. И еще, ты же ничего не менял в предложенном коде? Из-за чего может быть разное поведение приложения? Версия IE? У меня 9.0.8112.16421

burik писал(а):Запускаю под Win 7 x64, VS 2010 v4.0.30319 SP1. Проект WinForms.

У меня один в один окружение
Вложения
WindowsApplication1.rar
(62.68 Кб) Скачиваний: 177

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 27.04.2012 (Пт) 20:31

Mleha писал(а):С миганием - действительно мигания не наблюдается с фильтром)

Ну это у кого как :)
У меня WinXP SP3. Меняет цвет раз в 5 секунд :D
A вот без фильтра форма вылазиет наверх других приложений...

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: WebBrowser и активация формы

Сообщение FireFenix » 28.04.2012 (Сб) 0:56

Можно сделать хак через рефлексию - найти место, которое вызывает получение фокуса и подменить своей реализацией. Но для этого нада перелопатить весь контрол и найти место
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 28.04.2012 (Сб) 1:18

FireFenix писал(а):Можно сделать хак через рефлексию - найти место, которое вызывает получение фокуса и подменить своей реализацией.

Ты думаешь, что это не в нативной части контрола сделано? Что-то сомнительно...

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: WebBrowser и активация формы

Сообщение FireFenix » 28.04.2012 (Сб) 20:50

Qwertiy писал(а):
FireFenix писал(а):Можно сделать хак через рефлексию - найти место, которое вызывает получение фокуса и подменить своей реализацией.

Ты думаешь, что это не в нативной части контрола сделано? Что-то сомнительно...

FireFenix писал(а):Но для этого нада перелопатить весь контрол и найти место

Если в нативной части происходит прямая установка фокуса через системное API, то тогда да - провал.
Остальные цепочки связей или методы можно заменить через рефлексию или свойств самого объекта
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

burik
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 514
Зарегистрирован: 03.11.2005 (Чт) 22:04
Откуда: Беларусь, Рогачев

Re: WebBrowser и активация формы

Сообщение burik » 29.04.2012 (Вс) 12:59

Mleha писал(а):Собрал проект, burik, посмотри пожалуйста. И еще, ты же ничего не менял в предложенном коде?


Я не брал код - набросал свой пример еще до того, как ты выложил. У меня фокус передавался конкретному элементу внутри страницы:
Код: Выделить всё
<!DOCTYPE html>
<html>
<head>
    <title>Focus test</title>
    <script type="text/javascript">
    function setFocus() {
        document.getElementById("textField").focus();
        setTimeout("setFocus()", 3000);
    }
    </script>
</head>
    <body onload="setFocus()">
        <input type="text" />
        <input type="text" id="textField" />
    </body>
</html>


Вероятно дело в этом - у тебя вызывается просто focus(), а если учитывать что этот код находится в контексте window, то вызов эквивалентен вызову window.focus(), соответственно, подобное поведение вполне логично. Тебе нужно просто переопределить focus().

Для примера добавь в свой код перед вызовом foc() переопределение функции:
Код: Выделить всё
function focus() { }

и посмотри что будет.

Ну а в целом, нужно обрабатывать загрузку нового документа и переопределять эту функцию. Пример в аттаче.
Вложения
VbFocusIssue.zip
Простой пример оверайда.
(12.1 Кб) Скачиваний: 186
Между слухов, сказок, мифов,
просто лжи, легенд сомнений
мы враждуем жарче скифов
за несходство заблуждений
Игорь Губерман

Mleha
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 146
Зарегистрирован: 06.10.2004 (Ср) 7:49
Откуда: Ангарск

Re: WebBrowser и активация формы

Сообщение Mleha » 29.04.2012 (Вс) 17:16

burik, Благодарю! Работает!!

Отлов же сообщений окну работал все таки, но через раз((.
Запущу приложение без студии. Все нормально. Как только запущу студию (просто открою исходник какого либо проекта), то все - окошко наверху(
С чем это связать так и не понял..

Переделал обработчик события DocumentCompleted. Теперь не надо цеплять Javascript из файла:
Только пришлось зацепить референс Microsoft.mshtml
Код: Выделить всё
   Private Sub OnDocumentCompleted(sender As System.Object, e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
    Dim head As HtmlElement, Script As HtmlElement
    Dim Script2 As mshtml.IHTMLScriptElement

    Script = WebBrowser1.Document.CreateElement("script")
    script.SetAttribute("type", "text/javascript")

    Script2 = Script.DomElement
    Script2.text = "function overrideWindowFocus() {window.focus = function () { }; };"

    head = WebBrowser1.Document.GetElementsByTagName("head").Item(0)
    head.AppendChild(script)

    WebBrowser1.Document.InvokeScript("overrideWindowFocus")
  End Sub



Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 17

    TopList