TWebBrowser コンポーネントを使う
今更〜〜〜ですが,必要にせまられて作ってたら忘れそうなのでメモメモ。
Delphi で IE コンポーネントを使うなら下記のサイトがまとまってます。
ま,TWebBrowser とか IWebBrowser2 とかでググると今でも結構たくさんのページがヒットしますんで。
(上記ページでも言及されていますが)そのまま TWebBrowser を使うといろいろ不具合があります。対処法もいろいろあるのですが,面倒なら下記の TUIWebBrowser コンポーネントを使うと楽らしいです(今回の案件では使いませんでした)。
GET じゃなく POST で Navigate したい
Navigate(URL, Flags, TargetFrameName, PostData, Headers) という引数のプロシージャがあるので PostData に適切に設定すれば POST になる……のですが,ヘッダの Content-Type に application/x-www-form-urlencoded を指定するのを忘れてはいけません。たぶん Content-Length も指定したほうがいいかも。
試してみて色々気をつけるべきことを書きました⇒TWebBrowser での POST - daily dayflower
読み込まれたドキュメントの DOM をいじりたい
例えば自動ログインとかのオートクルーズ機能をつけるときに DOM をプログラムから操作したくなりますよね。
DocumentComplete イベントが発生した後であれば,OleObject の Document プロパティに JavaScript でいうところの document オブジェクトが存在するので,JavaScript で DOM をいじるかのようにアレコレできます。実際には IHTMLDocument(1〜5)インタフェースを介するわけですが,Delphi なので透過的に扱えます。オートメーション万歳*1。
e := WebBrowser1.OLEObject.Document.documentElement.getElementById('ほげほげ');
とか。
オンメモリで作成した HTML を読み込ませたい
TWebBrowser.Document プロパティを IStream と見做して Load するのが正攻法といわれてますが(⇒http://www.monazilla.org/document/directwrite.html),正直めんどうくさいですよね。
先ほどの DOM の件を応用して考えると,
WebBrowser1.OLEObject.Document.documentElement.innerHTML := 'ほげほげ〜';
みたくすればいけるかなと思うのですが,このプロパティ,読込はできるんですが(⇒http://hpcgi1.nifty.com/MADIA/DelphiBBS/wwwlng.cgi?print+200511/05110006.txt)書込しようとすると
innerHTML プロパティを設定できませんでした。この操作に 対して無効なターゲット要素です。
と怒られてしまいます。
んで,解決策としては,まず about:blank に Navigate してやり,DocumentComplete イベントを待ちます。この時点で documentElemement.innerHTML は
<HEAD></HEAD> <BODY></BODY>
というブランクに非常に近いものになっているんですが,ここで WebBrowser1.OLEObject.Document.write(ほげほげ) してやると,上記の内容は消されて新しい html を表示することができます。
ただし,これ,実質 document.write(〜) を行っているようなものなので,連続して行うと,どんどん追記されてしまいます。なので新たに読み込みさせたい場合,その都度 about:blank に Navigate() してやる必要があります。結局この方法も面倒になってしまいました。
別に about:blank である必要はありませんでした。DocumentComplete イベント後,初回の Document.write() 時のみ,既存のドキュメントは上書きされます。
なお,body 要素の中だけ書き換えればいいのなら,Document.body.innerHTML であれば書込可能ですので,それが一番楽かも。
TWebBrowser を非表示にして色々やりたい
TWebBrowser を Visible := false にして使おうと思っても,NavigateComplete2 イベントは発生するものの,DocumentComplete イベントは発生しません。事実上使えないわけです。印刷とか。
で,対処法は,TWebBrowser コンポーネントを親コンポーネントから見えない領域に追いやってしまえばよいです。
- たとえば TWebBrowser コンポーネントを Width 800, Height 600 で作成
- Left を -800 とかにする(念のためもうちっと大きめなほうがいいかも)
- 親コンポーネント(フォーム等)の AutoScroll プロパティを false にする(フォームにスクロールバーが出てしまうため)
単純な仕組みですが思いつくのに半日かかりました。このへんをダイナミックにいじると,表示したり隠したりもできます。