Board index » cppbuilder » TccpWebBrowser event problem

TccpWebBrowser event problem


2007-04-27 11:34:23 PM
cppbuilder63
Hi,
I added a form with a TccpWebBrowser to my application to show some news
at start-up.
I try to use the OnNavigateError to check if it is possible to load the
html news page from the server. If not I want to load a page from the
local app directory to inform the user that he must be online to read
the news.
I tried the following code:
void __fastcall TFormNews::LoadPage(const WideString url, const
WideString local_url)
{
LocalURL = local_url;
CppWebBrowser1->Navigate(url);
CppWebBrowser1->Refresh();
if (!FConnected)
CppWebBrowser1->Navigate(LocalURL);
ShowModal();
}
The event handler of OnNavigateError sets the FConnect to false:
void __fastcall TFormNews::CppWebBrowser1NavigateError(TObject *Sender,
LPDISPATCH pDisp, Variant *URL, Variant *Frame, Variant *StatusCode,
VARIANT_BOOL *Cancel)
{
// test if event is fired
if (*Cancel)
ShowMessage("Cancel = true");
else
ShowMessage("Cancel = false");
FConnected = false;
}
Refresh() fires the OnNavigateError event but FConnect is not set to
false if the program reaches the if-statement. If I include a
ShowMessage("Stop!") between the Refresh() and the if-statement then all
works fine! I see from the ShowMessage windows that ShowMessage("Stop!")
arrives before the ShowMessage from the OnNavigateError event handler.
How can I tell the program to wait until the OnNavigateError event
handler has finished? Or is there another solution?
First I didn't insert the Refresh(), then OnNavigateError event is fired
only by ShowModal(), not by Navigate()!!
Thank in advance for any help.
Kind regards
Rolf
 
 

Re:TccpWebBrowser event problem

"Rolf Fankhauser" < XXXX@XXXXX.COM >wrote in message
Quote
void __fastcall TFormNews::LoadPage(const WideString url, const
WideString local_url)
You should pass those parameters by const reference instead:
void __fastcall TFormNews::LoadPage(const WideString &url, const
WideString &local_url)
Quote
CppWebBrowser1->Navigate(url);
CppWebBrowser1->Refresh();
Navigate() is an asynchronous operation, running in the background.
You have to wait for the events to be triggered in order to know
whether it succeeded or not. You are not waiting for the events, so
you are accessing it too soon after Navigate() exits.
Try this instead:
WideString LocalURL;
bool LoadingLocal;
void __fastcall TFormNews::LoadPage(const WideString &url, const
WideString &local_url)
{
LocalURL = local_url;
LoadingLocal = false;
CppWebBrowser1->Navigate(url);
}
void __fastcall TFormNews::CppWebBrowser1NavigateError(TObject
*Sender, LPDISPATCH pDisp, Variant *URL, Variant *Frame, Variant
*StatusCode, VARIANT_BOOL *Cancel)
{
if( !LoadingLocal )
{
// error loading remote url, load local file next...
LoadingLocal = true;
CppWebBrowser1->Navigate(LocalURL);
}
else
// error loading local file...
}
void __fastcall TFormNews::CppWebBrowser1DocumentComplete(TObject*
Sender, LPDISPATCH pDisp, TVariant *URL)
{
ShowModal();
}
Quote
Refresh() fires the OnNavigateError event but FConnect is not
set to false if the program reaches the if-statement.
Because the event hasn't actually been triggered yet by the time that
'if' statement is reached.
Quote
If I include a ShowMessage("Stop!") between the Refresh() and
the if-statement then all works fine!
ShowMessage() displays a modal TForm. TForm::ShowModal() internally
runs a secondary message queue until the TForm is closed. By calling
ShowMessage(), you are allowing the TCppWebBrowser a chance to process
the pending messages it needs to trigger its events. Without the
ShowMessage(), no message processing is being performed in your code.
Which is why I changed your code in my example above to make
LoadPage() always exit immediately, in order to return control to the
main message queue and allow the normal flow of message processing to
occur.
Gambit
 

Re:TccpWebBrowser event problem

"Rolf Fankhauser" < XXXX@XXXXX.COM >wrote in message
Quote
Thanks for your solution. I see the point. But from my tries so far
I recognized that Navigate() didn't fire the OnNavigateError event
in any case. I had to add Refresh().
Works fine for me without Refresh().
Quote
But In the meantime I solved the problem by adding a TTimer.
After loading the page the program waits 500 ms to be sure that
the event handler of OnNavigateError is finished.
That is a very bad and inaccurate approach to this issue. I already
told you how to make it work properly. The TTimer only masks the
issue, it does not solve it.
Gambit
 

{smallsort}

Re:TccpWebBrowser event problem

Remy,
Thanks for your solution. I see the point. But from my tries so far I
recognized that Navigate() didn't fire the OnNavigateError event in any
case. I had to add Refresh().
But In the meantime I solved the problem by adding a TTimer. After
loading the page the program waits 500 ms to be sure that the event
handler of
OnNavigateError is finished. After that FConnect is correctly set.
I didn't try if I can wait a shorter time but it works. Your solution
would be better.
void __fastcall TFormNews::LoadPage(const WideString &url, const
WideString &local_url, double *last_read, bool read_always, bool
*read_first)
{
ReadFirst = read_first;
ReadAlways = read_always;
LocalURL = local_url;
NewsLastRead = last_read;
CppWebBrowser1->Navigate(url);
CppWebBrowser1->Refresh();
Timer1->Enabled = true;
}
//---------------------------------------------------------------------------
// after waiting until the event handler of OnNavigateError is finished
void __fastcall TFormNews::Timer1Timer(TObject *Sender)
{
Timer1->Enabled = false;
if (!FConnected)
{
if (!ReadAlways)
if (!*ReadFirst)
return;
else
{
CppWebBrowser1->Navigate(LocalURL);
*ReadFirst = false;
CppWebBrowser1->Refresh();
}
}
else
if (!ReadAlways) // if Help / News chosen
if (!NewsAreAdded(NewsLastRead)) return;
ShowModal();
}
 

Re:TccpWebBrowser event problem

Remy Lebeau (TeamB) wrote:
Quote
"Rolf Fankhauser" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...


>Thanks for your solution. I see the point. But from my tries so far
>I recognized that Navigate() didn't fire the OnNavigateError event
>in any case. I had to add Refresh().


Works fine for me without Refresh().

Perhaps there was another error in my code!

>But In the meantime I solved the problem by adding a TTimer.
>After loading the page the program waits 500 ms to be sure that
>the event handler of OnNavigateError is finished.


That is a very bad and inaccurate approach to this issue. I already
told you how to make it work properly. The TTimer only masks the
issue, it does not solve it.

I implemented the TTimer before I saw your reply. I will implement your
solution. Thanks again!
Quote

Gambit


 

Re:TccpWebBrowser event problem

I implemented your solution but the OnDocumentComplete event does not
fire in both cases (remote and local loading). So no form is shown.
Did I forget to set a special property of TCppWebBrowser?
I use CBuilder 6, IE 7 and Windows XP.
Remy Lebeau (TeamB) wrote:
Quote
"Rolf Fankhauser" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...


>Thanks for your solution. I see the point. But from my tries so far
>I recognized that Navigate() didn't fire the OnNavigateError event
>in any case. I had to add Refresh().


Works fine for me without Refresh().


>But In the meantime I solved the problem by adding a TTimer.
>After loading the page the program waits 500 ms to be sure that
>the event handler of OnNavigateError is finished.


That is a very bad and inaccurate approach to this issue. I already
told you how to make it work properly. The TTimer only masks the
issue, it does not solve it.


Gambit


 

Re:TccpWebBrowser event problem

I use now the OnNavigateComplete2 event instead of the
OnDocumentComplete event. There remains one little problem:
If LoadPage() is called in off-line mode (local page is loaded) a second
time (it is called at start-up and can be called by a menu item) then an
empty form is shown. If this form is closed, the form is shown again
with the right contents.
This doesn't happen on-line (if the remote page is loaded).
void __fastcall TFormNews::CppWebBrowser1NavigateComplete2(TObject *Sender,
LPDISPATCH pDisp, Variant *URL)
{
if (!ReadAlways) // at start-up
if (LoadingLocal) {
if (!*ReadFirst)
return; // already shown
else
*ReadFirst = false;
}
else
if (!NewsAreAdded(NewsLastRead))
return;
ShowModal();
}
ReadAlways is true if LoadPage is invoked by the menu item.
ReadFirst is true if the local page is never shown at start-up.
NewsAreAdded() checks if the update date of the remote page is newer
than the date of the last reading of the remote page. This prevents
multiple display of the news form at start-up if news haven't changed.
Rolf Fankhauser wrote:
Quote
I implemented your solution but the OnDocumentComplete event does not
fire in both cases (remote and local loading). So no form is shown.

Did I forget to set a special property of TCppWebBrowser?

I use CBuilder 6, IE 7 and Windows XP.

Remy Lebeau (TeamB) wrote:

>"Rolf Fankhauser" < XXXX@XXXXX.COM >wrote in message
>news: XXXX@XXXXX.COM ...
>
>
>>Thanks for your solution. I see the point. But from my tries so far
>>I recognized that Navigate() didn't fire the OnNavigateError event
>>in any case. I had to add Refresh().
>
>
>
>Works fine for me without Refresh().
>
>
>>But In the meantime I solved the problem by adding a TTimer.
>>After loading the page the program waits 500 ms to be sure that
>>the event handler of OnNavigateError is finished.
>
>
>
>That is a very bad and inaccurate approach to this issue. I already
>told you how to make it work properly. The TTimer only masks the
>issue, it does not solve it.
>
>
>Gambit
>
>
 

Re:TccpWebBrowser event problem

Remy Lebeau (TeamB) wrote:
Quote
"Rolf Fankhauser" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...


>Thanks for your solution. I see the point. But from my tries so far
>I recognized that Navigate() didn't fire the OnNavigateError event
>in any case. I had to add Refresh().


Works fine for me without Refresh().


>But In the meantime I solved the problem by adding a TTimer.
>After loading the page the program waits 500 ms to be sure that
>the event handler of OnNavigateError is finished.


That is a very bad and inaccurate approach to this issue. I already
told you how to make it work properly. The TTimer only masks the
issue, it does not solve it.


Gambit


I implemented your approach but the problem is that if the remote site
is not reachable (I have this situation at the moment) that the event
NavigateError is not fired! So nothing happens.
Rolf