Web Browser Control Flicker
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
Other Posts you might also like
- Adding minimal OWIN Identity Authentication to an Existing ASP.NET MVC Application
- Resolving Paths To Server Relative Paths in .NET Code
- Map Physical Paths with an HttpContext.MapPath() Extension Method in ASP.NET
- Back to Basics: Rewriting a URL in ASP.NET Core
- Getting the ASP.NET Core Server Hosting Urls at Startup and in Requests
The Voices of Reason
# re: Web Browser Control Flicker
Isn't there a Windows API equivalent of LockScreen that you could use while you're mucking with the web browser control?
DECLARE INTEGER LockWindowUpdate IN user32 INTEGER hWndLock
http://www.news2news.com/vfp/?group=-1&function=404 (definition)
http://www.news2news.com/vfp/?example=257&function=404 (example)
The following extracted from the above News2News.com URL's:
The LockWindowUpdate function disables or enables drawing in the specified window. Only one window can be locked at a time.
hWndLock [in] Specifies the window in which drawing will be disabled. If this parameter is NULL, drawing in the locked window is enabled.
Return value: If the function succeeds, the return value is nonzero. If the function fails, the return value is zero, indicating that an error occurred or another window was already locked.
When the drawing is disabled, whatever you do with controls on this form, you still have its image unchanged. You can still close this form by clicking on the Close button, which image will not change during the click.
This behaviour could possibly be useful for windowing controls (controls with window handles, as OLE controls) to disable their visual update for the time of performing some operations on them, like adding rows etc. Though this is only my assumption, needs to be tested.
# re: Web Browser Control Flicker
Two ideas:
(1) Use a timer to launch the window you want activated - in other words, instead of launcing the form immediately, start a timer that waits 0.5 seconds (that's a guess) AFTER your browser control has processed the click event, THEN launch the form you want launched.
- OR -
(2) Checkout news2news.com's window functions. You should be able to use the Windows API to set window focus to the appropriate form - possibly (???) with an optional delay as described above so that the web browser has completed its processing and won't try to be on top.
# re: Web Browser Control Flicker
Interesting idea but my guess that behind the scenes that's FoxPro is actually doing with Form.Locksreen and that doesn't work because the WB appently draws into it's own window - windowed control. The other issue I found is that if the Web Browser is not visible or locked it doesn't size properly. So at some point I have to make it visible with the wrong size and then resize it anyway whihc is apparently what gives the flicker.
The solution above of setting the control to 0 height and width works to eliminate the flicker, but to be sure it's a hack around a very ill behaved control.
# re: Web Browser Control Flicker