Adding contextmenu to WP8 browser control

冷暖自知 提交于 2019-12-10 11:54:06

问题


I am trying to attach a context menu when user perform a hold gesture on a link on a webpage.

I've searched the web and found some recommendations HERE

if (webBrowser.IsScriptEnabled)
        {
            webBrowser.InvokeScript("execScript", "function eventListener(evt){ if (evt.type == 'MSPointerDown') { gestureHandler.addPointer(evt.pointerId); return; } if (evt.detail & evt.MSGESTURE_FLAG_END) {  window.external.notify(evt.srcElement.tagName);}}");
            webBrowser.InvokeScript("execScript","document.addEventListener('MSGestureHold', eventListener, false); document.addEventListener('MSPointerDown', eventListener, false);  gestureHandler = new MSGesture(); gestureHandler.target = document.body;");
        }

But the second execScript raised this error

 System.SystemException was unhandled by user code
  HResult=-2146233087
  Message=An unknown error has occurred. Error: 80020101.
  Source=Microsoft.Phone.Interop
  StackTrace:
   at Microsoft.Phone.Controls.NativeMethods.ValidateHResult(Int32 hr)
   at Microsoft.Phone.Controls.WebBrowserInterop.InvokeScript(String scriptName, String[] args)
   at Microsoft.Phone.Controls.WebBrowser.InvokeScript(String scriptName, String[] args)
   at Tabbed_Browser.User_Controls.WebBrowser.AttachContextMenu()
   at Tabbed_Browser.User_Controls.WebBrowser.webBrowser_Loaded(Object sender, RoutedEventArgs e)
   at MS.Internal.CoreInvokeHandler.InvokeEventHandler(Int32 typeIndex, Delegate handlerDelegate, Object sender, Object args)
   at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String eventName)
  InnerException: 

I've also tried the following, based on this posting. But apparently it only work in WP7 phone not in WP8 or the emulator.

public void AttachContextMenu()
    {
        try
        {
            if (webBrowser.IsScriptEnabled)
            {
                webBrowser.InvokeScript("execScript", "function FindParentLink(item) \r\n{\r\n\tif (!item.parentNode)\r\n\t\treturn null;\r\n\tif (item.tagName.toLowerCase() == 'a') \r\n\t{\r\n\t\treturn item;\r\n\t} \r\n\telse \r\n\t{\r\n\t\treturn FindParentLink(item.parentNode);\r\n\t}\r\n}\r\n\r\nfunction FindParentImage(item) \r\n{\r\n\tif (!item.parentNode)\r\n\t\treturn null;\r\n\tif (item.tagName.toLowerCase() == 'img') \r\n\t{\r\n\t\treturn item;\r\n\t} \r\n\telse \r\n\t{\r\n\t\treturn FindParentImage(item.parentNode);\r\n\t}\r\n}\r\n\r\nfunction HandleContextMenu() \r\n{\r\n\tvar linkItem = FindParentLink(event.srcElement);\r\n    var imageItem = FindParentImage(event.srcElement);\r\n    var notifyOutput = '';\r\n    if (linkItem != null) if (linkItem.href != null) notifyOutput += linkItem.href;\r\n    if (imageItem != null) if (imageItem.src != null) notifyOutput += imageItem.src;\r\n    if (notifyOutput != '')\r\n        window.external.notify(notifyOutput);\r\n    else\r\n\t\twindow.external.notify('NOTLINKIMG');\r\n}");
                webBrowser.InvokeScript("execScript", "document.oncontextmenu = HandleContextMenu;");
            }
        }
        catch
        {
        }
    }

I monitor the result via ScriptNotify but it never fired

    private void webBrowser_ScriptNotify(object sender, NotifyEventArgs e)
    {
        Debug.WriteLine(e.Value.ToString());
    }

Anyone know how to attach context menu in WP8 browser control?

EDIT

I've found an info that window.navigator.msPointerEnabled is false on the WebBrowser control and True on the Internet Explorer application. So does that mean we can't implement touch event detection properly in the control. Can we set it to enabled?


回答1:


If window.navigator.msPointerEnabled is false ,you can use onmousedown and onmouseup to monitor




回答2:


After trying to get the WP8 web browser control do some tricks, here are a couple observations.

The ...

System.SystemException
Message=An unknown error has occurred. Error: 80020101.

... typically means your javascript was not parsed correctly. Often a syntax error.

I found striping out the CR, LF, and TAB characters reduces the noise and makes finding syntax errors in a VisualStudio JavaScript editor window a little easier. String.Replace() is your friend.

I have only been successful using the InvokeScript() to execute anonymous functions. This pattern has been successful: (pay attention to the punctuation)

webBrowser.InvokeScript("eval", "(function (param1) { window.external.notify(param1); })('this is your message');");

In your specific case, I see three functions being defined but what causes them to be executed? Perhaps that explains the exception.

Gyle




回答3:


This is my solution. It is working on Windows Phone 8

<phone:WebBrowser
                x:Name="WebBrowser"
                IsHitTestVisible="True"
                IsScriptEnabled="True"
                LoadCompleted="WebBrowser_LoadCompleted"
                                                                ScriptNotify="WebBrowser_ScriptNotify">
                          
</phone:WebBrowser>
 
private void WebBrowser_LoadCompleted(object sender, NavigationEventArgs e)
{
                if (WebBrowser.IsScriptEnabled)
                {
                                var JavaScriptText =
                                                @"function ReplaceBadXmlChars(str) {
                                                var stri = str.split('&').join('&amp;');
                                                stri = stri.split('<').join('&lt;');
                                                stri = stri.split('>').join('&gt;');
                                                stri = stri.split("'").join('&apos;');
                                                stri = stri.split('"').join('&quot;');
                                                return stri;
                                }
 
                                function FindParentByTag(item, tag) {
                                                if (!item.parentNode) return null;
                                                if (item.tagName.toLowerCase() == tag.toLowerCase()) {
                                                                return item;
                                                } else {
                                                                return FindParentByTag(item.parentNode, tag);
                                                }
                                }
 
                                function OnClick() {
                                                var linkItem = FindParentByTag(event.srcElement, 'a');
                                                var imageItem = FindParentByTag(event.srcElement, 'img');
 
                                                var zoom = screen.deviceXDPI / screen.logicalXDPI;
                                                var valid = false;
                                                var notifyMsg = '<Click ';
                                                {
                                                                notifyMsg += 'pos="' + parseInt(event.clientX * zoom) + ',' + parseInt(event.clientY * zoom) + '" ';
                                                                if (linkItem != null && linkItem.href != null && !linkItem.href.startsWith("javascript")) {
                                                                                notifyMsg += 'url="' + ReplaceBadXmlChars(linkItem.href) + '" ';
                                                                                valid = true;
                                                                }
 
                                                                if (imageItem != null && imageItem.href != null && !linkItem.href.startsWith("javascript")) {
                                                                                notifyMsg += 'img="' + ReplaceBadXmlChars(imageItem.src) + '" ';
                                                                                valid = true;
                                                                }
                                                }
                                                notifyMsg += '/>';
                                                if (valid) {
                                                                window.external.notify(notifyMsg);
                                                                return false;
                                                }
                                }
 
 
                                function RegisterClickNotification() {
                                                window.document.onclick = OnClick;
 
                                                window.document.body.addEventListener('MSPointerDown', function(evt) {
                                                                evt = evt || window.event;
 
                                                                var linkItem = FindParentByTag(evt.srcElement, 'a');
                                                                var imageItem = FindParentByTag(evt.srcElement, 'img');
 
                                                                window.devicePixelRatio = window.screen.deviceXDPI / window.screen.logicalXDPI;
                                                                var doc = window.document.documentElement;
                                                                var left = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0);
                                                                var top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
 
                                                                var timerId = window.setTimeout(function() {
                                                                                var notifyMsg = 'pos="' + parseInt((evt.clientX - left)) + ',' + parseInt((evt.clientY - top)) + '" ';
 
                                                                                if (linkItem != null && linkItem.href != null) {
                                                                                                notifyMsg += 'url="' + ReplaceBadXmlChars(linkItem.href) + '" ';
                                                                                }
 
                                                                                if (imageItem != null && imageItem.href != null) {
                                                                                                notifyMsg += 'img="' + ReplaceBadXmlChars(imageItem.src) + '" ';
                                                                                }
 
                                                                                window.external.notify('<Hold ' + notifyMsg + '/>');
                                                                }, 500);
                                                                StopLoading();
                                                                evt.target.data = timerId;
                                                });
                                }
 
                                window.document.body.addEventListener('MSPointerUp', function (evt) {
                                                window.clearTimeout(evt.target.data);
                                });
 
                                window.document.body.addEventListener('MSPointerMove', function (evt) {   
                                                window.clearTimeout(evt.target.data);   
                                });
 
                                window.document.body.addEventListener('MSPointerOut', function (evt) {
                                                window.clearTimeout(evt.target.data);
                                });
 
                                window.document.body.addEventListener('pointerup', function (evt) {
                                 
                                });"
 
                                WebBrowser.InvokeScript("eval", new string[] { JavaScriptText });
                                WebBrowser.InvokeScript("RegisterClickNotification");
                                WebBrowser.InvokeScript("execScript", new string[] {
                                "function eventListener(evt) {if (evt.type == 'MSPointerDown'){ gestureHandler.addPointer(evt.pointerId); return; } if (evt.detail & evt.MSGESTURE_FLAG_END) {  window.external.notify(evt.srcElement.tagName);}}" });
                                WebBrowser.InvokeScript("execScript", new string[] { "document.addEventListener('MSGestureHold', eventListener, false); document.addEventListener('MSPointerDown', eventListener, false);  gestureHandler = new MSGesture(); gestureHandler.target = document.body;" });
                }
}



回答4:


The following code works, but it fires even when you tap on any image or link. We may have to add a timer of some sort since we can't attach.

EDIT:

I was able to figure it out! The following code works in WP8 AND only detects a hold, not a tap.

public void AttachScripts()
    {
        try
        {
            if (GINternet.IsScriptEnabled)
            {
                var scriptsText = @"function ReplaceBadXmlChars(str) {
                                            var stri = str.split('&').join('&amp;');
                                            stri = stri.split('<').join('&lt;');
                                            stri = stri.split('>').join('&gt;');
                                            stri = stri.split(""'"").join('&apos;');
                                            stri = stri.split('""""').join('&quot;');
                                            return stri;
                            }

                            function FindParentLink(item) {
                            if (!item.parentNode)
                                return null;
                            if (item.tagName.toLowerCase() == 'a') {
                                return item;
                            } else {
                                return FindParentLink(item.parentNode);
                            }}

                            function FindParentImage(item) {
                            if (!item.parentNode)
                                return null;
                            if (item.tagName.toLowerCase() == 'img') { 
                                return item;
                            } else {
                                return FindParentImage(item.parentNode);
                            }}

                            var currGNetMouseTimer;
                            window.document.body.addEventListener('pointerdown', function (evt) {
                                                            evt = evt || window.event;

                                                            var linkItem = FindParentLink(evt.srcElement);
                                                            var imageItem = FindParentImage(evt.srcElement);

                                                            currGNetMouseTimer = window.setTimeout(function() {
                                                                            var notifyMsg = '';

                                                                            if (linkItem != null && linkItem.href != null) {
                                                                                notifyMsg += ReplaceBadXmlChars(linkItem.href);
                                                                            }

                                                                            if (imageItem != null && imageItem.src != null) {
                                                                                notifyMsg += ReplaceBadXmlChars(imageItem.src);
                                                                            }

                                                                            if (notifyMsg != '') {
                                                                                window.external.notify(notifyMsg);
                                                                            } else {
                                                                                window.external.notify('NOTLINKIMG');
                                                                            }
                                                            }, 750);
                            },false);

                            window.document.body.addEventListener('pointermove', function (evt) {
                                            window.clearTimeout(currGNetMouseTimer);
                            },false); 

                            window.document.body.addEventListener('pointerup', function (evt) {
                                            window.clearTimeout(currGNetMouseTimer);
                            },false); 

                            window.document.body.addEventListener('pointerout', function (evt) {
                                            window.clearTimeout(currGNetMouseTimer);
                            },false);";



                GINternet.InvokeScript("execScript", new string[] { scriptsText });
            }
        }
        catch
        {
        }
    }

    private void GINternet_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
    {
        //REQUIRED FOR WINDOWS PHONE 8
        AttachScripts();
}


来源:https://stackoverflow.com/questions/16481127/adding-contextmenu-to-wp8-browser-control

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!