zoukankan      html  css  js  c++  java
  • [Sciter系列] MFC下的Sciter–3.Sciter脚本与底层交互

    [Sciter系列] MFC下的Sciter–3.Sciter脚本与底层交互,脚本调用底层自定义的方法函数。

    本系列文章的目的就是一步步构建出一个功能可用,接口基本完善的基于MFC框架的SciterFrame程序,以此作为以后程序的基础。其中,文章中按照如下逻辑编排(解决如下问题):

    1、使用什么环境

    2、完成什么功能

    3、如何完成


    1、工程环境: VS2010 + Sciter-SDK + Win7

    建议:HTML页面还使用ANSI编码,UTF-8此时不建议使用。

    2、本文完成的功能:HTML页面添加自定义函数调用,在底层将此函数实现,同时演示部分自带函数的使用。

    3、具体步骤如下:

    一、TS调用自带函数的演示:(即不需要自己编写和实现对应的函数,引擎自带)

    TS脚本自身有很多自带的函数,如msgbox(消息框),selectFile(文件选择框),Update等。

    这些函数可以在帮助文档里面查看:

    aa

    简单的HTML测试代码:

    <html>
    <head>
        <title>Hello World</title>
    
        <style>
            .test{
                background-color: black;
                color: white;
            }
        </style>
        <script type="text/tiscript">
            $(#btnExit).onClick = function () {
                stdout.println("退出");
    //            view.close();
                return true;
            }
            $(#btnUpdate).onClick = function () {
                stdout.println("刷新");
                view.update();
                return true;
            }
            $(#btnLoad).onClick = function () {
                stdout.println("加载");
                var fn = view.selectFile(#open,"HTML Files (*.htm,*.html)|*.HTM;*.HTML|All Files (*.*)|*.*" , "html" );
                if( fn ) view.load(fn);
                return true;
            }
        </script>
    </head>
    <body bgcolor="#00AAAA" >
        <h1>自带函数测试</h1>
        <input #btnExit type="button" value="退出"/>
        <input #btnUpdate type="button" value="刷新"/>
        <input #btnLoad type="button" value="加载"/>
    </body>
    </html>

    这个代码在Sciter.exe中就可以测试了。

    二、设置自定义函数,并且调用对应的函数

    我们在之前的HTML代码中添加自定义函数调用部分:

    <html>
    <head>
        <title>Hello World</title>
    
        <style>
            .test{
                background-color: black;
                color: white;
            }
        </style>
        <script type="text/tiscript">
    
            $(#btnExit).onClick = function () {
                stdout.println("退出");
    //            view.close();
                return true;
            }
            $(#btnUpdate).onClick = function () {
                stdout.println("刷新");
                view.update();
                return true;
            }
            $(#btnLoad).onClick = function () {
                stdout.println("加载");
                var fn = view.selectFile(#open,"HTML Files (*.htm,*.html)|*.HTM;*.HTML|All Files (*.*)|*.*" , "html" );
                if( fn ) view.load(fn);
                return true;
            }
            // 调用我们程序自定义方法
            $(#btnCall).onClick = function () {
                stdout.println("调用自定义函数");
                var ret = view.msgbox(#information, "这个函数将调用底层编写的函数addsome()函数,<br/><br/>请确保不是使用测试工具调用的,否则无效!",
                 "你确定调用?",[ {id:#yes, text:"确定"}, {id:#no, text:"取消"} ] );
                    if( ret == #yes )
                    {
                        stdout.println("确定");
                        // addsome()是自定义函数,一定要以view.xxxx(xx)方式调用
                        ret = view.addsome(3,2);
                        view.msgbox(#information,ret);
                    }else{
                        stdout.println("取消");
                    }
                return true;
            }
        </script>
    </head>
    <body bgcolor="#00AAAA" >
        <h1 .test>Hello World!</h1>
        <h2 #test1>你好啊</h2>
        <input #btnExit type="button" value="退出"/>
        <input #btnUpdate type="button" value="刷新"/>
        <input #btnLoad type="button" value="加载"/>
        <br/><br/><br/>
        <input #btnCall type="button" value="调用底层定义的函数"/>
    </body>
    </html>

    当然,这个自定义函数现在还没有实现,并且如果在Sciter.exe中在弹出的对话框中选择“确定”也不会有下面的那个消息框弹出,因为TS脚本找不到这样一个函数用来调用,通过调试工具查看就会看到报错信息。

    下面我们来进行最重要的工作,用VC++实现addsome函数:

    首先,我们要明白函数调用的机理:

    当TS脚本准备调用一个函数时,他肯定会先查找自身是否拥有这个函数,如果没有就会查找底层是否注册了这个函数,找到后就按照规定的规则调用它,将返回值返回到TS中,完成整个调用过程。

    然后,我们通过C++来实现它:

    想要完成这个过程,我们需要确保几个问题:

    1、我们的程序如何让TS脚本得知实现的接口?

    答:首先,我们的窗口类要继承于sciter::event_handle,这个需要头文件 #include "include/sciter-x-host-callback.h" 的支持,在窗口被加载后需要主动注册我们的窗口到TS引擎中,即调用 sciter::attach_dom_event_handler(this->m_hWnd,this); 方法,这样TS脚本就知道可以在我们的窗口中找到对应的函数。但是TS作为一种解释性的脚本语言,不可能直接调用C++的方法,所以我们还需要在做一步工作:

    SDK作者早已考虑了这些问题,它使用了类似MFC的消息映射机制,如下所示:

    //消息映射的函数
        json::value addsome(json::value a,json::value b); // 测试的函数
        //Sciter的TiScript消息映射
        BEGIN_FUNCTION_MAP 
            FUNCTION_2("addsome", addsome) // 后面的2表示有2个参数 
        END_FUNCTION_MAP

    这样,当TS脚本调用addsome()函数时,通过窗口类通知给消息映射,然后消息映射调用VC++实现的addsome方法,实现自定义函数的调用。

    虽然似乎这个问题已经解决了,因为函数已经可以被调用了,但是问题永远不像想想的那么简单。

    2、如何处理被调函数的参数及返回值?

    答:这个涉及到json类的使用,需要使用者自行摸索。我给出一个样例:

    json::value CHelloWorldDlg::addsome( json::value a,json::value b )
    {
        int aa = int(a.d) + int(b.d);  // xx.d 返回的是int64的整数,可以作为数据类型转换使用
        return json::value(aa);   // 返回求和后的结果
    }

    如上所述,自定义函数的声明调用都完成了,至于多线程、资源内置等内容我们在后面讨论

    补充:

    相信很多人都想在自己的程序中使用到像Sciter.exe中的调试工具,如何将这个工具添加到自己的程序中去呢?其实很简单!

    答:在WindowProc中拦截F12按键按下的消息,使用sciter::inspect()调用即可。需要特别注意的是一定要将sdk中的 inspector32/64.dll 拷贝到程序运行目录下,否则没效果。使用时按下F12键就可以了。

    if (message == WM_KEYDOWN && wParam == VK_F12)
        {
            sciter::inspect(this->m_hWnd);
            return 0;
        }

    ---------------

    本节源代码下载

    http://pan.baidu.com/s/17VeWm

    博客:

    CSDN:http://blog.csdn.net/bbdxf

    cnBlogs: http://www.cnblogs.com/bbdxf

    CSDN博客:http://blog.csdn.net/bbdxf
    CNBlogs: http://www.cnblogs.com/bbdxf
    本博客内容为本人原创,如有转载请保留出处!尊重他人就是尊重自己!

  • 相关阅读:
    Windows Azure Redis 缓存服务
    Windows Azure支持七层负载均衡--Application Gateway
    使用中国版 Office 365 -- Team Site分享
    翻译 GITHUB上HOW TO BE A GOOD PROGRAMMER
    翻译 github上How to be a good programmer
    linux note
    vim note
    编程策略类note
    jni note
    python note
  • 原文地址:https://www.cnblogs.com/bbdxf/p/3410324.html
Copyright © 2011-2022 走看看