Question

I have an Delphi application that uses TWebbrowser component to automate navigation to another web application we have.

My problem is that sometimes IE shows the infamous 'Are you sure you want to leave this page' message and when this happens, my app can't navigate to another pages unless an user clicks on 'Leave this page' button. I can't edit the website code to remove this warning, unfortunately.

This message is plaguing my app for weeks, and I could not reach to a proper solution anymore. What I did is to keep a background process do manually send a keystroke when this window is show, but this is not a good solution because nobody can use the computer while my app is working.

I saw possible solution for C# in the topic below but I need a Delphi code instead.

Supress the "are you sure you want to leave this page" popup in the .NET webbrowser control

Any help is very, very appreciated.

Thanks :)

Was it helpful?

Solution

This message is shown by the underlying MSHTML engine if the web page handles window.onbeforeunload event. Usually, it's there for a reason, to let the user know his/her input hasn't been saved or submitted yet. The prompt suppression script from the answer you linked doesn't work for cases when the page uses addEventListener("beforeonload", handler) or attachEvent("onbeforeunload", handler). I don't think there's a reliable way of doing this, without resorting to low-level Windows hooks.

[UPDATE] The following script (look for "Inject this script") is a hack which aggressively suppresses the page's own handlers for onbeforeunload event, via setInterval. It should work in 99% of cases, but it still leaves a gap for the page to override onbeforeonload right before navigating away.

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title></title>
    <script type="text/javascript">
        window.attachEvent("onbeforeunload", function (ev) {
            window.event.returnValue = "onbeforeunload via window.attachEvent()";
        });

        window.addEventListener("beforeunload", function (ev) {
            window.event.returnValue = "onbeforeunload via window.addEventListener()";
        });

        window.onbeforeunload = function (ev) {
            window.event.returnValue = "onbeforeunload via window.onbeforeunload";
        };
    </script>

    <script type="text/javascript">
        //
        // Inject this script
        //
        (function () {
            var onbeforeunloadHandler = function (ev) {
                if (ev) {
                    if (ev.stopPropagation)
                        ev.stopPropagation();
                    if (ev.stopImmediatePropagation)
                        ev.stopImmediatePropagation();
                    ev.returnValue = undefined;
                }
                window.event.returnValue = undefined;
            }

            var handler = null;
            var intervalHandler = function () {
                if (handler)
                    window.detachEvent("onbeforeunload", handler);

                // window.attachEvent works best
                handler = window.attachEvent("onbeforeunload", onbeforeunloadHandler);
                // handler = window.addEventListener("beforeunload", onbeforeunloadHandler);
                // handler = window.onload = onbeforeunloadHandler;
            };

            window.setInterval(intervalHandler, 500);
            intervalHandler();
        })();
    </script>

</head>
<body>
    <a href="http://www.example.com">Go away</a>
</body>
</html>

To inject this script with Delphi, you'd probably need to resort to low-level WebBrowser/MSHTML COM interfaces, like IWebBrowser2, IHTMLDocument2, IHTMLScriptElement, in a very similar way it's done in the linked answer. With some more efforts, the same can also be done via late binding, using IDispatch::GetIDsOfNames and IDispatch::Invoke only. If you're asking for exact Delphi code, I don't have one.

OTHER TIPS

The other answer you link to handles the browser's Navigated event. In it, it injects a script element into the page and into each frame on the page. That script assigns a new value to window.alert so that when other code on the page calls it, it does nothing.

This code resets the event handler:

var
  WrkIHTMLWindow2: IHTMLWindow2;
  WrkIHTMLWindow2Disp: IHTMLWindow2Disp;
begin
  WrkIHTMLWindow2 := IHTMLDocument2Disp(WrkIWebBrowser2.Document).parentWindow;
  if WrkIHTMLWindow2.QueryInterface(IHTMLWindow2Disp, WrkIHTMLWindow2Disp) = S_OK then
    if not VarIsNull(WrkIHTMLWindow2Disp.onbeforeunload) then
      WrkIHTMLWindow2Disp.onbeforeunload := NULL;
end;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top