DocumentComplete N.O.E ??

Hi,
I have the following code in the DocumentComplete event of my HTMLViewer:

// HIDE THE PROGRESS WHEEL AS THE PAGE HAS NOW LOADED ProgressWheel1.visible = False

The problem is that if the user closes the window before the page has finished loading - the app crashes and I get a nil object exception on that line.

What code do I need to put in the Window.Close event, in order to prevent this?
I tried adding the same line of code in the Window.Close event, but I still get the same error.

Thank you all in advance.

Sounds like the Window gets closed but the HTMLViewer is still wired up and fires it’s event.

Try calling MyViewer.Cancel in the Windows Close event.

If that doesn’t work change your code to…

if ProgressWheel1 <> nil then ProgressWheel1.visible = False

Thanks Will - your first option works perfectly :slight_smile:
Much appreciated.

The real problem here is overlooked; namely, that you’re assuming that ProgressWheel1 <> nil. In fact, these control references can and do return nil in Open and Close event handlers of other controls and the containing window, depending on the platform.

Charles,
I’m using this line of code in the Windows Close event- so all seems ok.

MyViewer.Cancel

[quote=193554:@Richard Summers]Charles,
I’m using this line of code in the Windows Close event- so all seems ok.

MyViewer.Cancel

What if MyViewer returns nil?

Charles,
are you saying that MyViewer could return nil - even though there is definitely an HTMLViewer with that name in the window?
If that’s the case - how can anyone ever have a HTMLViewer in their app, if it’s possible it could randomly return nil?

The only solution I can see is this in the window.close event - but I’m sure this wouldn’t work :slight_smile:

If MyViewer = Nil then MyViewer.Cancel Else MyViewer.Cancel End If

I must be missing something obvious here?

Thanks.

[quote=193569:@Richard Summers]So are you saying that MyViewer could return nil - even though there is definitely an HTMLViewer with that name in the window?
If that’s the case - how can anyone ever have a HTMLViewer in their app?

I must be missing something obvious here?

Thanks.[/quote]

HTMLViewer closes before the Window close takes place. With some degree of bad luck, its destructor could have taken effect before you try to call Cancel.

You could simply do

If MyViewer <> Nil then MyViewer.Cancel end if

Thanks Michel,
However - If I put your code in the window.close event - MyViewer could still be nil.

Thus I’m in the same predicament :frowning:

Do you understand why you were getting a NilObjectException in your original post?

Charles,
my confusion regarding my original problem is this:

Basically, I would expect the HTMLViewer’s DocumentComplete event to only fire if the page loaded completely (hence the name).
However, if the user has closed the window before the page completely loaded - how is the DocumentComplete event still firing?

This makes absolutely no sense to me :frowning:

[quote=193578:@Richard Summers]Charles,
my confusion regarding my original problem is this:

Basically, I would expect the HTMLViewer’s DocumentComplete event to only fire if the page loaded completely (hence the name).
However, if the user has closed the window before the page completely loaded - how is the DocumentComplete event still firing?

This makes absolutely no sense to me :([/quote]

Hmmm; having poked around a bit I can see why. As best as I can determine from experiment, HTMLViewer.Cancel invokes the DocumentComplete event handler. My guess is that this is not a bug, but a gotcha.

So what you would need to do would be to add a private property LoadCanceled as Boolean to the window. Call HTMLViewer.Cancel in the CancelClose event handler, and set LoadCanceled to true before calling HTMLViewer.Cancel. Then you can check the value of LoadCanceled in the DocumentComplete handler.

What platform are you building for? For Mac OS, ProgressWheel1 is not nil when I check it in the HTMLViewer.DocumentComplete handler.

Charles,
I’m using OS X Yosemite.

Thanks for the help - I will try your recommendation :slight_smile:

Very much appreciated!

Charles,
I have done as you advised above, and created the property and also added the CancelClose event and code.

I now also have this code in the DocumentComplete event:

[code]// HIDE THE PROGRESS WHEEL AS THE PAGE HAS NOW LOADED
ProgressWheel1.visible = False

// ENABLE OR DISABLE THE PAGE BACK AND PAGE FORWARD BUTTONS
PageBackButton.Enabled = Me.CanGoBack
PageForwardButton.Enabled = Me.CanGoForward

// CHECK IF THE USER IS CLOSING THE WINDOW - IF SO - HIDE THE PROGRESS WHEEL
If LoadCancelled = True Then
// HIDE THE PROGRESS WHEEL
ProgressWheel1.visible = False
End If[/code]

All seems to be working now.
I can close the window whilst the page is still loading - with no crash.

Hopefully this is now fixed.

Here’s a demo of what’s happening (I speculate). When an HTMLViewer is loading a document, that’s like a different process that’ll stay alive by itself, like a Timer. When you close the Window it gets torn down but the HTMLViewer continues running it’s loading code and eventually triggers it’s DocumentComplete event handler.

So the Window is torn down but it isn’t nil. This HTMLViewer process is holding some reference keeping the Window instance alive and still invokes it’s event handler, which then runs with nil controls.

To replicate what I think the situation is I added a Timer as a Property of App with its Action handler being a Window method. Because the Timers handler now references the Window when you ‘close’ the Window it gets torn down but the instance is still there for the Timer. So 3 seconds later the Timer still fires on this Window, but it’s torn down, controls nil, exception.

[code]//push the button, close the window and wait a couple seconds

Timer1 As Timer //App Property

Window Window1

Sub Action() //PushButton1

if App.Timer1 = nil then
  App.Timer1 = new Timer
  App.Timer1.Period = 3000
  AddHandler App.Timer1.Action, AddressOf TimerAction
end

App.Timer1.Mode = Timer.ModeSingle

End Sub

Sub TimerAction(sender As Timer) //Method
PushButton1.Top = PushButton1.Top + 10
End Sub

End Window[/code]

Note the crash won’t happen with a Timer placed on a Window. Appears a Timers Close event properly stops it running, which is what HTMLViewer isn’t doing and you have to manually do yourself in Window.Close.

Cool.
Thank you both for all the information - I really appreciate all the help and advice.