Qt写Activex插件 总结
2014-02-11 11:16
260 查看
最近写的插件功能基本完成,也遇到了一些坑,在这里记录一下。
我写的这个插件的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
用法:
看上去,似乎这样就OK了。实际上,枚举也确实是这样导出的。但你对照着GE的API看看,就会发现,这个定义的枚举值我怎么在其他的函数里调用!而且 ge.LAYER_TERRAIN 这样调用,仔细看似乎并不是枚举,因为ge是对象,用对象再点出来一个枚举。。我反正是没见过。
所以我的最后的解决方案是用:property。代码如下:
看着很啰嗦是吧,暂时我也没好的解决方案,如果哪位看官解决过,麻烦告诉一下:)
4. 动态生成函数,事件监听
这里费了我很大的力气,但最终的解决方案还是没有与GE完全一致(哎,还得努力啊。。)。这里把我的解决方案记录下来,供大家参考。
在GE的api里有个 addEventListener 函数,可以用于事件的绑定。函数的原型: addEventListener(obj, 'signal', callbackfunc)也就是当obj发出'signal'事件时,会回调callbackfunc这个函数。
可以直接用C++写导出函数,但问题是怎么调用js的函数,我搜了很久也没有找到。。。所以就把这个方法写成js的函数了。
因为ActiveQt中的事件写成监听函数要写成: function obj::signal(e) { }这样的方式才行,所以问题就变成了怎么用那三个参数生成一个监听函数了。
同样,搜了很久,再参考了这个和这个后,才得到一个解决方案:
这里的 addEventListener 函数,两个参数都必须是字符串才行。所以最终的调用效果是:
附上GE的调用方式:
呵呵,差别还是挺大的吧,哎,还得改啊,有进展了再来分享。
PS:当用ActiveQt开发插件时,推荐用 out-of-process 方式,这样写出的插件是exe,可以直接运行,调试的时候方便不少,而且还能当桌面程序用,哈哈。
来自为知笔记(Wiz)
我写的这个插件的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;}}
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,可以直接运行,调试的时候方便不少,而且还能当桌面程序用,哈哈。
来自为知笔记(Wiz)
相关文章推荐
- QT浏览器插件的开发过程总结
- 关于ActiveX插件小项目总结
- 【原】关于ActiveX插件小项目总结
- QT 商业版调用activex插件
- myslide 插件开发知识点总结和 css3 动画性能问题的研究
- NGUI 相关插件总结
- linux下qt开发的mysql工具远程连接问题总结
- Qt窗口中的一些小技术总结
- Qt鼠标事件QMouseEvent总结
- QT中窗口刷新事件的学习总结
- Qt下数据库操作总结(转载)
- Qt 的几个核心机制总结之 布局
- QT插件
- Qt学习(16)——Qt5中的文件与文件夹总结
- 开发Qt应用程序的基本方法总结
- Qt 出现"Undefined reference to 'vtable for'原因总结
- Qt 5.2 自定义设计师UI插件 遇到问题记录
- uboot-busybox-kernel-libc-qt版本总结
- atitit. 浏览器插件 控件 applet 的部署,签名总结 浏览器 插件 控件 的签名安全机制o9o
- Linux下移植OpenCV + Qt 到ARM(Tiny6410)总结