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. 升级Gogs版本

    今天早上收到阿里云发的报警短信,大致内容如下: 前提分析: 公司代码代码仓库使用是Gogs搭建的,版本是0.11.34,二进制方式安装的,连接的是其他主机上的MySQL数据库,因此被检测到有这个漏洞 ...

  2. 关于HM NISEDIT在新版系统下编译并运行提示权限不足问题的解决方案

    如果你使用过NSIS为你的项目制作过安装包,那HM nisedit一定是你绕不过去的槛,作为NSIS号称的最佳免费IDE/编辑器,功能齐全,与NSIS配合性能强悍,实至名归.只是开发作者最后版本更新在 ...

  3. mac通过docker一键部署Jenkins

    目录 mac通过docker一键部署Jenkins 一.前言 二.系统配置 三.安装步骤 Dockerhub查看镜像地址 1.一键安装 1.1.下载脚本 1.2.安装程序 1.2.1.安装程序详情 1 ...

  4. day05多表查询01

    多表查询 前面讲过的基本查询都是对一张表进行查询,但在实际的开发中远远不够. 下面使用表emp,dept,salgrade进行多表查询 emp: dept: salgrade: 1.前置-mysql表 ...

  5. 【Spring boot】整合tomcat底层原理

    本文结论 源码基于spring boot2.6.6 项目的pom.xml中存在spring-boot-starter-web的时候,在项目启动时候就会自动启动一个Tomcat. 自动配置类Servle ...

  6. 6.MongoDB系列之特殊索引和集合类型

    1. 地理空间索引及全文搜索 与Elasitcsearch一样,MongoDB同样支持地理空间索引及全文搜索,由于选型常用ES而非MongoDB此处略过 2. TTL索引 首先先了解下固定集合,其类似 ...

  7. uoj348【WC2018】州区划分

    题目链接 直接讲吨吨吨给的标准做法吧.记\(f(i,j)\)表示各个州(可以重叠)的城市数量之和为i,这些州的并集为j的方案数,反正若有两个州之间有交集最后的\(|j|\)会不等于\(i\).有 \( ...

  8. Request method ‘POST‘ not supported。 Failed to load resource: net::ERR_FAILED

    1.问题描述 技术栈:前后端项目分离(Springboot+Vue+MybatisPlus) 前端报错信息: 后端报错信息: 2.问题分析 这里使用了ResultFul风格的接口设计方式.增删改查对应 ...

  9. 一天五道Java面试题----第十一天(分布式架构下,Session共享有什么方案--------->分布式事务解决方案)

    这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 1.分布式架构下,Session共享有什么方案 2.简述你对RPC.RMI的理解 3.分布式id生成方案 4.分布式锁解决 ...

  10. 你应该知道的数仓安全:都是同名Schema惹的祸

    摘要:我是管理员账号,怎么还没有权限?当小伙伴询问的时候,我第一时间就会想到都是用户同名Schema惹的祸 本文分享自华为云社区<你应该知道的数仓安全--都是同名Schema惹的祸>,作者 ...