Как отобразить всплывающее окно из веб-браузера в другом окне, которое я создал? - PullRequest
7 голосов
/ 24 июня 2011

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

Проблема в том, что это веб-приложение абсолютно любит всплывающие окна ....

Когда открывается всплывающее окно, оно открываетсяв окне IE, которое не является дочерним элементом формы контейнера MDI, частью которой является мое главное окно.

Как получить все всплывающие окна, созданные путем нажатия на ссылки в моем веб-браузере, чтобы они были дочерним элементом моего MDIконтейнер (аналогично настройке свойства MDIParent формы)?

Заранее спасибо.

Ответы [ 3 ]

25 голосов
/ 25 июня 2011

Элемент управления веб-браузера поддерживает событие NewWindow, чтобы получать уведомления о всплывающем окне. Обертка Winforms, однако, не позволяет вам делать с ней многое, вы можете только отменить всплывающее окно. Собственная оболочка COM позволяет передавать новый экземпляр веб-браузера, который затем будет использоваться для отображения всплывающего окна.

Чтобы воспользоваться этим, нужно потрудиться. Для начала используйте Project + Add Reference, вкладку Browse и выберите c: \ windows \ system32 \ shdocvw.dll. Это добавляет ссылку на собственный интерфейс COM.

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

public partial class Form2 : Form {
    public Form2() {
        InitializeComponent();
    }
    public WebBrowser Browser {
        get { return webBrowser1; }
    }
}

Свойство Browser предоставляет доступ к браузеру, который будет использоваться для отображения веб-страницы во всплывающем окне.

Теперь вернемся к основной форме. Поместите на него WebBrowser и сделайте так, чтобы его код выглядел так:

public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
        webBrowser1.Url = new Uri("http://google.com");
    }
    SHDocVw.WebBrowser nativeBrowser;
    protected override void OnLoad(EventArgs e) {
        base.OnLoad(e);
        nativeBrowser = (SHDocVw.WebBrowser)webBrowser1.ActiveXInstance;
        nativeBrowser.NewWindow2 += nativeBrowser_NewWindow2;
    }
    protected override void OnFormClosing(FormClosingEventArgs e) {
        nativeBrowser.NewWindow2 -= nativeBrowser_NewWindow2;
        base.OnFormClosing(e);
    }

    void nativeBrowser_NewWindow2(ref object ppDisp, ref bool Cancel) {
        var popup = new Form2();
        popup.Show(this);
        ppDisp = popup.Browser.ActiveXInstance;
    }
}

Метод OnLoad получает ссылку на собственный интерфейс COM, а затем подписывает обработчик события на событие NewWindow2. Я удостоверился, что отменил подписку на это событие в обработчике событий FormClosing, не уверен на 100%, если это необходимо. Лучше в безопасности, чем потом извиниться.

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

Имейте в виду, что это событие не срабатывает для окна, отображаемого, когда Javascript использует alert (). Браузер не рассматривает это окно как всплывающее окно HTML и не использует окно браузера для его отображения, поэтому вы не можете перехватить или заменить его.

3 голосов
/ 06 мая 2014

Я обнаружил, что лучший способ сделать это - реализовать / обработать событие NewWindow3

Добавьте ссылку на c: \ windows \ system32 \ shdocvw.dll , как указано в других ответах здесь.

Добавить обработчик событий

SHDocVw.WebBrowser wbCOMmain = (SHDocVw.WebBrowser)webbrowser.ActiveXInstance;
wbCOMmain.NewWindow3 += wbCOMmain_NewWindow3;

Метод события

void wbCOMmain_NewWindow3(ref object ppDisp, 
                          ref bool Cancel, 
                          uint dwFlags, 
                          string bstrUrlContext, 
                          string bstrUrl)
{
    // bstrUrl is the url being navigated to
    Cancel = true; // stop the navigation

    // Do whatever else you want to do with that URL
    // open in the same browser or new browser, etc.
}
  • Установить для "Встраивать типы взаимодействия" для сборки "Interop.SHDocVw" значение false
  • Установите для "локальной копии" значение true.

Источник этой справки MSDN Post

2 голосов
/ 20 декабря 2013

Уточнение ответа Ханса, вы можете получить WebBrowser для доступа к COM без добавления ссылки. Это с помощью неопубликованных методов Winforms WebBrowser.AttachInterface и DetachInterface.

Более подробно здесь .

Вот код:

Использование (измените свой экземпляр WebBrowser на WebBrowserNewWindow2)

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        this.webBrowser1.NewWindow2 += webBrowser_NewWindow2;
    }

    protected override void OnFormClosing(FormClosingEventArgs e)
    {
        webBrowser1.NewWindow2 -= webBrowser_NewWindow2;
        base.OnFormClosing(e);
    }

    void webBrowser_NewWindow2(object sender, WebBrowserNewWindow2EventArgs e)
    {
        var popup = new Form1();
        popup.Show(this);
        e.PpDisp = popup.Browser.ActiveXInstance;
    }
    public WebBrowserNewWindow2 Browser
    {
        get { return webBrowser1; }
    }
}

Код:

using System;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace SHDocVw
{
    public delegate void WebBrowserNewWindow2EventHandler(object sender, WebBrowserNewWindow2EventArgs e);

    public class WebBrowserNewWindow2EventArgs : EventArgs
    {
        public WebBrowserNewWindow2EventArgs(object ppDisp, bool cancel)
        {
            PpDisp = ppDisp;
            Cancel = cancel;
        }

        public object PpDisp { get; set; }
        public bool Cancel { get; set; }
    }

    public class WebBrowserNewWindow2 : WebBrowser
    {
        private AxHost.ConnectionPointCookie _cookie;
        private WebBrowser2EventHelper _helper;

        [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
        protected override void CreateSink()
        {
            base.CreateSink();

            _helper = new WebBrowser2EventHelper(this);
            _cookie = new AxHost.ConnectionPointCookie(
                this.ActiveXInstance, _helper, typeof(DWebBrowserEvents2));
        }

        [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
        protected override void DetachSink()
        {
            if (_cookie != null)
            {
                _cookie.Disconnect();
                _cookie = null;
            }
            base.DetachSink();
        }

        public event WebBrowserNewWindow2EventHandler NewWindow2;

        private class WebBrowser2EventHelper : StandardOleMarshalObject, DWebBrowserEvents2
        {
            private readonly WebBrowserNewWindow2 _parent;

            public WebBrowser2EventHelper(WebBrowserNewWindow2 parent)
            {
                _parent = parent;
            }

            public void NewWindow2(ref object pDisp, ref bool cancel)
            {
                WebBrowserNewWindow2EventArgs arg = new WebBrowserNewWindow2EventArgs(pDisp, cancel);
                _parent.NewWindow2(this, arg);
                if (pDisp != arg.PpDisp)
                    pDisp = arg.PpDisp;
                if (cancel != arg.Cancel)
                    cancel = arg.Cancel;
            }
        }

        [ComImport, Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D"),
        InterfaceType(ComInterfaceType.InterfaceIsIDispatch),
        TypeLibType(TypeLibTypeFlags.FHidden)]
        public interface DWebBrowserEvents2
        {
            [DispId(0xfb)]
            void NewWindow2(
                [In, Out, MarshalAs(UnmanagedType.IDispatch)] ref object ppDisp,
                [In, Out] ref bool cancel);
        }
    }
}
...