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プロジェクトを参照してください。
という事で以上です。
それではまた!