Qt开发Active控件:如何使用ActiveQt Server开发大型软件的主框架

注:本文更多地是带着如何去思考答案,而不是纯粹的放一个答案上来,如果你需要直接看到完整的答案,请直接看实例和最后的柳暗花明部分,里面由详细的注释可以解答你的问题。

前情提要:

Qt的进程间通信,以服务器的形式,手把手教你VS上进行Qt的COM、ActivedQt Server的开发,比保姆还保姆

本文提供两个实例:

ActiveQt Server COM服务器端:Qt_ActiveServer_Main

ActiveQt Active控件调用端:Client_ActiveServer_Demo

上文提到如何创建并调用一个Active控件,但是并不能完全满足我们的要求:现在我有一个主框架或者说主程序,会有很多别的模块需要在外部开发,这些模块可能会需要用到主框架中的信息,或者说一些接口来调用一些特定的功能。比如说我一个课堂教学模块,可能需要实现屏幕广播,语音广播,资料下发等功能。

如果你根据前文的实例进行我们根据上文的实例开发中会发现一个很明显的问题,那就是我们可以从调用方向主框架调用方法,但是却没法从主框架中发送消息给调用方。或者说如果这个COM服务器是有ui的,如果多个调用方可能就会调起多个界面,而且关闭调用方的同时会把这些界面都关闭,这又是怎么回事呢?为什么我们的ActiveServer不是像一个服务器一样简单地向其他的调用方提供服务?

关于这点,我翻遍了国内外几乎所有论坛和文章,以及Qt官方论坛和文章,发现并没有什么讨论的,或者零星有两个提问的人,但是都没有获得相关开发人员的回应。在这里我将会讨论上面的问题,并给出一套可行的方案。

一、当我们在创建一个ActiveQt Server的时候,我们在做什么。

由前文我们可以知道,我们建立一个Qt的COM组件,其实很简单,通过

这样一个宏就可以将一个类暴露在外,并且建立连接。然后我们可以拆分成如下形式:



--------------与以下形式---------------

我们在main函数内这么写了之后,我们就可以来调用了。这是我们在Qt的官方文档上看到的,也是我们能在几乎所有资料上看到的。

现在我们是不是建立了一个Active Server了呢?是的,你是建立了一个ActiveServer,但是现在这个ActiveServer只能单方面地提供服务,就像我上面说的那样:,那就是我们可以从调用方向主框架调用方法,但是却没法从主框架中发送消息给调用方。

这是为什么?我们要从创建开始说起。我们知道ActiveQt Server上是通过三个模块来实现ActiveServer的,我们可以从官方文档上看到:

第一个 第二个类你稍微看一下内容你就会发现,第一个类是为了提供一些额外接口,第二个类是用来提供与COM事件和绑定函数、参数的。真正用于运作整个ActiveServer的其实是QAxFactory

但是我们走进来看这个类的介绍,我们发现这个类里面全是提供的虚函数,我们应该会意识到这个类其实是一个基类,通过虚函数提供了一大堆的方法供其他组件去调用

聪明的你肯定想到了,那既然如此肯定是需要我们去继承这个QAxFactory类,然后来执行一些操作的吧!

等等,我们真的需要继承一个QAxFactory类(且不论能不能继承)吗?我们好像并没有见到一个QAxFactory的实例吧,那我们继承它又有什么用呢?(当然了,其实我是尝试继承了的,但是继承不了,这个单例会直接无法初始化了,还有些别的问题,这里就不一一分析了)

文档中没有提到,但是我在某个不记得的帖子上看到有人在说QAxFactory类提供了一个全局的单例qAxFactory(),于是我开始研究起了这个单例

经过一段时间对QAxFactory类的函数的研究,我发现这些函数其实没有多大用,并没有想到能解决什么问题的,于是问题又继续了下去。

有什么,不一样?

我们这个时候想到去比对一下,我们生成的ActiveServer和普通的Qt应用程序有什么不一样?聪明的你发现了,除了引用了QAxFactory.h之外,就是引用了这个宏:



----------------分割线-----------------

在中文

通过查找资料,你会发现Q_CLASSINFO宏只是给类提供了一个标识,并不是影响工作的关键。于是QAXFACTORY_BEGIN就理所应当的是我们查找的关键,让我们走到官方文档:(英文的就不放了,看着费劲,这里放个百度翻译吧)

这个好像和我之前讲的也没有什么关系,只是影响了声明导出和注册的类等信息,为了探寻真相,我们需要进一步走到QAxFactory.h内部去看发生了什么

这个宏好像就覆写一堆函数...有点意义不明,继续看下去,然后就想了一段时间....

想一下发生了什么

我们发现,每次一个外部进程用一个QAxObject来setControl一下我们的服务器,就会多一个窗口对吧。等等,多一个窗口?

为什么会多一个窗口?难道是创建了一个新的进程吗?不会啊,还记得我们的Main函数是怎么写的吗?

在我们的程序设计之初就考虑了不会让外部进程启动一个新进程的,所以不可能是新的进程导致的窗口启动的。

那就只有一个可能了,是一个新的类实例化了。我们将断点放到窗口类的构造函数上,我们发现断点被击中了!说明猜测是对的,类确实是被实例化了。

这样一切的疑问就解决了!为什么我们没法通信,因为信号根本就不是从这个实例发出的,而是从另外一个被外部调用绑定的实例啊!都不是一个对象而且没有进行绑定那肯定是没法通信的啊!

也就是说,每个QAxObject 绑定了与ActiveQtServer之间的连接的时候,都会实例化一个新的实例来专门处理这这两个进程之间的服务与连接。

现在的问题就很简单了,我们该如何找到这个被新建的实例?

我们可以根据调用堆栈找到,是通过这个QAxFactory类的某个实例调用了createObject。那么问题就从怎么建立连接变成了怎么找到这个QAxFactory的某个实例建立的,于是我又回到了对qAxFactory()的研究

介绍文档中是这么介绍QAxFactory类的:

我真的被这个文档疯狂误导,因为确实是调用了这个createObject 方法生成了一个实例(但是不是通过qAxObject进行的,后面会说),但是我硬是横竖看不懂怎么找到已经调用生成的实例我要去哪里找,唯一有点关系的就是这个featurList() (其实一点关系没有),搞了好久我觉得哪里有问题,就又回到qaxfactory.h里面去看,到底做了什么

这次不一样了,我看到一点不一样的东西,我们看到这个宏,初始化了一个QAxClass,这个类是什么?在Qt的官方文档上我居然没有找到,定睛一看,哦原来是这个.h文件里面声明的类,来看看内容

原来是提供了一个QAxFactory的模板子类,到这里我才明白,原来这是通过这个QAxClass的createObject来生成实例的。于是我开始尝试继承重写这个类

(过程不表了,反正搞了一个多小时我发现这个类其实是写在lib里面的改不了 囧)

ok重写是不行的,那肯定也和这个qAxFactory()的实例没有关系了,现在貌似又进了一个死胡同。

最后柳暗花明的是,我抱着试一试的态度问了下AI,它居然告诉我,你既然要记录实例化的对象,那你为什么不通过一个静态的QList,在每次这个类的对象实例化的时候将其记录在案。当你需要发送消息的时候,就可以从这个QList中读取想要的QObject,然后发送对应的信号,不就行了吗?

听罢,我惊为天人。于是就开始写

柳暗花明-总结

于是总的开发就这样结束了,把大概最后的框架描述一下就是

首先我们需要一个导出类A,这个类是暴露给外部的,提供接口给外部进程调用,这个类A需要继承QObject和QAxBindable,前者可以保证signals和slots的使用,后者可以保证signals和slots和COM函数和事件对接上。

然后我们要知道,外部每次调用setControl,其实都是实例化了一个导出类A,与这个实例之间进行信号交换。我们需要在这个类中声明一个静态数组,用于每次实例化这样一个对象的时候将所有的对象记录在案,以供调用。

然后我们可以通过一个总的COM管理类Main_Activerserver_Demo来管理这些实例化对象,比如让所有的对象发送消息

具体你想怎么操作都行,这里就不表了。

这里你可能会问,那我怎么让这个管理类Main_Activerserver_Demo接收外部进程的消息?它怎么知道信号什么时候来,怎么知道什么时候有新的实例会来?当然了,我们不知道,于是只能借助外部的一个信号中转站SignalCenter,并建立一个单例,以类似

的形式来广播通知让所有能看到SignalCenter的实例接收到消息...目前的想法是这样,也许后面会有更好的方案,但这个不是重点。

more?剩下的只有愉快的交流就完事了

Qt开发Active控件:如何使用ActiveQt Server开发大型软件的主框架(2)的更多相关文章

  1. CAD控件:QT开发使用控件入门

    1. 环境搭建: 3 1.1. 安装Qt 3 1.2. 安装Microsoft Windows SDK的调试包 6 2. QT中使用MxDraw控件 7 1.3. 引入控件 7 3. 打开DWG文件 ...

  2. paper 139:qt超强绘图控件qwt - 安装及配置

    qwt是一个基于LGPL版权协议的开源项目, 可生成各种统计图.它为具有技术专业背景的程序提供GUI组件和一组实用类,其目标是以基于2D方式的窗体部件来显示数据, 数据源以数值,数组或一组浮点数等方式 ...

  3. 用C#开发ActiveX控件,并使用web调用

    入职差不多两个月了,由学生慢慢向职场人做转变,也慢慢的积累知识,不断的更新自己.最近的一个项目里边,涉及到的一些问题,因为SDK提供的只是winform才能使用了,但是有需求咱们必须得完成啊,所以涉及 ...

  4. IE8下调用Active控件

    之前在IE6下运行正常的Active控件,浏览器升级到IE8后全部失效,并呈浏览器崩溃状. 网上搜了一圈得到如下解决方法: 1.设置信任站点 2.还需要在IE浏览器菜单 “工具>Internet ...

  5. ATL开发 ActiveX控件的 inf文件模板

    ATL开发 ActiveX控件的 inf文件模板    

  6. 使用C#开发ActiveX控件(新)

    前言 ActiveX控件以前也叫做OLE控件,它是微软IE支持的一种软件组件或对象,可以将其插入到Web页面中,实现在浏览器端执行动态程序功能,以增强浏览器端的动态处理能力.通常ActiveX控件都是 ...

  7. IOS学习资源收集--开发UI控件相关

    收集的一些本人了解过的iOS开发UI控件相关的代码资源(本文持续补充更新) 内容大纲: 1.本人在github上也上传了我分装好的一些可重复利用的UI控件 2.计时相关的自定义UILabel控件 正文 ...

  8. HMI开发与控件

    =>控件是什么概念? 百度曰,控件是对数据和方法的封装.控件可以有自己的属性和方法.属性是控件数据的简单访问者. 对于HMI开发来说,使用控件可以快速获取到用户的交互(包括按下.释放.点击.拖动 ...

  9. [转]C#开发ActiveX控件,.NET开发OCX控件案例

    引自:百度   http://hi.baidu.com/yanzuoguang/blog/item/fe11974edf52873aaec3ab42.html 讲下什么是ActiveX控件,到底有什么 ...

  10. Excel中的表单控件和active控件

    EXCEL中有两种控件:表单控件和active控件 表单控件是excel5和excel95开始使用的,从excel97开始,active控件开始出现 关于表单控件和active控件的区别和使用范围,网 ...

随机推荐

  1. Logstash:为 Logstash 日志启动索引生命周期管理

    文章转载自:https://elasticstack.blog.csdn.net/article/details/110816948

  2. core-js/modules/es.error.cause.js 报错

    解决方法: 1.先删除 node_modules 依赖 npm rm -rf node_modules 2.首先安装 报错的插件 npm install --save core-js 3.最后再 np ...

  3. 跟我学Python图像处理丨带你掌握傅里叶变换原理及实现

    摘要:傅里叶变换主要是将时间域上的信号转变为频率域上的信号,用来进行图像除噪.图像增强等处理. 本文分享自华为云社区<[Python图像处理] 二十二.Python图像傅里叶变换原理及实现> ...

  4. 2>&1到底是什么意思?

    java -jar snapshot.jar > snapshot.log 2>&1 & 写Java的朋友一定对上面的命令很熟悉,相信大部分人都知道>表示的是重定向, ...

  5. Petrozavodsk Winter Training Camp 2016: Moscow SU Trinity Contest

    题目列表 A.ABBA E.Elvis Presley G. Biological Software Utilities J. Burnished Security Updates A.ABBA 题意 ...

  6. 锐捷网关交换机开启dhcp服务

    锐捷网关交换机作为dhcp server: Ruijie(config)#service dhcp        ------>该命令默认不启用,交换机必须配置 Ruijie(config)#i ...

  7. POJ3662 [USACO08JAN]Telephone Lines (二分答案/分层图求最短路)

    这道题目有两种解法: 1.将每个点视为一个二元组(x,p),表示从起点到x有p条路径免费,相当于构建了一张分层图,N*k个节点,P*k条边.在这张图上用优先队列优化的SPFA算法求解,注意这里的d数组 ...

  8. Docker | 容器互联互通

    上篇讲到创建自定义网络,我创建了 mynet 网络,并指定了网关和子网地址.在上篇结尾呢,我抛出了一个问题:其它网络下的容器可以直接访问mynet网络下的容器吗?今天就让我们一块看下怎么实现容器互联. ...

  9. Vue中组件化编码使用、实现组件之间的参数传递(实战练习二)

    上一章节实现的是静态页面的设计.这一章节实现将数据抽取出来.通过组件间参数的传递来实现 上一章节链接地址:https://blog.csdn.net/weixin_43304253/article/d ...

  10. 彻底学会Selenium元素定位

    转载请注明出处️ 作者:测试蔡坨坨 原文链接:caituotuo.top/63099961.html 你好,我是测试蔡坨坨. 最近收到不少初学UI自动化测试的小伙伴私信,对于元素的定位还是有些头疼,总 ...