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

我写的这个插件的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. yaml

    YAML http://baike.baidu.com/link?url=Jqbh_SBnlVuP0dPCknzd5ti5jr4h9HcacA0j56ztf4QsPcXI8kvgFaKpvhRG3em ...

  2. 获取页面内iframe里面的元素

    结构直接看图比较直接 这里window.frames获取的是iframe的数组 要记得给iframe加个ID才行 后面的记录会详细讲解 在父窗口获取页面内的iframe 里面的元素window.fra ...

  3. ThinkPHP配置简单的mysql读写分离

    ThinkPHP内置了分布式数据库的支持,包括主从式数据库的读写分离,但是分布式数据库必须是相同的数据库类型. 配置DB_DEPLOY_TYPE 为1 可以采用分布式数据库支持.如果采用分布式数据库, ...

  4. Shader 学习笔记

    Shader "Custom/Diffuse Texture" { // Shader的开始,双引号内饰该Shader的名字 Properties { _MainTex (&quo ...

  5. python 学习 : 一个简单的秒表

      游戏说明:绿色数字(左边表示成功停止在整秒的次数,右边表示停止的总次数) 点击stop,如果小数点后为0,即你停止的时间是整秒数,右上方斜杠左边数字加一 把代码复制到这个网页code run he ...

  6. codevs1316 文化之旅

    题目描述 Description 有一位使者要游历各国,他每到一个国家,都能学到一种文化,但他不愿意学习任何一种文化超过一次(即如果他学习了某种文化,则他就不能到达其他有这种文化的国家).不同的国家可 ...

  7. UI第七节——UISlider详解

    - (void)viewDidLoad { [super viewDidLoad]; // 实例化UISlider,高度对外观没有影响 UISlider *slider = [[UISlider al ...

  8. cvCreateCameraCapture

    编辑 本词条缺少信息栏.名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧! cvCreateCameraCapture,初始化从摄像头中获取视频,专业名词.   初始化从摄像头中获取视频 ...

  9. make menuconfig error 解决方法记录

    新建的一个虚拟机,发现make menuconfig 后会出错,查了一下是缺少一些库. 这个错误已经错了两次了,我不希望第三次出现了还想不起来,所以特此记录. # 错误信息: make[2]: *** ...

  10. 使用github pages, hexo搭建个人博客教程

    具体的原理性的东西就不说了直接上教程,怕等下自己忘了. 一. github 阶段 申请一个github 账号并成功登录进去. 创建一个名字为xxx.github.io的空项目. 二. hexo 阶段 ...