Веб-браузер для обработки всплывающих окон в приложении

Я пытаюсь использовать элемент управления WebBrowser для запуска новой формы для всплывающих окон вместо ее открытия в IE. Вместо этого я попытался использовать AxWebBrowser, чтобы получить всплывающие окна, которые работают с событием NewWindow3 и просто выполняют e.ppDisp = AxWebBrowser.Application, но есть много ограничений, связанных с AxWebBrowser. Поэтому вместо этого я пытаюсь расширить обычный WebBrowser, чтобы включить событие NewWindow3, например AxWebBrowser, но столкнулся с проблемами. С e.ppDisp = AxWebBrowser.Application я получаю ошибки: «Обнаружен InvalidVariant», а затем «Указанный вариант OLE недействителен», если я продолжаю.

Примечание. Это мой первый раз, когда я расширяю класс, поэтому я мог упустить что-то простое. Если я попытаюсь просто перейти к новому URL-адресу в новом окне, я получу ошибки java-скрипта с сайта.

Я обновил базу кода по комментариям. Удален класс ExtendedWebBrowser для более компактной и приятной версии. Вот новый код:

Из основной формы и очень похожей формы BrowserPopup —

Protected Overrides Sub OnLoad(ByVal e As EventArgs)
    MyBase.OnLoad(e)
    nativeBrowser = DirectCast(ExtendedWebBrowser1.ActiveXInstance, SHDocVw.WebBrowser)
    AddHandler nativeBrowser.NewWindow3, AddressOf nativeBrowser_NewWindow3
    AddHandler nativeBrowser.WindowClosing, AddressOf nativeBrowser_WindowClosing
End Sub

Private Sub nativeBrowser_NewWindow3(ByRef ppDisp As Object, ByRef Cancel As Boolean, ByVal dwflags As UInteger, ByVal bStrUrlContext As String, ByVal bstrUrl As String)
    Dim popup = New BrowserPopup()
    popup.Show(Me)
    popup.browserPop.DocumentText = bStrUrlContext
    ppDisp = popup.browserPop.ActiveXInstance
End Sub

Private Sub nativeBrowser_WindowClosing(ByVal IsChildWindow As Boolean, ByRef Cancel As Boolean)
    MsgBox("working?") '<<<Doesn't Trigger>>>
End Sub

Protected Overrides Sub OnFormClosing(ByVal e As FormClosingEventArgs)
    MyBase.OnFormClosing(e)
End Sub

Кроме того, если это поможет, вот сценарий со страницы, который должен иметь возможность закрывать всплывающую форму, но вместо этого просто деактивирует веб-браузер.

<table isListBtn="false" cellpadding="0" enabled="true" class="buttonBorderBlue"
cellspacing="0" border="0" onClick="if (typeof(workpaneMediator_toolbar)!='undefined')
workpaneMediator_toolbar.onSelect('CANCEL_ACTION', this)"
actionType="CLOSE_WINDOW_TYPE" id="workpaneMediator_toolbar_CANCEL_ACTIONWrapper"
nowrap><tr><td class="buttonBlueTD">

person Congree    schedule 27.10.2013    source источник
comment
Ответил здесь для С#, не должно быть проблем с переводом на VB.   -  person noseratio    schedule 28.10.2013
comment
Спасибо за ответ! Я смог преобразовать код и внедрить его в свой собственный. Теперь он появляется без ошибок и по большей части правильно запускает скрипты. Но при нажатии кнопок java-скрипта для отправки/отмены всплывающего окна веб-браузер перестает работать (как и должно быть), но всплывающая форма не исчезает. Я исследую и вижу, могу ли я найти что-нибудь для этого.   -  person Congree    schedule 28.10.2013
comment
Для ссылок JavaScript проверьте эту.   -  person noseratio    schedule 28.10.2013
comment
Ссылка, которую вы предоставили для JavaScripts, кажется, мало что для меня делает. Просто чтобы внести ясность, я удалил класс WebBrowserEx на данный момент, забрав элемент, который вы впервые опубликовали. Это успешно открывает всплывающее окно в новой форме без ошибок. Однако при попытке щелкнуть «Отправить/закрыть» в новой форме веб-браузер, похоже, деактивируется, как будто ему сказали закрыть. Но сама форма не закрывается автоматически. Я попытался проверить различные события из веб-браузера, но не могу найти никаких событий, если они вызываются.   -  person Congree    schedule 30.10.2013
comment
Обработка закрытия формы с помощью WebBrowser из JavaScript — это другое дело. Вы смотрели на событие WindowClosing базовый элемент управления WebBrowser ActiveX?   -  person noseratio    schedule 30.10.2013
comment
WindowClosing тоже не улавливает. Собираюсь обновить код в моем исходном посте, чтобы отразить последние изменения.   -  person Congree    schedule 30.10.2013


Ответы (1)


Вы правы, что WindowClosing не увольняют за Winforms WebBrowser Control, я это подтверждаю. Похоже, это давняя ошибка в коде размещения .NET WebBrowser ActiveX, которая никогда не исправлялась. Проверьте это сообщение для получения дополнительных сведений и возможного обходного пути.

Другим возможным обходным путем может быть размещение элемента управления ActiveX WebBrowser непосредственно через класс AxHost, и в этом случае WindowClosing срабатывает правильно. Пример:

С#:

using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WebBrowserApp
{
    // MainForm

    public partial class MainForm : Form 
    {
        WebBrowser webBrowser;

        public MainForm()
        {
            InitializeComponent();
            InitBrowser();

            if (this.webBrowser.Document == null && this.webBrowser.ActiveXInstance == null)
                throw new ApplicationException ("Unable to initialize WebBrowser ActiveX control.");

            var ax = (SHDocVw.WebBrowser)this.webBrowser.ActiveXInstance;
            ax.NewWindow2 += (ref object ppDisp, ref bool Cancel) =>
            {
                var popup = new RawBrowserPopup();
                popup.Visible = true;
                ppDisp = popup.WebBrowser.ActiveXInstance;
            };

            this.Load += (s, e) =>
            {
                this.webBrowser.DocumentText = "<a target=\"_blank\" href=\"javascript:'<button onclick=\\'window.close()\\'>Close</button>'\">Go</a>";
            };
        }

        // create a WebBrowser instance
        void InitBrowser()
        {
            this.webBrowser = new WebBrowser();
            this.webBrowser.Dock = DockStyle.Fill;
            this.Controls.Add(this.webBrowser);
            this.webBrowser.Visible = true;
        }
    }

    // RawWebBrowser

    public class RawWebBrowser : AxHost
    {
        public RawWebBrowser()
            : base("8856f961-340a-11d0-a96b-00c04fd705a2")
        {
        }

        public event EventHandler Initialized;

        protected override void AttachInterfaces()
        {
            if (this.Initialized != null)
                this.Initialized(this, new EventArgs());
        }

        public object ActiveXInstance
        {
            get
            {
                return base.GetOcx();
            }
        }
    }

    // RawBrowserPopup

    public class RawBrowserPopup : Form
    {
        RawWebBrowser webBrowser;

        public RawWebBrowser WebBrowser
        {
            get { return this.webBrowser; }
        }

        public RawBrowserPopup()
        {
            this.webBrowser = new RawWebBrowser();

            this.webBrowser.Initialized += (s, e) =>
            {
                var ax = (SHDocVw.WebBrowser)this.webBrowser.ActiveXInstance;
                ax.NewWindow2 += (ref object ppDisp, ref bool Cancel) =>
                {
                    var popup = new RawBrowserPopup();
                    popup.Visible = true;
                    ppDisp = popup.WebBrowser.ActiveXInstance;
                };

                ax.WindowClosing += (bool IsChildWindow, ref bool Cancel) =>
                {
                    Cancel = true;
                    this.Close();
                };
            };

            this.webBrowser.Dock = DockStyle.Fill;
            this.Controls.Add(this.webBrowser);
            this.webBrowser.Visible = true;
        }
    }
}

VB.NET:

Public Class Form1
    Dim webBrowser As WebBrowser = New WebBrowser()

    Sub New()
        MyBase.New()
        Me.InitializeComponent()
        webBrowser.Dock = DockStyle.Fill
        Me.Controls.Add(webBrowser)
        webBrowser.Visible = True
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.webBrowser.DocumentText = "<a target='_blank' href='javascript:""<button onclick=\""window.close()\"">Close</button>""'>Go</a>"

        Dim ActiveX As SHDocVw.WebBrowser = Me.webBrowser.ActiveXInstance
        AddHandler ActiveX.NewWindow2, AddressOf WebBrowser_ActiveX_NewWindow2
    End Sub

    Private Sub WebBrowser_ActiveX_NewWindow2(ByRef ppDisp As Object, ByRef Cancel As Boolean)
        Dim popup As RawBrowserPopup = New RawBrowserPopup()
        popup.Visible = True
        ppDisp = popup.WebBrowser.ActiveXInstance
    End Sub
End Class

Public Class RawWebBrowser
    Inherits System.Windows.Forms.AxHost

    Sub New()
        MyBase.New("8856f961-340a-11d0-a96b-00c04fd705a2")
    End Sub

    Event Initialized(sender As Object, e As EventArgs)

    Protected Overrides Sub AttachInterfaces()
        RaiseEvent Initialized(Me, New EventArgs())
    End Sub

    Public ReadOnly Property ActiveXInstance() As Object
        Get
            Return MyBase.GetOcx()
        End Get
    End Property
End Class

Public Class RawBrowserPopup
    Inherits System.Windows.Forms.Form

    Dim WithEvents rawBrowser As RawWebBrowser = New RawWebBrowser()

    Sub New()
        MyBase.New()
        rawBrowser.Dock = DockStyle.Fill
        Me.Controls.Add(rawBrowser)
        rawBrowser.Visible = True
    End Sub

    Public ReadOnly Property WebBrowser() As Object
        Get
            Return rawBrowser
        End Get
    End Property

    Private Sub rawBrowser_Initialized(sender As Object, e As EventArgs) Handles rawBrowser.Initialized
        Dim activeX As SHDocVw.WebBrowser = rawBrowser.ActiveXInstance
        AddHandler activeX.NewWindow2, AddressOf activeX_NewWindow2
        AddHandler activeX.WindowClosing, AddressOf activeX_WindowClosing
    End Sub

    Private Sub activeX_NewWindow2(ByRef ppDisp As Object, ByRef Cancel As Boolean)
        Dim popup As RawBrowserPopup = New RawBrowserPopup()
        popup.Visible = True
        ppDisp = popup.WebBrowser.ActiveXInstance
    End Sub

    Private Sub activeX_WindowClosing(IsChildWindow As Boolean, ByRef Cancel As Boolean)
        Cancel = True
        Me.Close()
    End Sub

End Class
person noseratio    schedule 30.10.2013
comment
Ссылка, предоставленная для обходного пути, показывает событие ParentNotify, происходящее в WM_LBUTTONDOWN. WM_DESTROY, похоже, не вызывается. Я думаю, что мне, возможно, придется изучить C#, потому что все решения для моей проблемы доступны на C#, и они никогда не работают правильно при преобразовании в VB.Net. Я могу подтвердить, что ваше решение работает для С# без проблем. Но я не могу правильно преобразовать код в VB.Net. Такие сайты, как developerfusion.com, конвертируют его неправильно. В частности, ему не нравится преобразование ax.NewWindow2 += (ref object ppDisp, ref bool Cancel) =>... - person Congree; 30.10.2013
comment
@Congree, я опубликовал рабочий образец VB.NET. Это все, что я могу помочь с этим вопросом. - person noseratio; 31.10.2013
comment
Большое спасибо за всю вашу помощь! Я убедился, что он правильно работает в VB.Net и это именно то, что мне нужно. Еще раз спасибо! Я буду голосовать, как только у меня будет достаточно представителей и сайт позволит мне. - person Congree; 01.11.2013
comment
Рад, что это помогло. +1 за сообщение о проблеме с WindowClosing. - person noseratio; 01.11.2013