javascriptvb6webbrowser-controlminimizedvisibilitychange

document.hidden is incorrectly false when used in a WebBrowser control


I want to detect when a window is minimized in JavaScript, so I am using document.hidden. In the below snippet, click "Start" and minimize the window by clicking the minimize button, toggling the application icon in the taskbar, using Win + Down Arrow, using Win + D, etc.

When the window is minimized, you will see "hidden" appear in the textarea.

var startButton = document.getElementById("start");
var stopButton = document.getElementById("stop");
var ta = document.getElementById("ta");

var id;
startButton.onclick = function() {
	id = setInterval(function() {
		ta.value += document.hidden ? "hidden\n" : "visible\n";
	}, 1000);
};

stopButton.onclick = function() {
	if (id) clearInterval(id);
};
<button id="start">Start</button>
<button id="stop">Stop</button>
<br />
<textarea id="ta" cols="50" rows="20"></textarea>

No issues there.

However, I am hosting this JS code in VB6.

I have created a simple project with a form with a WebBrowser control and a CommandButton. My only code is this:

Private Sub Command1_Click()
    WebBrowser1.Navigate "http://localhost:1234/mypage.html"
End Sub

Clicking the command button takes me to the same page:

enter image description here

In VB6, "hidden" is displayed for these three cases:

But not, in this case:

I've also noticed that "hidden" is only displayed the first time the window is minimized. If you minimize it again, it will display "visible".

I'm guessing this is a bug with how WebBrowser controls integrate with JS? Does anyone have any workarounds for this?


I may soon repurpose this question into a broader one, since this has less to do with document.hidden being wrong and more to do with WebBrowser not integrating nicely with JS's Page Visibility.

A more general problem that I have discovered is that the visibilitychange handler does not fire when run in a page hosted by a WebBrowser control in VB6, but works totally fine in the browser:

var ta = document.getElementById("ta");
document.addEventListener("visibilitychange", function ()
{
	ta.value += document.visibilityState + "\n";
});
<textarea id="ta" cols="50" rows="20"></textarea>


Solution

  • I worked around it by listening to the Resize event, and whenever the WindowState changed, I'd set a property in my JS code indicating the state:

    Private Sub Form_Resize()
        Static lWindowState As Long
        Dim lNewWindowState As Long
        Dim lOldWindowState As Long
    
        lNewWindowState = m_DesktopForm.WindowState
        lOldWindowState = lWindowState
    
        If lWindowState <> lNewWindowState Then  
            lWindowState = lNewWindowState
    
            Dim bHidden As Boolean
            bHidden = (lWindowState = vbMinimized)          
            Call CallByName(MyJSObj, "windowIsHidden", VbLet, bHidden)
        End If
    End Sub
    

    My JS has an object (that VB can reference) like this:

    MyJSObj = {
        windowIsHidden: false
    }
    

    Then I added a method to wrap document.hidden:

    function isDocumentHidden() {
        // if document.hidden is true, trust that. If it's not true, then fall back on what VB says
        return document.hidden || MyJSObj.windowIsHidden;
    }
    

    I use that method in my code instead of document.hidden.