• 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);
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 首先我们看到这是一个结构体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个函数,一下节我们来实现它们的函数实体
  • 相关阅读:
    执行增删改查时获取SQL语句
    网络面试-0x08如何理解CDN?
    C++ Reference: Standard C++ Library reference: C Library: cwchar: btowc
    数据读写:Unity中基于C#脚本实现数据读写功能
    第十一章:项目风险管理
    PGP软件安装文件加密&解密&签名实践记录
    [EI复现】基于主从博弈的新型城镇配电系统产消者竞价策略(Matlab代码实现)
    Three.js-效果合成(EffectComposer)
    Spring Boot中如何接入jetcache缓存
    android-apk解包打包
  • 原文地址:https://blog.csdn.net/weixin_43716462/article/details/127653768