SWTのBrowserコンポーネント拡張のコツ2
2009年3月 3日(火) 17:01 JST
SWTのBrowserコンポーネント拡張のコツ からの続き拡張BrowserでのHTML取得の実装例 というところを参考に、
- ブラウザが取得したHTMLソースを横取りして、
- いろいろgrepやら加工やらして、
- 自動でちょちょいと操作しちゃおう
フレームで割ってあるような場合、OLEを使用してframeオブジェクトするまではいいんですが、
そこからそのフレームのinnnerHTMLがどうしても取れなくて泣きそうな今日この頃。
フレームで分割されたページのソースを取得するにはどうするか、
それは、任意のタイミングで、
browser.execute("top.window.status=top.frames[0].document.body.innerHTML");
でステータスバーにフレームのソースを転送(JavaScript)して、
browser.addStatusTextListener( new StatusTextListener() {
public void changed(StatusTextEvent event) {
System.out.println(event.text);
}
});
ステータス変化を捕らえるリスナを自分(ブラウザクラス)に登録していただく、という方法で、ゲット。
フレーム数だけstatusがあるようで、リスナが多重にイベントを受け取ってしまうので注意。
ただ、browserクラスはたいていスレッドでコマンド実行するので、
多重に受けとってもいいようにしておくのがベスト。)
JavaScriptで、window.status="コマンド";
とステータス表示を変更した場合、続けて、window.status=""とやってクリアしておかないと、
どうもいつまでもイベントリスナが反応してしまうようです。
たとえばこうするといいと思います。
<input type="button" onClick="windows.status='some.commandcommand'; window.status=''; " >
MSDNを見ていたら、IE8以降になると、
frameオブジェクトから直接getDocumentできるようになるようなことが書いてあったので、
とりあえずそういう時期になったらSWTももっと便利になっているでしょうから、
今はこれ(ステータスバー経由)でいいのだ
↓ブラウザクラスを単純に継承してHTMLのソースを取得するクラスを作ったので、
↓下に書いておきます。(ほとんど上のリンク先のと同じです・・・)
public class BrowserEx extends Browser {
public BrowserEx(Composite parent, int style) {
super(parent, style);
}
protected void checkSubclass() {
// kill subclass check.
}
public String getText() {
OleAutomation auto=null;
try {
Class c = this.getClass().getSuperclass();
Field f = c.getDeclaredField("auto");
f.setAccessible(true);
auto = (OleAutomation)f.get(this);
} catch ( NoSuchFieldException nsfe) {
nsfe.printStackTrace();
} catch ( IllegalAccessException iae) {
iae.printStackTrace();
}
checkWidget();
String htmlText = null;
// documentオブジェクト(IHTMLDocument3インタフェース)を取得する
int[] rgdispid = auto.getIDsOfNames(new String[] {"Document"});
Variant varResult = auto.getProperty(rgdispid[0]);
if ((varResult != null) && (varResult.getType() != OLE.VT_EMPTY)) {
OleAutomation htmlDocument = varResult.getAutomation();
varResult.dispose();
// documentElement(IHTMLElementインタフェース)を取得する
rgdispid = htmlDocument.getIDsOfNames(new String[] {"documentElement"});
if (rgdispid != null) {
varResult = htmlDocument.getProperty(rgdispid[0]);
if ((varResult != null) && (varResult.getType() != OLE.VT_EMPTY)) {
OleAutomation htmlElement = varResult.getAutomation();
varResult.dispose();
// outerHTMLを取得する
rgdispid = htmlElement.getIDsOfNames(new String[] {"outerHTML"});
if (rgdispid != null) {
varResult = htmlElement.getProperty(rgdispid[0]);
if ((varResult != null) && (varResult.getType() != OLE.VT_EMPTY)) {
htmlText = varResult.getString();
}
}
htmlElement.dispose();
}
}
htmlDocument.dispose();
}
return htmlText;
}