WebBrowserコントロールを利用している際に、JavaScriptでopenメソッドを呼ばれるなどで新しいWindowを開かれるとポップアップでIEが開かれてしまい、制御がプログラムから外れてしまいます。
本エントリーでは新しいWindowが開かれる前にイベントをインターセプトする方法を記載します。
MSHTMLインターフェースのDWebBrowserEventsを利用することでハンドルします。
まずは「Microsoft Internet Controls」のCOMの参照を追加します。

で、以下のようにWebBrowserのLoadCompleteイベントでDWebBrowserEventsのNewWindowイベントにイベントハンドラを追加します。
private bool isInitialized = false;
private void WebBrowser_LoadCompleted(object sender, NavigationEventArgs e)
{
if(!isInitialized)
{
IServiceProvider serviceProvider = (IServiceProvider)webBrowser.Document;
Guid serviceGuid = new Guid("0002DF05-0000-0000-C000-000000000046");
Guid iid = typeof(SHDocVw.IWebBrowser2).GUID;
SHDocVw.DWebBrowserEvents_Event wbEvents = (SHDocVw.DWebBrowserEvents_Event)serviceProvider.QueryService(ref serviceGuid, ref iid);
wbEvents.NewWindow += OnNewWindow;
isInitialized = true;
}
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("6d5140c1-7436-11ce-8034-00aa006009fa")]
private interface IServiceProvider
{
[return: MarshalAs(UnmanagedType.IUnknown)]
object QueryService(ref Guid guidService, ref Guid riid);
}
上記のサンプルでは、OnNewWindowというメソッドをハンドラとして追加しています。
あとはイベントを受け取ったら好きなように処理すればOKです。
以下にイベントを受ける際のサンプルも一応載せておきます。
private void OnNewWindow(string URL, int Flags, string TargetFrameName, ref object PostData, string Headers, ref bool Processed)
{
Processed = true;
webBrowser.Navigate(URL);
}
上の例では、Processedにtrueを設定することで、ブラウザのイベントをキャンセルし、ポップアップで開くよう指定されたURIに画面を遷移させています。
他にはタブブラウザ的にアプリ内で別のWebBrowserを開いてそちらで開くとかが、動作としてはありそうなパターンですね。
一応動くコードをGithubに上げておきます。
WebBrowserSampleソリューションのHandleNewWindowBrowserプロジェクトを参照してください。
という事で以上です。
それではまた!