8

アプリの 1 つに単純な Web ブラウザー コントロールを実装しようとしています。これは、私が作成しているツールセットに Web アプリを統合するのに役立ちます。

問題は、この Web アプリがポップアップ ウィンドウを絶対に好むことです....

ポップアップを開くと、メイン ウィンドウが含まれる MDI コンテナー フォームの子ではない IE ウィンドウで開きます。

WebBrowser のリンクをクリックして作成されたすべてのポップアップを MDI コンテナーの子にするにはどうすればよいですか (フォームの MDIParent プロパティを設定するのと同様です)。

前もって感謝します。

4

4 に答える 4

26

Web ブラウザー コントロールは、ポップアップ ウィンドウに関する通知を受け取る NewWindow イベントをサポートしています。ただし、Winforms ラッパーでは、多くのことを行うことはできません。ポップアップをキャンセルすることしかできません。ネイティブ COM ラッパーは、Web ブラウザーの新しいインスタンスを返すことを許可します。そのインスタンスは、ポップアップの表示に使用されます。

これを利用するには、いくつかの作業が必要です。まず、[プロジェクト] + [参照の追加] の [参照] タブを使用して、c:\windows\system32\shdocvw.dll を選択します。これにより、ネイティブ COM インターフェイスへの参照が追加されます。

ポップアップ フォームとして機能するフォームを作成します。その上に WebBrowser をドロップし、そのコードを次のようにします。

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

Browser プロパティは、ポップアップ ウィンドウに Web ページを表示するために使用されるブラウザーへのアクセスを提供します。

ここでメインフォームに戻ります。その上に 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 ポップアップとして処理せず、ブラウザ ウィンドウを使用して表示しないため、傍受したり置き換えたりすることはできません。

于 2011-06-24T20:30:32.053 に答える
3

これを行う最善の方法は、 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」アセンブリの「Embed Interop Types」を false に設定します。
  • 「ローカル コピー」を true に設定します。

そのヘルプのソースMSDN ポスト

于 2014-05-06T17:24:30.513 に答える
2

Hans の回答を改良すると、参照を追加せずに COM にアクセスするための WebBrowser を派生させることができます。これは、未公開の 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);
        }
    }
}
于 2013-12-20T18:28:32.570 に答える