Уеб браузър за обработка на изскачащи прозорци в приложението

Опитвам се да използвам контролата WebBrowser, за да стартирам нов формуляр за изскачащи прозорци, вместо да се отваря в IE. Опитах се да използвам AxWebBrowser вместо това, за да получа изскачащи прозорци, който работи със събитие NewWindow3 и просто правя e.ppDisp = AxWebBrowser.Application, но има много ограничения, които идват с AxWebBrowser. Затова вместо това се опитвам да разширя нормалния уеббраузър, за да включва събитието 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
Отговорено тук за C#, не би трябвало да е проблем да се преведе на 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 хостинг кода, който никога не е бил адресиран. Проверете тази публикация за повече подробности и възможно заобиколно решение.

Друго възможно заобиколно решение може да бъде хостването на WebBrowser ActiveX Control директно чрез AxHost клас, в който случай WindowClosing се задейства правилно. Пример:

C#:

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='/bgjavascript:""<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. Мога да потвърдя, че вашето решение работи за C# без проблем. Но изглежда не мога да преобразувам правилно кода във 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