您的位置:首页 > 编程语言 > Qt开发

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

来自为知笔记(Wiz)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: