Webページの表示完了を知りたい

解決


Kenny  2010-10-01 20:19:16  No: 39271  IP: 192.*.*.*

D7にて、TWebBrowserを使って簡単なWebブラウザを作っています。
Webページを読み込んで表示を完了したときにある処理をしたいのですが、どのようにしてそのタイミングを取ればよいのか分かりません。
新規のページを読み込んだときにはOnCommandStateChange イベントが発生し、表示完了後にCSC_UPDATECOMMANDSが来るのでそれを利用しているのですが、Refreshメソッドで更新したときには表示完了後にOnCommandStateChange イベントが発生しないようです。
目的としては一つのWebページを表示し、定期的に表示更新し、ページを保存したいのです。

編集 削除
Quest  2010-10-01 21:30:08  No: 39272  IP: 192.*.*.*

OnDocumentCompleteイベントはどうですか?
ただ、こちらバージョンはDelphi2007ですが。

編集 削除
Kenny  2010-10-02 11:07:34  No: 39273  IP: 192.*.*.*

Questさん、ありがとうございます。
OnDocumentCompleteイベントも試してみたのですが、新規ページの読み込み表示が完了したときには
イベントが起こりますが、Refreshでは起きないようです。
一度別のページに移動してすぐに戻ると、表示完了後OnDocumentCompleteイベントが起きますから、
Refreshしても更新すべき内容がない時にはイベントが起きない、と言うことなのかも知れません。
ステータスバーに「ページが表示されました」と表示されるタイミングを知りたいだけなんですけど…。
愚直にOnStatusTextChange で  if Text='ページが表示されました' then 〜とやると取るには取れますが
不具合もありますし、あまりにもお馬鹿な気がして(^-^;

編集 削除
 2010-10-02 18:27:34  No: 39274  IP: 192.*.*.*

試してないが、busyプロパティは?

while IE.busy do begin
  application.processmessages;
end;
showmessage('');

編集 削除
Kenny  2010-10-03 00:12:58  No: 39275  IP: 192.*.*.*

あ さん、ありがとうございます。試しにこんな風にしてみました。

procedure TForm1.WebBrowser1CommandStateChange(Sender: TObject;
  Command: Integer; Enable: WordBool);
begin
  if WebBrowser1.busy=false then
    MessageBeep(MB_ICONASTERISK)
  else
    MessageBeep(MB_ICONEXCLAMATION);
end;

ステートが変わると音で分かるのですが、サイトによって上手く機能したりしなかったりしますね。
キャッシュとか、CGIの実行待ちとか、色々あるのかも知れません。

今はとりあえずチェックしたいときだけタイマーを回して、1秒ごとにReadyState=READYSTATE_COMPLETEを
チェックするようにしていますが。

編集 削除
 2010-10-04 21:33:15  No: 39276  IP: 192.*.*.*

>OnDocumentCompleteイベントも試してみたのですが、新規ページの読み込み表示が完了したときには
>イベントが起こりますが、Refreshでは起きないようです。

これは本当ですか?当方では起こってるように見えますが。

procedure TForm1.Button2Click(Sender: TObject);
begin
  WebBrowser1.Refresh;
end;

procedure TForm1.WebBrowser1DocumentComplete(Sender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
begin
  ShowMessage('');
end;

編集 削除
Kenny  2010-10-04 22:32:00  No: 39277  IP: 192.*.*.*

あ さん、ありがとうございます。
先にも書きましたが、サイトの内容によって振る舞いが違うようで、例えばgoogleであれば望んだ動作になります。
上手く動作しないサイトのURLを出せればいいのですが、仕事の関係するあまり公開していないURLですので、
同じように上手く動作しない、公開されているサイトを探して報告しますので、しばらくお待ち頂ければ感謝です。

編集 削除
monaa  2010-10-05 09:41:27  No: 39278  IP: 192.*.*.*

書きたくてウズウズしてたので書き込みます。

そもそも、目的の動作がNavigateなんだから、
ボタンはRefreshって書いても、同じページをNavigateしちゃえばいいだけじゃないですかね?
Refreshは仕様上DownloadCompleteしか発生しないものですから。
旧式のブラウザならともかく、今時のブラウザはNavigateでも更新されますよ。

編集 削除
monaa  2010-10-05 09:49:27  No: 39279  IP: 192.*.*.*

全然だめでした。
書き込む前にテストするんだった…

編集 削除
Kenny  2010-10-07 12:27:41  No: 39280  IP: 192.*.*.*

monaaさん、いつぞやは大変お世話になりました。

Refreshの代わりにNavigateというのは確かにその通りですね。頭が固まっていました。
ただどちらにしても、フレームページでは何度もDocumentCompleteが発生するので、何か考えないと
だめですね。当たり前ですが。
Webサイトの作りも無数に種類があるので、とりあえず社内用だけに使えればよいと言う方針で、一応
タイマーを使う方法で解決としておきます。
皆さんありがとうございました。

編集 削除
みかん、伊予柑  2010-10-07 17:03:36  No: 39281  IP: 192.*.*.*

>Refreshの代わりにNavigateというのは確かにその通りですね。頭が固まっていました。
>ただどちらにしても、フレームページでは何度もDocumentCompleteが発生するので、何か考えないと
>だめですね。当たり前ですが。

フレームを使用してるWEBページでの対策ならば、

procedure TForm1.WebBrowser1DocumentComplete(Sender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
var
  CurWB: IWebBrowser;
  TopWB: IWebBrowser;
  sName: string;
begin
  CurWB := pDisp as IWebBrowser;
  TopWB := (Sender as TWebBrowser).ControlInterface;
  sName := OleVariant(CurWB.Document).ParentWindow.Name;
  if CurWB <> TopWB then begin
    // サブフレーム読み込み(まだミカン)
    Memo1.Lines.Add(' SubFrame:'+ sName);
  end else begin
    // 全フレーム読み込み、いよ!完(イヨカン)だね
    // …ページ表示完了時の処理…
    Memo1.Lines.Add('MainFrame:'+ sName);
  end;
end;

編集 削除
Kenny  2010-10-08 16:57:13  No: 39282  IP: 192.*.*.*

みかん、伊予柑さん、ありがとうございます。サンプルコード、参考にさせて頂きます。
WebBrowserを使うのが初めてなので、四苦八苦しています…。

編集 削除