DOBON.NET DOBON.NETプログラミング掲示板過去ログ

新規ウィンドウを自前のForm(WebBrowser)で開きたい(VC#2008)

環境/言語:[VC#.NET 2008]
分類:[.NET]

はじめまして、Kyunsukeと申します。
仕事で必要があり、自作のForm上のWebBrowserコントロールWebページを表示させようとしています。

表示させようとしているWebページはログインを必要としており、デフォルトのWebBrowserコントロールではIEが開いてしまいます。
そこで、いくつかのWebサイトを参照して、クラスを拡張してNewWindow2イベントの実装しようと試みました。
下記コードではイベントの実装は成功しているようなのですが新規ウィンドウはIEで開いてしまいます。
AxHost.InvalidActiveXStateExceptionの例外がスローされているのが原因なのでしょうか…

もしよければ、先生先輩方のお知恵を拝借できれば幸いです。

//------------------------コード--------------------------------//

//Form1.cs抜粋
using System.Security.Permissions;
using System.Runtime.InteropServices;

namespace myBrowser
{

[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public partial class Form1 : Form
{

public Form1()
{
InitializeComponent();

}

private void webBrowser_NewWindow2(object sender, WebBrowserNewWindow2EventArgs e)
{
//新しいWebBrowserの初期化
var newBrowser = new WebBrowserEx();
newBrowser.Dock = DockStyle.Fill;

//新しいWebBrowserからさらにウィンドウを開かせるときも同じようにする
newBrowser.NewWindow2 += webBrowser_NewWindow2;

//新しいWebBrowserに表示させる設定
e.ppDisp = newBrowser.Application;
newBrowser.RegisterAsBrowser = true;
newBrowser.Visible = true;

}

public class WebBrowserEx : WebBrowser
{
private AxHost.ConnectionPointCookie cookie;
private WebBrowser2EventHelper helper;

[DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)]
[DispIdAttribute(200)]

public object Application
{
get
{
if (this.ActiveXInstance == null)
{
throw new AxHost.InvalidActiveXStateException("Application", AxHost.ActiveXInvokeKind.PropertyGet);
}
return ((IWebBrowser2)this.ActiveXInstance).Application;
}
}

[DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)]
[DispIdAttribute(552)]
public bool RegisterAsBrowser
{
get
{
if (this.ActiveXInstance == null)
{
throw new AxHost.InvalidActiveXStateException("RegisterAsBrowser", AxHost.ActiveXInvokeKind.PropertyGet);
}
return ((IWebBrowser2)this.ActiveXInstance).RegisterAsBrowser;
}
set
{
if (this.ActiveXInstance == null)
{
throw new AxHost.InvalidActiveXStateException("RegisterAsBrowser", AxHost.ActiveXInvokeKind.PropertySet);
}
((IWebBrowser2)this.ActiveXInstance).RegisterAsBrowser = value;
}
}

[PermissionSetAttribute(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;// = (o, e) => { };

protected virtual void OnNewWindow2(WebBrowserNewWindow2EventArgs e)
{
NewWindow2(this, e);
}

private class WebBrowser2EventHelper : StandardOleMarshalObject, DWebBrowserEvents2
{
private WebBrowserEx parent;

public WebBrowser2EventHelper(WebBrowserEx parent)
{
this.parent = parent;
}

public void NewWindow2(ref object ppDisp, ref bool cancel)
{
var e = new WebBrowserNewWindow2EventArgs(ppDisp);
this.parent.OnNewWindow2(e);
ppDisp = e.ppDisp;
cancel = e.Cancel;
}
}
}

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

public class WebBrowserNewWindow2EventArgs : CancelEventArgs
{
public object ppDisp { get; set; }

public WebBrowserNewWindow2EventArgs(object ppDisp)
{
this.ppDisp = ppDisp;
}
}

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

[ComImport, Guid("D30C1661-CDAF-11D0-8A3E-00C04FC9E26E")]
public interface IWebBrowser2
{
object Application { get; }
bool RegisterAsBrowser { get; set; }
}

public enum DISPID
{
NEWWINDOW2 = 251
}
}

//Form1.Desineer.cs抜粋

private WebBrowserEx webBrowser1;
private void InitializeComponent()
{
this.webBrowser1 = new WebBrowserEx();
//
// webBrowser1
//
this.webBrowser1.Dock = System.Windows.Forms.DockStyle.Fill;
this.webBrowser1.IsWebBrowserContextMenuEnabled = false;
this.webBrowser1.Location = new System.Drawing.Point(0, 74);
this.webBrowser1.Name = "webBrowser1";
this.webBrowser1.Size = new System.Drawing.Size(292, 170);
this.webBrowser1.TabIndex = 0;
this.webBrowser1.WebBrowserShortcutsEnabled = false;
this.webBrowser1.Navigated += new System.Windows.Forms.WebBrowserNavigatedEventHandler(this.webBrowser1_Navigated);
this.webBrowser1.NewWindow2 += new WebBrowserNewWindow2EventHandler(webBrowser_NewWindow2);
//
// Form1
//
this.Controls.Add(this.webBrowser1);
}
IWebBrowser2インターフェイスの定義が間違っていると思います。

>         [ComImport, Guid("D30C1661-CDAF-11D0-8A3E-00C04FC9E26E")]
>         public interface IWebBrowser2
>         {
>             object Application { get; }
>             bool RegisterAsBrowser { get; set; }
>         }

IWebBrowser2インターフェイスをきちんと定義するのは大変だと思うので,

return ((IWebBrowser2)this.ActiveXInstance).Application;

の部分は遅延バインディングで次のようにすればよいと思います。

return this.ActiveXInstance.GetType().InvokeMember("Application", System.Reflection.BindingFlags.GetProperty, null, this.ActiveXInstance, null);
あと,新しく作ったWebBrowserコントロールをフォームにAddしていないと思います。簡単なタブ型ブラウザにするなら次のようになると思います。

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

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        TabControl TabControl1 = new TabControl();
        WebBrowserEx WebBrowser1;
        TabPage TabPage1;

        private void Form1_Load(System.Object sender, System.EventArgs e)
        {
            this.WebBrowser1 = new WebBrowserEx();
            this.WebBrowser1.Dock = DockStyle.Fill;
            WebBrowser1.NewWindow2 += WebBrowser_NewWindow2;
            this.TabPage1 = new TabPage();
            this.TabPage1.Controls.Add(WebBrowser1);
            this.TabControl1.Dock = DockStyle.Fill;
            this.TabControl1.TabPages.Add(TabPage1);
            this.Controls.Add(this.TabControl1);
            this.WebBrowser1.GoHome();
        }
        
        private void WebBrowser_NewWindow2(object sender, WebBrowserNewWindow2EventArgs e)
        {
            this.WebBrowser1 = new WebBrowserEx();
            this.WebBrowser1.Dock = DockStyle.Fill;
            WebBrowser1.NewWindow2 += WebBrowser_NewWindow2;
            this.TabPage1 = new TabPage();
            this.TabPage1.Controls.Add(WebBrowser1);
            this.TabControl1.Controls.Add(TabPage1);
            this.TabControl1.SelectedTab = TabPage1;
            e.ppDisp = this.WebBrowser1.Application;
            this.WebBrowser1.RegisterAsBrowser = true;
        }
         
        public Form1()
        {
            InitializeComponent();
        }
    }

    public class WebBrowserEx : WebBrowser
    {
        private AxHost.ConnectionPointCookie cookie;
        private WebBrowser2EventHelper helper;

        [DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)]
        [DispIdAttribute(200)]

        public object Application
        {
            get
            {
                if (this.ActiveXInstance == null)
                {
                    throw new AxHost.InvalidActiveXStateException("Application", AxHost.ActiveXInvokeKind.PropertyGet);
                }
                return this.ActiveXInstance.GetType().InvokeMember("Application", System.Reflection.BindingFlags.GetProperty, null, this.ActiveXInstance, null);


            }
        }

        [DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)]
        [DispIdAttribute(552)]
        public bool RegisterAsBrowser
        {
            get
            {
                if (this.ActiveXInstance == null)
                {
                    throw new AxHost.InvalidActiveXStateException("RegisterAsBrowser", AxHost.ActiveXInvokeKind.PropertyGet);
                }
                return (bool)this.ActiveXInstance.GetType().InvokeMember("RegisterAsBrowser", System.Reflection.BindingFlags.GetProperty, null, this.ActiveXInstance, null);


            }
            set
            {
                if (this.ActiveXInstance == null)
                {
                    throw new AxHost.InvalidActiveXStateException("RegisterAsBrowser", AxHost.ActiveXInvokeKind.PropertySet);
                }
                this.ActiveXInstance.GetType().InvokeMember("RegisterAsBrowser", System.Reflection.BindingFlags.SetProperty, null, this.ActiveXInstance, new object[]{value});
            }
        }

        [PermissionSetAttribute(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;// = (o, e) => { };

        protected virtual void OnNewWindow2(WebBrowserNewWindow2EventArgs e)
        {
            NewWindow2(this, e);
        }

        private class WebBrowser2EventHelper : StandardOleMarshalObject, DWebBrowserEvents2
        {
            private WebBrowserEx parent;

            public WebBrowser2EventHelper(WebBrowserEx parent)
            {
                this.parent = parent;
            }

            public void NewWindow2(ref object ppDisp, ref bool cancel)
            {
                var e = new WebBrowserNewWindow2EventArgs(ppDisp);
                this.parent.OnNewWindow2(e);
                ppDisp = e.ppDisp;
                cancel = e.Cancel;
            }
        }
    }

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

    public class WebBrowserNewWindow2EventArgs : CancelEventArgs
    {
        public object ppDisp { get; set; }

        public WebBrowserNewWindow2EventArgs(object ppDisp)
        {
            this.ppDisp = ppDisp;
        }
    }

    [ComImport, Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    [TypeLibType(TypeLibTypeFlags.FHidden)]
    public interface DWebBrowserEvents2
    {
        [DispId(251)]
        void NewWindow2([InAttribute(), OutAttribute(), MarshalAs(UnmanagedType.IDispatch)] ref object ppDisp, [InAttribute(), OutAttribute()] ref bool cancel);
    }
}
YASさん、早急な回答ありがとうございます。
No.3に記載されたコードで別タブで無事開くことができました。

現在作成しているのは、別ウィンドウの項目選択小窓で選択した結果を親ウィンドウにもどすというものでして…
ログインを必要としており、IEで開くためセッション切れを起こすという問題が突破できず詰まっておりました。

次の目標はスクリプトのwindow.close()の検知してタブを閉じることです。

また皆様方の知恵をお借りすることがあるかもしれませんが、またよろしくお願いします。
このたびは本当にありがとうございました。
解決済み!
> 次の目標はスクリプトのwindow.close()の検知してタブを閉じることです。

以前私も同じようなことで悩みました。VBですが,Webページにまとめましたので,参考にしてください。

http://homepage1.nifty.com/yasunari/VB/VB2005/WebBrowserWindowClosingEvent.htm

DOBON.NET | プログラミング道 | プログラミング掲示板