IE コンポーネントにおけるイベントの発生順序
一般化しづらいのですがあえて書くと,Navigate(URL) 後の基本的な流れは,こうです。
- BeforeNavigate2 イベント発生
- NavigateComplete2 イベント発生
- DocumentComplete イベント発生
- ProgressChange (Progress = 0, ProgressMax = 0) イベント発生(※)
2〜4の間に
- CommandStateChange イベント
- DownloadBegin イベント
- DownloadComplete イベント
- ProgressChange イベント
- TitleChange イベント
- StatusTextChange イベント
が順不同で発生します。
ちょっと複雑な例
アサヒコムのある記事の場合の例ですが,
BeforeNavigate2: http://www.asahi.com/life/update/(略) NavigateComplete2: http://www.asahi.com/life/update/(略) BeforeNavigate2: http://pagead2.googlesyndication.com/(略) NavigateComplete2: http://pagead2.googlesyndication.com/(略) DocumentComplete: http://pagead2.googlesyndication.com/(略) DocumentComplete: http://www.asahi.com/life/update/(略)
このように JavaScript で googlead を読み込んでいるのでそれらからもイベントが発生してしまいます。
それじゃ本当の DocumentComplete は?と思いますが,TWebBrowser の LocationURL にドキュメント全体の URL が入っている(そしてブレない)ので,それと比較すれば判定できるかと。
続いて msn の例ですが,
BeforeNavigate2: http://jp.msn.com/ NavigateComplete2: http://jp.msn.com/ BeforeNavigate2: about:blank BeforeNavigate2: about:blank BeforeNavigate2: about:blank BeforeNavigate2: about:blank BeforeNavigate2: about:blank BeforeNavigate2: about:blank BeforeNavigate2: about:blank BeforeNavigate2: about:blank DocumentComplete: http://jp.msn.com/ DocumentComplete: http://jp.msn.com/ DocumentComplete: http://jp.msn.com/ DocumentComplete: http://jp.msn.com/ DocumentComplete: http://jp.msn.com/ DocumentComplete: http://jp.msn.com/ DocumentComplete: http://jp.msn.com/ DocumentComplete: http://jp.msn.com/
これも JavaScript で読み込んでいるのですが非常に判断しにくい例です。下記追記参照。
最初 iframe 使うとそうなるのかな,と思ったのですが今の msn のページは iframe 使ってないようですし……Ajax で遅延ロードするとこうなるのかなぁ。
BeforeNavigate2 と DocumentComplete の数が対応してないのがちょっと困り者です。
お口なおし?でわかりやすい例として, google.com にアクセスして google.co.jp にリダイレクトされる例です。
BeforeNavigate2: http://www.google.com/ NavigateComplete2: http://www.google.co.jp/ DocumentComplete: http://www.google.co.jp/
NavigateComplete2 の時点でリダイレクト先の URI になっています。サイトによっては BeforeNavigate2 の時点でもリダイレクト先になっていたような……*1
ともかく,この場合 TWebBrowser.LocationURL は http://www.google.co.jp/ になっているのでやはりそちらと比較すればオーケー。
ProgressChange イベントについて
スタート時は ProgressMax が 10000 で,ドキュメントをある程度読み込むまではそのまま Progress がちょっとずつ増えていきます。が,ドキュメント読み込み後は臨機応変に ProgressMax も増えます。なので Progress rate がリニアに増えていくことを期待してはいけません。また,まれに Progress > ProgressMax になるときもありますし。
Progress == -1 の時に読み込み終了,とドキュメントに書いてあります。経験上,上の Step 4 のように(↑※参照),ドキュメントを完全に読み込み終えた時点で Progress = 0, ProgressMax = 0 のイベントが発生するようです(あくまで目安ということで*2)。
NavigationError 発生時のイベント順序
- BeforeNavigate2 イベント発生
- NavigateError イベント発生
- NavigateError イベント発生
- NavigateComplete2 イベント発生
- DocumentComplete イベント発生
NavigateError がダブっているのは打ち間違いではありません。エラー画面(ドキュメント)を表示する必要があるので,それらの都合で NavigateError イベントが複数回発生することもあります。
しかもエラー画面の表示時に NavigateComplete2 イベント/DocumentComplete イベントが発生するので最終段階だけではエラーとして判断しがたいことがあります。まぁ内的にフラグをもてばいいですし,もっと簡単にはイベントハンドラの Cancel 変数に True を渡すとそこで Navigate 処理が終了するのでその後のイベントは発生しません*3。
NavigateError イベントは Status コードを付随しますが,VT_I4(vtInteger)です。サーバサイドのエラーであれば,例えば 404 などのお馴染みのものです。クライアントサイドのエラー(DNS lookup 失敗等)には Status コードは $80000000 みたく 32bit 数値になります。これらについては SDK のドキュメント参照。
このドキュメントのステータスを後から取得する方法がありそうなものですが……みつかりませんでした。DOM 系のプロパティで何かありましたっけ?
追記 2007/09/26
引数pDispがTWebBrowserのApplicationプロパティと一致する場合、そのページは最上位のフレーム(Topのフレーム)であると判定できます。
... snip ...
フレームが使われたページでは、各フレームごとにこのイベントが発生しますが、完了した順に発生するため最上位のフレームは一番最後にこのイベントが発生します。
http://griffy.pekori.to/soft/technologies.html
あーこれでいけました。