IDocHostUIHandlerを実装してみることに。
2002/01/30でも書いたように、ATL側で実装してある、IDocHostUIHandlerは、IAxWinHostWindow::SetExternalUIHandlerで設定したUIHandlerに呼び出しを委譲してくれる。が、よくよく見てみたら、IDocHostUIHandlerではなくて、IDocHostUIHandlerDispatchを実装しなくてはいけないらしい。IDocHostUIHandlerDispatchはATL固有のインターフェイスで、IDispatchの派生で、引数なども全てDispatch互換のものになっている。でも、ATL側からはIDispatch::Invoke経由ではなくて、vtble経由で呼ばれる。謎だ。
というわけで、IDocHostUIHandlerDispatchを実装。で、AtlAxGetHostで取得したIUknownからQueryInterfaceでIAxWinHostWindowを取得して、SetExternalUIHandlerで設定する。確かに呼び出してくれた。
でも、本来の目的は、IDocHostUIHandler(Dispatch)::OnDocWindowActivateで、ウィンドウがアクティブになったことを知りたかったんだけど、なぜか呼ばれない。これって、ActiveXコントロール的にアクティベイトされたときにしか呼ばれないのか?。IOleInPlaceActiveObject::OnDocWindowActivateの説明を見るとMDIの時に呼ばれるのか。
しょうがないので、アクティブかどうか(フォーカスがあるかどうか)は、現在のフォーカスを持っているウィンドウが、ホストウィンドウの子ウィンドウかどうかで判断するようにした。
さらに、IHTMLDocument::open, write, closeを使ってドキュメントを書き込むと、コントロールが勝手にフォーカスを持っていってしまうことが発覚。んー、どうしたもんか。
IDocHostUIHandler(Dispatch)::GetHostInfoで、リンクをクリックしたときの動作などをカスタマイズできるので、リンクをクリックしたときは別のフレームで表示することにした。が、実はこれはIAxWinAmbientDispatch::put_DocHostFlagsで設定できることが発覚。わざわざIDocHostUIHandlerDispatchをインプリした意味ないじゃん。。。
上に書いたように、IDocHostUIHandlerDispatch::GetHostInfoで、DOCHOSTUIFLAG_OPENNEWWINをセットしているにもかかわらず、リンクをクリックすると新しいウィンドウが開かずに今のウィンドウ内でブラウズしてしまう。メソッド自体は呼ばれているのに。
さらに、リンクをクリックした場合にも、IInternetProtocolのフックが有効になっていることが発覚。でも、これはE_FAILを返しておけば勝手にデフォルトが使われるみたい。エラーページ(res://...)だとデフォルトが使われないのは、あれもPluggable protocol handlerで処理しているからか?