IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> CorelDRAWX4的C++插件开发(四十)纯C++插件开发(4)继承插件结构体IVGAppPlugin和自动化接口IDispatch -> 正文阅读

[系统运维]CorelDRAWX4的C++插件开发(四十)纯C++插件开发(4)继承插件结构体IVGAppPlugin和自动化接口IDispatch

  • 因为在注册插件的时候,是要传一个名为IDispatch*这样子的一个参数,所以我们可以看到插件在注册的时候默认就是要求这是一个实现了自动化的接口(IDispatch,如下图所示,是后面将要展示的代码,先拎出来讲一下),可以看到参数(IDispatch * EventSink)这实际上就是注册插件时需要提供的自动化的接口IDispatch的地址指针,所以我们在继承了插件结构体时还要实现自动化接口(IDispatch).
    在这里插入图片描述
  • 自动化接口IDispatch接口不过就是未知接口IUnknown接口的扩展
  • 首先大略说一下关于未知接口IUnknown,因为主程序CDR在运行过程中突然要加载我们写的插件程序,然而CDR主程序并不知道我们这些后来人写的是些啥程序,所以他根本不知道调用我们会运行出现什么,所以这个就是这个接口名字含义的由来,他只是用来呼唤我们用的,至于呼唤出来的是个什么东西它完全不知道,所以叫作未知接口,英文IUnknown更直接:“我不知道”…
  • 拆分IUnknown里面就是三个函数,分别是QueryInterface,AddRefRelease,第一个函数QueryInterface是查询接口,也是IUnknown的第一个函数,这是固定的,任何其它的IUnknown接口,第一个函数都是QueryInterface,它是用来确定查询接口用的,第二个AddRef增加和第三个Release减少分别是计数用的,用以确认这个接口的寿命,是实现自动化的一部分.
  • IDispatch就是在IUnknown的基础上再增加四个函数,分别是GetTypeInfoCount,GetTypeInfo,GetIDsOfNamesInvoke,这四个个函数就排在IUnknown三个函数后面形成一个自动化接口,有了这四个函数这个接口就不再是未知接口了,而是能够获取当前的函数个数,函数名称,ID和具体实现了一些什么功能等等.
    在这里插入图片描述
  • 接下来我们就开始创建结构体
struct CongLingKaiShi :public VGCore::IVGAppPlugin {
public:
	// IVGAppPlugin CDR主程序启动的 4 个函数
	virtual HRESULT __stdcall raw_OnLoad(VGCore::IVGApplication* Application);
	virtual HRESULT __stdcall raw_StartSession();
	virtual HRESULT __stdcall raw_StopSession();
	virtual HRESULT __stdcall raw_OnUnload();
public:
	// IUnknown 未知接口 3 个函数
	virtual HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject);
	virtual ULONG __stdcall AddRef(void) {return 1;}
	virtual ULONG __stdcall Release(void) {return 1;}
public:
	// IDispatch 调度接口 4 个函数
	virtual HRESULT __stdcall GetTypeInfoCount(UINT* pctinfo) { return E_NOTIMPL; }
	virtual HRESULT __stdcall GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) { return E_NOTIMPL; }
	virtual HRESULT __stdcall GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) { return E_NOTIMPL; }
	virtual HRESULT __stdcall Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr);
};
  • 首先我们看到这是一个结构体struct也就是结构体对象生成之前的模板
  • 结构体的名字叫作CongLingKaiShi
  • 后面跟上的冒号:public VGCore::IVGAppPlugin就是说CongLingKaiShi这个结构体要继承冒号后面的VGCore::IVGAppPlugin结构体,
  • public是描述继承形式为公有继承,也就是爷爷的财产(除私人物品)儿子和孙辈可以使用或分配给任何人
  • 顺带再说private私有继承,也就是爷爷的财产(除私人物品)儿子可以使用或分配给任何人,但孙子辈看不到
  • 另一个protected保护继承,也就是爷爷的财产(除私人物品)只有子子孙孙及其挚友能自己使用,无权给其它外人
  • 所以没有这些要求的话一般都是公有继承public,然后可以看到结构体里面还有四个public:这些都定义为公有成员
  • 然后我们可以看到一共有11个virtual 开头的虚函数,这11个函数怎么来的呢,我们可以打开vgcoreauto.tlh文件,查到定位到IVGAppPlugin这个函数体,如下图所示
    在这里插入图片描述
  • 可以看到下方有四个=0为结尾的纯虚函数,然后可以看到IVGAppPlugin后面紧跟着一个: IDispatch,说明IVGAppPlugin还继承了IDispatch这个结构体,而在IDispatch中就包含了GetTypeInfoCountGetTypeInfoGetIDsOfNamesInvoke四这个纯虚函数,如下图
    在这里插入图片描述
  • 然后我们看到IDispatch : public IUnknownIDispatch 这个自动化接口结构体又继承了IUnknown未知接口结构体中的三个纯虚函数QueryInterfaceAddRefRelease,如下图
    在这里插入图片描述
  • 以上就是11个纯虚函数的由来,所以当我们的结构体CongLingKaiShi 继承了一个VGCore::IVGAppPlugin的时候,实际上我们就一次性继承了11个纯虚函数,而纯虚函数是必须被实例化的,因为纯虚函数在基类是没有实体的(基类纯虚函数在基类中免写实体并方便基类指针多态访问派生类要写实体的虚函数,这句话有点拗口,反正就是要把这些函数全都实现一遍就好了)
  • virtual是表示这个函数是虚函数,它一定是派生出来的结构体或者类当中的同名函数,是另外在程序的虚函数表中进行维护的
  • HRESULT 是函数返回值,是一个无符号的长整数,跟ULONG类似的,它一般就是大于等于0的长整数long
  • __stdcall 是标准呼叫,里面规定了出栈和入栈的顺序等等
  • raw_OnLoad(VGCore::IVGApplication* Application)第是第一个函数,也是最重要的一个函数,名称为raw_OnLoad,就是在CDR主程序加载成功的时候,主程序会启动这个函数,然后把最重要的VGCore::IVGApplication* Application这个主程序的根结构体Application传过来.然后我们就可以通过这个Application操作当前的CDR主程序了,因为所有的东西都是封装在这个Application里面.(Application在三十二章里面详细讲过了)
  • 然后raw_StartSession也差不多类似是内部启动完毕之后会加载的函数,启动时间在raw_OnLoad之后
  • raw_StopSessionraw_OnUnload就是在关闭CDR的时候执行的函数了,可以把一些卸载类的功能放在这里面
  • 后面就是IDispatch的七个虚函数了,AddRefRelease是生存周期用的,我们的插件程序生存周期和主程序同步,所以不需要管他,直接返回1
  • 然后GetTypeInfoCountGetTypeInfo以及GetIDsOfNames我们就直接返回E_NOTIMPL没有实现该接口,因为这些都是给动态语言后绑定用的,我们并不需要
  • 除了上面5个用不上用的,后面我们主要就是要实现Invoke等其余6个函数,一下节我们来实现它们的函数实体
  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-11-05 00:57:57  更:2022-11-05 01:00:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 19:48:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码