zoukankan      html  css  js  c++  java
  • ActiveX(三)ActiveX 调用 Js

      在上一篇随笔: ActiveX(二)Js 监听 ActiveX中的事件  中,已经可以实现 Js 监听 ActiveX中的事件,至此、Js 和 ActiveX 已经可以实现双向通讯了。但是、这样的实现方式,都是站在Js的角度去实现的,那么 ActiveX 能否主动调用 Js 呢?答案无疑是肯定的,在该篇随笔中、我们将逐渐揭开这一层神秘的面纱。

      我第一次接触用C#代码调用Js是在四年前,那时候正在实习做Windows应用、需要借用 WebBrowser 控件操作js、完成一些特殊需求。当时的代码大致如下:

            // 执行JS
            private void ExecJs()
            {
                try
                {
                    if (this.webBrowser.Document != null)
                    {
                        mshtml.IHTMLDocument2 currentDoc = (mshtml.IHTMLDocument2)this.webBrowser.Document.DomDocument;
                        if (currentDoc != null)
                        {
                            mshtml.IHTMLWindow2 win = (mshtml.IHTMLWindow2)currentDoc.parentWindow;
                            if (win != null)
                            {
                                //调用 函数F、传递一个宽度做参数
                                win.execScript(string.Format("F('{0}')", this.webBrowser.Width), "javascript");
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }

      由上述代码、可以看出,其核心方法为 mshtml.IHTMLWindow2.execScript,注意:我们再仔细看一下方法名,有没有觉得很熟悉?如果你还没想起来,那我们继续看一下 mshtml.IHTMLWindow2 这个类型中还有什么成员吧。

        [Guid("332C4427-26CB-11D0-B483-00C04FD90119")]
        [TypeLibType(4160)]
        public interface IHTMLWindow2 : IHTMLFramesCollection2
        {
            [DispId(1153)]
            dynamic _newEnum { get; }
            [DispId(1161)]
            HTMLNavigator clientInformation { get; }
            [DispId(23)]
            bool closed { get; }
            [DispId(1101)]
            string defaultStatus { get; set; }
            [DispId(1151)]
            IHTMLDocument2 document { get; }
            [DispId(1152)]
            IHTMLEventObj @event { get; }
            [DispId(1169)]
            dynamic external { get; }
            [DispId(1100)]
            FramesCollection frames { get; }
            [DispId(2)]
            HTMLHistory history { get; }
            [DispId(1125)]
            HTMLImageElementFactory Image { get; }
            [DispId(1001)]
            int length { get; }
            [DispId(14)]
            HTMLLocation location { get; }
            [DispId(11)]
            string name { get; set; }
            [DispId(5)]
            HTMLNavigator navigator { get; }
            [DispId(1164)]
            dynamic offscreenBuffering { get; set; }
            [DispId(-2147412073)]
            dynamic onbeforeunload { get; set; }
            [DispId(-2147412097)]
            dynamic onblur { get; set; }
            [DispId(-2147412083)]
            dynamic onerror { get; set; }
            [DispId(-2147412098)]
            dynamic onfocus { get; set; }
            [DispId(-2147412099)]
            dynamic onhelp { get; set; }
            [DispId(-2147412080)]
            dynamic onload { get; set; }
            [DispId(-2147412076)]
            dynamic onresize { get; set; }
            [DispId(-2147412081)]
            dynamic onscroll { get; set; }
            [DispId(-2147412079)]
            dynamic onunload { get; set; }
            [DispId(4)]
            dynamic opener { get; set; }
            [DispId(1157)]
            HTMLOptionElementFactory Option { get; }
            [DispId(12)]
            IHTMLWindow2 parent { get; }
            [DispId(1156)]
            IHTMLScreen screen { get; }
            [DispId(20)]
            IHTMLWindow2 self { get; }
            [DispId(1102)]
            string status { get; set; }
            [DispId(21)]
            IHTMLWindow2 top { get; }
            [DispId(22)]
            IHTMLWindow2 window { get; }
    
            [DispId(1105)]
            void alert(string message = "");
            [DispId(1159)]
            void blur();
            [DispId(1163)]
            void clearInterval(int timerID);
            [DispId(1104)]
            void clearTimeout(int timerID);
            [DispId(3)]
            void close();
            [DispId(1110)]
            bool confirm(string message = "");
            [DispId(1165)]
            dynamic execScript(string code, string language = "JScript");
            [DispId(1158)]
            void focus();
            [DispId(0)]
            dynamic item(ref object pvarIndex);
            [DispId(7)]
            void moveBy(int x, int y);
            [DispId(6)]
            void moveTo(int x, int y);
            [DispId(25)]
            void navigate(string url);
            [DispId(13)]
            IHTMLWindow2 open(string url = "", string name = "", string features = "", bool replace = false);
            [DispId(1111)]
            dynamic prompt(string message = "", string defstr = "undefined");
            [DispId(8)]
            void resizeBy(int x, int y);
            [DispId(9)]
            void resizeTo(int x, int y);
            [DispId(1160)]
            void scroll(int x, int y);
            [DispId(1167)]
            void scrollBy(int x, int y);
            [DispId(1168)]
            void scrollTo(int x, int y);
            [DispId(1173)]
            int setInterval(string expression, int msec, ref object language = Type.Missing);
            [DispId(1172)]
            int setTimeout(string expression, int msec, ref object language = Type.Missing);
            [DispId(1155)]
            void showHelp(string helpURL, object helpArg = Type.Missing, string features = "");
            [DispId(1154)]
            dynamic showModalDialog(string dialog, ref object varArgIn = Type.Missing, ref object varOptions = Type.Missing);
            [DispId(1166)]
            string toString();
        }
    IHTMLWindow2

      想起来了没有? 如果还没有、那只能说你一行Js代码都没写过。 没错,js 中的 window 对象 实现了 mshtml.IHTMLWindow2 这个接口。既然如此,我们通过一个初始化函数将 window 对象传入,就可以得到  mshtml.IHTMLWindow2 接口了。

    哈哈,补充一下, mshtml 命名空间 源自:Microsoft.mshtml.dll.

    当知道了如上的信息后,一切就变的‘简单’了:

            /// <summary>
            /// 调用Js函数
            /// </summary>
            /// <param name="functionName">js函数名</param>
            /// <param name="args">参数</param>
            /// <returns></returns>
            private dynamic RunJs(string functionName, string args = "")
            {
                dynamic dy = null;
    
                // 方法返回值永远为 null
                if (this.window2 != null)
                {
                    //调用函数
                    dy = this.window2.execScript(string.Format("{0}('{1}')", functionName, args), "javascript");
                }
     
    
                return dy;
            }

    通过如上的代码,确实可以调用Js、但是、还有一个Bug... 返回值一直为Null. 

    那怎么办呢? 反射——没错,就是反射调用Js,也许你现在还想不明白, 先看一下代码吧,看完后你也许会恍然大悟:

            /// <summary>
            /// 调用Js函数
            /// </summary>
            /// <param name="functionName">js函数名</param>
            /// <param name="args">参数</param>
            /// <returns></returns>
            private dynamic RunJs(string functionName, string args = "")
            {
                dynamic dy = null;// 第二种方式 反射调用 Js
                // 被调用的js函数必须有一个参数
                if (this.window2 != null)
                {
                    dy = this.window2.GetType().InvokeMember(functionName,
                        BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public,
                        null, this.window2, new object[] { args });
                }
    
                return dy;
            }

    有没有想到呢 —— 全局的Js函数其实是属于window对象的,当然可以用反射去调用啦。

    完整的测试项目demo: TestActiveX.zip

    下一篇,我们将探究强大的 Microsoft.mshtml.dll,有点期待。

    (未完待续...)

  • 相关阅读:
    web前端要学哪些?
    angularjs factory,service,provider 自定义服务的不同
    PSP软件开发过程
    Eclipse连接sqlserver体验过程
    在线制作GIF图片项目愿景与范围
    C# Hashtable vs Dictionary 学习笔记
    Unity 工作经历+近期面试经历
    配置文件加载的一个坑
    rabbitmq exchange type
    centos7下nginx添加到自定义系统服务中提示Access denied
  • 原文地址:https://www.cnblogs.com/08shiyan/p/5070314.html
Copyright © 2011-2022 走看看