• Qt写Activex插件 总结


    最近写的插件功能基本完成,也遇到了一些坑,在这里记录一下。

    我写的这个插件的js接口是仿造google earth的js接口,尽可能的达到与它的api一致。先从最简单的说起:

    1. 导出接口中的float参数

    GE中的一些接口有些参数是float,比如下面这个:
        float KmlMouseEvent::getLatitude()

    你要是真按着这个函数来返回float,我估计你在页面里调用这个方法的时候肯定会提示你“方法不存在,或不支持该方法”之类的。
    明明写了,为啥提示没有这个方法呢?原因很简单,因为这个接口没有导出成功!没有导出成功的方法,你咋调呢?
    那么为什么没有导出成功?这个就得问assisant了。

    请翻到 Building ActiveX servers in Qt 这一页,往下翻,会看到一个Qt data types与COM property的对应表。
    仔细看就会发现,根本没有float这一项!

    我对COM不熟,不知道COM是不是本身就没有float;还是Qt认为有double就够用了,float不需要;还是因为javascript只有number类型,不区分float和double,如果能导出float,会影响精度。。。

    所以解决办法就出来了,接口参数都用double,不要用float!

    2. 导出类的创建和回收

    这个其实是我对ActiveQt框架如何管理对象的一个疑惑。因为在这个框架中,所以导出的类都只能以new这种方式创建出来,在js代码中也是new xxxx;而且所有的导出函数也不能用对象作为参数,而必须用对象的指针才行。那我什么时候删除呢?

    其实这里我也没有看到一些说明文档,不过倒是在网上搜的时候看到这篇博客,写的还是挺不错的,解释的很清楚。

    3. 枚举类型的导出

    在GE的api中是存在这样的调用的:
        ge.getLayerRoot().enableLayerById(ge.LAYER_TERRAIN, true);
        (其中ge是google.earth.createInstance得到的对象)

    这里就涉及到枚举值。那怎么在Qt里导出枚举呢。
    这个其实翻翻例子,应该就能找到这个宏:
        Q_ENUMS

    用法:
    class MyClass : public QObject
    {
         Q_OBJECT
         Q_ENUMS(Priority)
     
    public:
         MyClass(QObject *parent = 0);
         ~MyClass();
     
         enum Priority { High, Low, VeryHigh, VeryLow };
         void setPriority(Priority priority);
         Priority priority() const;
    }

    看上去,似乎这样就OK了。实际上,枚举也确实是这样导出的。
    但你对照着GE的API看看,就会发现,这个定义的枚举值我怎么在其他的函数里调用!而且 ge.LAYER_TERRAIN 这样调用,仔细看似乎并不是枚举,因为ge是对象,用对象再点出来一个枚举。。我反正是没见过。

    所以我的最后的解决方案是用:property。代码如下:
    class MyClass : public QWidget, public QAxBindable
    {
        Q_OBJECT
        Q_PROPERTY(int LAYER_TERRAIN READ enum_TERRAIN)
        Q_PROPERTY(int LAYER_BORDERS READ enum_BORDERS)

    public:
        int enum_TERRAIN() {return 0;}
        int enum_BORDERS() {return 1;}
    }

    看着很啰嗦是吧,暂时我也没好的解决方案,如果哪位看官解决过,麻烦告诉一下:)

    4. 动态生成函数,事件监听

    这里费了我很大的力气,但最终的解决方案还是没有与GE完全一致(哎,还得努力啊。。)。这里把我的解决方案记录下来,供大家参考。

    在GE的api里有个 addEventListener 函数,可以用于事件的绑定。函数的原型:
        addEventListener(obj, 'signal', callbackfunc)
    也就是当obj发出'signal'事件时,会回调callbackfunc这个函数。

    可以直接用C++写导出函数,但问题是怎么调用js的函数,我搜了很久也没有找到。。。所以就把这个方法写成js的函数了。

    因为ActiveQt中的事件写成监听函数要写成:
        function obj::signal(e) { }
    这样的方式才行,所以问题就变成了怎么用那三个参数生成一个监听函数了。

    同样,搜了很久,再参考了这个这个后,才得到一个解决方案:
    //////////////////////////////////////////////////
    // 动态生成函数
    var X2={} //my namespace:)
    X2.Eval=function(code){
        if(!!(window.attachEvent && !window.opera)){
            //ie
            alert(code);
            window.execScript(code);
        }else{
            //not ie
            window.eval_r(code);
        }
    }
     
    MYOBJECT.property.addEventListener = function(obj, signal, func) {
        var src = "function "+obj+"::"+signal+"(event) {" +
            func+"(event);" +
        "}";
        X2.Eval(src);
    }

    这里的 addEventListener 函数,两个参数都必须是字符串才行。所以最终的调用效果是:
    function mouseuphandler(e) { alert('ok'); }
    obj.addEventListener("mouseup", "mouseuphandler");

    附上GE的调用方式:
    google.earth.addEventListener(ge.getWindow(), 'click', function (event) { })

    呵呵,差别还是挺大的吧,哎,还得改啊,有进展了再来分享。

    PS:当用ActiveQt开发插件时,推荐用 out-of-process 方式,这样写出的插件是exe,可以直接运行,调试的时候方便不少,而且还能当桌面程序用,哈哈。




  • 相关阅读:
    git clone 解决Permission Denied (publickey)问题
    json-server 的基本使用
    存储过程的基本使用(1)
    Linux中的yum是什么?如何配置?如何使用?
    搭建博客园皮肤
    PSCP和SCP区别和用法
    Linux 磁盘分区和挂载
    win10产生文件的哈希值
    linux下刻录iso到U盘
    jquery鼠标移入移出
  • 原文地址:https://www.cnblogs.com/chaoswong/p/3544048.html
Copyright © 2020-2023  润新知