The Web Browser control has a mind of its own when you stick it onto a form with most ActiveX environments and especially inside of Visual FoxPro. I’m using the control both for previews and HTML editing in Help Builder and while it works OK, coercing it to behave like a proper control takes some work.
The most annoying problem I’ve had for a while is that the control displays at some default position in the container it is hosted on when first loaded. You see a white flashing rectangle briefly before the control can be resized.
I’ve tried all sorts of different things:
- Initializing the form with right coordinates to start with in the Form’s Init
- Assigning the top and left in the constructor
- Using LockScreen to keep the form from updating its display
- Hiding the container briefly, then showing it after the resize is complete
None of them worked. Even the last option which temporarily hides the container then redisplays it once the control is on it didn’t work. The control flashes ONTOP of the container and shows in the window!
Anything set in code prior to displaying the control – setting top, left, width and height also had no effect until the control becomes visible. The problem is that the control loads relatively slowly so you see a visible flicker of the WB control loading in a default position then ‘snapping’ into its real position.
Well, eventually I stumbled on the solution which is to set the control’s base properties to a width of 0 and height 0. Surprisingly this worked where assignments from the Init of the control did not. Now the Web Browser control still misbehaves but it does so ‘invisibly’.
Note that when you do this you have to still resize the browser at some point and adjust one of the size/location parameters AFTER the control has been made visible. Otherwise the control will not show the new location. Talk about a buggy implementation.
I’ve been struggling with a few issues in Help Builder and the HTML Edit mode when this came up again. One other problem in edit mode is that if you edit the document and navigate off IE prompts you to save the document. I couldn’t find a way around this problem so the easiest solution I could find was to simply remove the control and reload it – this is where the above comes in – more flicker because this loading unloading now happens a little more frequently. Surprisingly the overhead of unloading/reloading is minor once the visual nastiness has been removed.
Here’s the code that demonstrates how I now do this:
FUNCTION SetViewMode
LPARAMETER lnMode
LOCAL loHelp, llError, loEdit
loHelp = ThisForm.oHelp
IF lnMode = 2
*** If the control exists already remove it!
IF VARTYPE(this.Parent.oHtmlEdit) == "O"
this.Parent.RemoveObject("oHtmlEdit")
ENDIF
TRY
THIS.parent.AddObject("oHTMLEdit","wwBrowser_editor",;
this.left,this.top,this.Width,this.height)
CATCH
llError = .t.
ENDTRY
IF llError
THIS.SetViewMode(1)
WAIT WINDOW "Can't set control into WYSIWYG edit mode..." nowait
RETURN
ENDIF
loEdit = THIS.parent.oHTMLedit
loEdit.visible = .T.
*** Force the resize from 0,0 height/width
loEdit.Height = THIS.height +1
loEdit.Height = THIS.height -1
*** Load the Html
THIS.UpdateHTMLEditDisplay()
THIS.nViewMode = 2
ELSE
this.nViewMode = 1
*** We're just in Text Mode - no need to switch
IF VARTYPE(this.Parent.oHtmlEdit) != "O"
RETURN
ENDIF
THIS.Parent.oHTMLEdit.visible = .F.
THIS.visible = .T.
THISFORM.lockscreen = .T.
*** Display the textbox and read data from Design Mode
THIS.SaveHTMLToText()
*** Try to pre-selelect the text in the edit control
LOCAL loRange, lnAt, lcSelectedHtml
loEdit = THIS.parent.oHTMLedit
loRange = loEdit.Document.Selection.CreateRange()
loParent = null
IF VARTYPE(loRange) = "O"
TRY
loParent = loRange.parentElement
CATCH
FINALLY
IF !ISNULL(loParent)
lcSelectedHtml = FixBasePath(loParent.outerHtml , loEdit.Document.Body)
lnAt =ATC(lcSelectedHtml,this.Value)
IF lnAt > 0
this.SelStart = lnAt
this.SelLength = LEN(lcSelectedHtml)
this.SetFocus()
ENDIF
ENDIF
ENDTRY
ENDIF
this.SetFocus()
THIS.parent.RemoveObject("oHTMLEdit")
THIS.nViewMode = 1
THISFORM.LockScreen = .F.
ENDIF