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

我写的这个插件的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,可以直接运行,调试的时候方便不少,而且还能当桌面程序用,哈哈。

Qt写Activex插件 总结的更多相关文章

  1. Qt编写自定义控件插件路过的坑及注意事项

    在一日一控件的口号下,终于写好了五十几个自定义控件,包括各种仪表盘,各种温度计,各种进度条,各种按钮等,具体可参见(http://www.cnblogs.com/feiyangqingyun/p/61 ...

  2. C#开发ActiveX插件-aspx中嵌入

    刚到新的公司,第一周让我熟悉一下他们用的silverlight和arcgis.这周,也就是昨天分配了我一个小小的任务! 哪个项目的不知道,是让我实现一个在aspx中嵌入activeX插件! 在网上找了 ...

  3. 非IE内核浏览器支持activex插件

    之前在一个B/S项目中遇到一个需求,就是客户需要在页面上对报表的布局以及显示内容,进行自定义.最后决定使用activex技术来实现.众所周知,activex是微软搞得,因此只有ie内核的浏览器才能支持 ...

  4. 使用Qt编写模块化插件式应用程序

    动态链接库技术使软件工程师们兽血沸腾,它使得应用系统(程序)可以以二进制模块的形式灵活地组建起来.比起源码级别的模块化,二进制级别的模块划分使得各模块更加独立,各模块可以分别编译和链接,模块的升级不会 ...

  5. C#制作ActiveX插件

    首先新建项目--->类库,取名:ActiveXDemo 右键项目属性:应用属性==>程序集信息=>使程序集Com可见, 生成==>输出==>为com互操作注册 新建接口类 ...

  6. Qt编写activex控件在网页中运行

    qt能够实现的东西非常多,还可以写activex控件直接在网页中运行.参照qtdemo下的例子即可. 方案一:可执行文件下载:https://pan.baidu.com/s/14ge9ix2Ny0x7 ...

  7. 非IE内核浏览器如何支持activex插件

    原文地址:https://blog.csdn.net/johnson2008t/article/details/46126605 之前在一个B/S项目中遇到一个需求,就是客户需要在页面上对报表的布局以 ...

  8. ActiveX插件

    C#制作ActiveX插件 首先新建项目--->类库,取名:ActiveXDemo 右键项目属性:应用属性==>程序集信息=>使程序集Com可见, 生成==>输出==>为 ...

  9. 自己写jquery插件之模版插件高级篇(一)

    需求场景 最近项目改版中,发现很多地方有这样一个操作(见下图gif动画演示),很多地方都有用到.这里不讨论它的用户体验怎么样. 仅仅是从复用的角度,如果每个页面都去写text和select元素,两个b ...

随机推荐

  1. PHP读写文件

    一:读取文件 例1: $xml = ""; //打开文件 $f = fopen('http://app.eyuebus.com/Public/apk/version.xml', ' ...

  2. win7下安装和使用Windows XP Mode

    如果想在电脑中安装多个操作系统有几种方法: 1.安装虚拟机,继而在虚拟机中安装操作系统.虚拟机个数就相当于电脑个数,常用的虚拟机软件有VMVare,VMVare功能齐全,但是安装文件较大. 2.如果你 ...

  3. [linux]Socket编程的头文件

    socket编程中需要用到的头文件 sys/types.h:数据类型定义 sys/socket.h:提供socket函数及数据结构 netinet/in.h:定义数据结构sockaddr_in arp ...

  4. Factorization Machine因子分解机

    隐因子分解机Factorization Machine[http://www. w2bc. com/article/113916] https://my.oschina.net/keyven/blog ...

  5. js自动更新时间+星期

    <div class="top_bar" id="cao" height="28px"><script> setIn ...

  6. 当你在浏览器地址栏输入一个URL后回车,将会发生的事情?

    原文:http://igoro.com/archive/what-really-happens-when-you-navigate-to-a-url/ 作为一个软件开发者,你一定会对网络应用如何工作有 ...

  7. ACM/ICPC 之 Unix会议室(POJ1087)

    采用EK算法解网络流经典题,本题构图思路比较明确. //Unix会议室插座转换 //网络流-EK算法 //Time:47Ms Memory:1188K #include<iostream> ...

  8. Deep Learning入门视频(上)_一层/两层神经网络code

    关于在51CTO上的深度学习入门课程视频(9)中的code进行解释与总结: (1)单层神经网络: #coding:cp936 #建立单层神经网络,训练四个样本, import numpy as np ...

  9. hyperV中修改centos分辨率

    grubby --update-kernel=ALL --args="video=hyperv_fb:1366x768"

  10. Spring实例化Bean的三种方式及Bean的类型

    1.使用类构造器实例化  [默认的类构造器] <bean id=“orderService" class="cn.itcast.OrderServiceBean"/ ...