物置き

IHTMLFrameElementからIHTMLDocument2を得る

IEのウインドウハンドルを、いろいろごにょごにょすると、
そのIE上で表示しているHTMLに対応したIHTMLDocument2オブジェクトを得ることができる。
このオブジェクトから、IE上で表示しているHTMLデータ構造にアクセスすることができる。


でも、フレーム表示しているページの場合、フレーム内のドキュメントは別のオブジェクトとなっており、
これを取得するには、一手間必要。
調べた結果、下記の手順で取得することに成功したのでメモ。

#include <mshtml.h>
#include <comdef.h>
// (中略)...

	// doc(IHTMLDocument2*)はあらかじめ取得済みであるものとする。
	IHTMLElementCollection* col = NULL;
	doc->get_all(&col);
	// doc内のHTML要素を一つずつ調べる
	long elems;
	col->get_length(&elems);
	for (long i = 0; i < elems; ++i) {
		IDispatch* disp;
		col->item(_variant_t(i), _variant_t(), &disp);
		
		IHTMLFrameBase2* frame = NULL;
		disp->QueryInterface(IID_IHTMLFrameBase2, (void**)&frame);
		disp->Release();
		if (frame==NULL) {
			continue;	// frame以外の要素はここでは対象外とする
		}
		IHTMLWindow2* wnd = NULL;
		frame->get_contentWindow(&wnd);
		frame->Release();
		if (wnd==NULL) {
			continue;	// たぶんここは失敗しないはず..
		}
		IHTMLDocument2* frameDoc = NULL;
		wnd->get_document(&frameDoc);
		// frameDocはフレーム内のHTMLドキュメントオブジェクト
	}

(2008-12-11追記)
上記の方法だと、フレーム内のページが外部にある場合に取得することができない。
(get_documentで得られる値がNULLになる。の戻り値でエラー値が返る。上のコードだとチェックしてないけど..)
調べてみたところ、どうもIEの仕様により制限されている模様。


http://support.microsoft.com/default.aspx?scid=kb;ja;167796


じゃあしょうがないすね。おわり。
(追記おわり)


なんか、IEとかSleipnirでも、Vimperatorみたいなクイックヒント表示ができそうな感じ。
まだ一部のコントロールしか対応できてないけど、リンクにヒントを表示してページ遷移することができた。
こんな感じ。


しかし、そんな需要はあるのだろうか。
そもそもクイックヒントモードが使いたかったら、最初からVimperator使ってるわな..