COM 组件设计与应用(二)——GUID 和 接口
书接上回,话说在 doc(Word) 复合文件中,已经解决了保存 xls(Excel) 数据的问题了。那么,接下来又要解决另一个问题:当 WORD 程序读取复合文件,遇到了 xls 数据的时候,它该如何启动 Excel 呢?启动后,又如何让 Excel 自己去读入、解析、显示 xls 数据呢?
图一、CLSID 的概念
DWORD Data1; // 随机数
WORD Data2; // 和时间相关
WORD Data3; // 和时间相关
BYTE Data4[8]; // 和网卡MAC相关
} GUID;
typedef GUID CLSID; // 组件ID
typedef GUID IID; // 接口ID
#define REFCLSID const CLSID &
// 常见的声明和赋值方法
CLSID CLSID_Excel = {0x00024500,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
struct __declspec(uuid("00024500-0000-0000-C000-000000000046")) CLSID_Excel;
class DECLSPEC_UUID("00024500-0000-0000-C000-000000000046") CLSID_Excel;
// 注册表中的表示方法
{00024500-0000-0000-C000-000000000046} 用一个号码间接表示程序名,的确是个 Good idea,实现了组件位置的透明性,并方便地扩展出 DCOM(远程组件)。但,但,但,但.....CLSID 有16个字节共128位二进制数,干吗用这么长的数字呀?遥想当年......我还在上幼儿园的时候,人们设计了 socket,用 TCP/IP 协议进行网络通讯。每个参与通讯的计算机都有一个4字节的 IP 表示编号地址,范围是 0,0,0,0 ~ 255,255,255,255 共42亿个地址。可是没想到啊,没想到,自从 Internet 选择了TCP/IP 协议后,42亿个地址就不够全世界的劳动人民分配啦。除了劳动人民,还有冰箱、彩电、电饭锅、手机、手提电脑......这些都需要连网呀。在办公室通过网络开启电饭锅给我焖饭,下班回家后就能吃现成的啦,多幸福呀?!(注:在我们家老婆是领导,所以是我做饭。咳......)
你可以手工写 CLSID,但千万不要和人家已经生成的 CLSID 重复呀,所以严重地不推荐;(可是微软的CLSID都是手工写的,这叫“只许州官放火,不许百姓点灯”) ;
程序中,可以用函数 CoCreateGuid() 产生 CLSID;
使用工具产生 GUID(注2);
vc6.0版本运行:"vc目录\Common\Tools\GuidGen.exe"程序(你可以参照上回文章中介绍的方法,把这个工具程序加到开发环境中,方便调用)。vc.net版本,在菜单“工具\创建GUID”中,就可以执行了。
四、ProgID 概念
CLSIDFromProgID()、CLSIDFromProgIDEx() 由 ProgID 得到 CLSID。没什么好说的,你自己都可以写,查注册表贝
ProgIDFromCLSID() 由 CLSID 得到 ProgID,调用者使用完成后要释放 ProgID 的内存(注5)
CoCreateGuid() 随机生成一个 GUID
IsEqualGUID()、IsEqualCLSID()、IsEqualIID() 比较2个ID是否相等
StringFromCLSID()、StringFromGUID2()、StringFromIID() 由 CLSID,IID 得到注册表中CLSID样式的字符串,注意释放内存
图二、VTAB 的结构
图三、多个 VTAB 的结构
图四、COM 接口结构
图五、COM 接口结构的简洁图示
六、接口(Interface)概念
2、假设有一个指针型变量保存着 VTAB 的首地址,则这个变量就叫“接口指针”(注6), 变量命名的时候,习惯上加上"I"开头。另外为了区分不同的接口,每个接口 也都要有一个名字,该名字就和 CLSID 一样,使用 GUID 方式,叫 IID。
3、接口一经发表,就不能再修改了。不然就会出现向前兼容的问题。这个性质叫“接口不变性”。
4、组件中必须有3个函数,QueryInterface、AddRef、Release,它们3个函数也组成一个接口,叫"IUnknown"。(注7)
5、任何接口,其实都包含了 IUnknown 接口。随着你接触到更多的接口就会了更体会解到接口的另一个性质“继承性”。
6、在任何接口上,调用表中的第一个函数,其实就是调用 QueryInterface()函数,就得到你想要的另外一个接口指针。这个性质叫“接口的传递性”
7、C/C++语言中需要事先对函数声明,那么就 会要求组件也必须提供C语言的头文件。不行!为了能使COM具有跨语言的能力,决定不再为任何语言提供对应的函数接口声明,而是独立地提供一个叫类型库(TLB)的声明。每个语言的IDE环境自己去根据TLB生成自己语言需要的包装。这个性质叫“接口声明的独立性”(注8)
容器 协商部分 组件 应答部分
1 根据CLSID启动组件 。
CoCreateInstance() 生成对象,执行构造函数,执行初始化动作。
2 你有IUnknown接口吗? 有,给你!
3 恩,太好了,那么你有IPersistStorage接口吗?(注9)
IUnknown::QueryInterface(IID_IPersistStorage...) 没有!
4 真差劲,连这个都没有。那你有IPersistStreamInit接口吗?(注10)
IUnknown::QueryInterface(IID_IPersistStreamInit...) 哈,这个有,给!
5 好,好,这还差不多。你现在给我初始化吧。
IPersistStreamInit::InitNew() OK,初始化完成了。
6 完成了?好!现在你读数据去吧。
IPersistStreamInit::Load() 读完啦。我根据数据,已经在窗口中显示出来了。
7 好,现在咱们各自处理用户的鼠标、键盘消息吧...... ......
8 哎呀!用户要保存退出程序了。你的数据被用户修改了吗?
IPersistStreamInit::IsDirty() 改了,用户已经修改啦。
9 那好,那么用户修改后,你的数据需要多大的存储空间呀?
IPersistStreamInit::GetSizeMax() 恩,我算算呀......好了,总共需要500KB。
10 晕,你这么个小玩意居然占用这么大空间?!......好了,你可以存了。
IPersistStreamInit::Save() 谢谢,我已经存好了。
11 恩。拜拜了您那。(注11)
IPersistStreamInit::Release();IUnknown::Release() 执行析构函数,删除对象。
12 我自己也该退出了......
PostQuitMessage()
1、IDispatch 接口的 IID 是多少?(哎~~~ 笨笨,在源程序中,用鼠标右键执行Go to definition 呀)
2、IPicture 接口有几个函数?功能是什么?(别玩了!你多大了?想不想在程序中显示 JPG 图像呀,看 MSDN 去)
想知道为什么COM函数总是返回 HRESULT 吗?想知道如何使用 BSTR、VARIANT 吗?想知道 COM 中应该如何使用内存吗?想知道如何使用 UNICODE 吗?......恩~~~,我现在不能告诉你,我现在告诉你,怕你印象不深!且听下回分解......
图一、CLSID 的概念
"d:\Program files\Microsoft Office\Office\Excel.exe",完蛋了:-(
于是,微软想出了一个解决方案,那就是不使用直接的路径表示方法,而使用一个叫 CLSID(注1)的方式间接描述这些对象数据的处理程序路径。CLSID 其实就是一个号码,或者说是一个16字节的数。观察注册表(上图),在HKCR\CLSID\{......}主键下,LocalServer32(DLL组件使用InprocServer32) 中保存着程序路径名称。
转载于:https://blog.51cto.com/studoc/281688
COM 组件设计与应用(二)——GUID 和 接口相关推荐
- LED显示屏二次开发接口的设计方案
引言 在LED 显示屏工程应用中,有单块显示屏项目,但更多的是多块显示屏项目.对于单块显示屏,直接使用厂商配置的控制软件就满足要求了:但对于多块显示屏,尤其是系统集成项目,厂商配置的控制软件就很难满足 ...
- 【转载】COM 组件设计与应用(二)——GUID 和 接口
原文:http://vckbase.com/index.php/wv/1203.html COM 组件设计与应用 系列文章:http://vckbase.com/index.php/piwz?& ...
- JAVA组件设计原则(二)原则一:精准解决共性问题(摘自《java组件设计》)
组件定位:精准解决共性问题 组件的产生,来源于软件工程实践中,对重复.反复出现.普遍的.有相似性的问题进行分析,剥离掉各个问题的特性,抽取各个问题之间的共性,然后确定要设计一个或多个组件,这样 ...
- COM组件设计与应用(三)(转载)
COM组件设计与应用(三) 数据类型 作者:杨老师 一.前言 上回书介绍了GUID.CLSID.IID和接口的概念.本回的重点是介绍 COM 中的数据类型.咋还不介绍组件程序的设计步骤呀?咳..... ...
- COM 组件设计与应用
目录 COM 组件设计与应用(一) 起源及复合文件... 1 COM组件设计与应用(二) GUID 和 接口... 10 COM组件设计与应用(三) 数据类型... 20 COM组件设计与应用(四) ...
- ueditor上传组件显示乱码_最全面的移动端 UI组件设计详解:中篇
上一期给大家讲解了<最全面的移动端UI组件设计详解:上篇>,主要分享了:布局组件和导航组件2个部分:这次给大家带来:基础组件.表单组件和反馈组件详解,希望你在设计APP.小程序.H5页面中 ...
- COM 组件设计与应用(六)——用 ATL 写第一个组件(vc.net)
一.前言 1.与 <COM 组件设计与应用(五)>的内容基本一致.但本回讲解的是在 vc.net 2003 下的使用方法,即使你不再使用vc6.0,也请和上一回的内容,参照比对. 2.这第 ...
- vue 新手指引_精通react/vue组件设计之快速实现一个可定制的进度条组件
前言 这篇文章是笔者写组件设计的第四篇文章,之所以会写组件设计相关的文章,是因为作为一名前端优秀的前端工程师,面对各种繁琐而重复的工作,我们不应该按部就班的去"辛勤劳动",而是要根 ...
- COM 组件设计与应用(一)
COM 组件设计与应用(一) 起源及复合文件 作者:杨老师 一.前言 公元一九九五年某个夜黑风高的晚上,我的一位老师跟我说:"小杨呀,以后写程序就和搭积木一样啦.你赶快学习一些OLE的技术吧 ...
- react ui框架 移动端_你必须要知道的移动端UI组件设计宝典
作为一名UI设计师,我们经常要进行PC端和移动端的设计任务,上一次给大家分享了: <最全Web端UI组件设计详解> ,这次给大家带来移动端UI组件设计详情,尤其在我们APP.小程序.H5页 ...
最新文章
- outlook正在与服务器联系以获取信息,Outlook 2016点击邮件显示正在与服务器联系以获取信息...
- linux shell 符号 变量 参数表示
- 基于opencv的手写数字字符识别
- 釜底抽薪:掌控能源成本,根治企业能源损耗
- 基于深度学习的多目标跟踪算法——ReID与MOT的联系
- Unity3D中关于场景销毁时事件调用顺序的一点记录
- AlertDialog Unable to add window token null is
- Mysql-锁/隔离级别
- 学会提问pdf_原来只要1分钟,Word、PPT、PDF文件就能随意互相转换,快学学
- sonar小白式入门
- Eclipse 使用的注意 灵格斯 取词
- 计算机网络自顶向下第七版第四章答案,《计算机网络·自顶向下方法》第七版 第四章 课后习题与问题 答案...
- 大数据整体技术流程及架构
- 计算机软件工程师考试试题,计算机考试软件工程师试题
- linux sar使用方法,Linux系列之SAR命令使用详解-Go语言中文社区
- 最好听的男孩名字及1000个好听的女孩的名字
- win10家庭版如何修改用户名对应的文件夹的名字(中文该成英文字符)
- 狗狗最近不爱吃饭了,还好有办法应对
- MindManager2022免序列号弹窗解除功能限制
- @keyup.enter.native不生效?看看@keyup.enter.native和@keyup.enter的区别和使用
热门文章
- 网站性能提高之国外空间
- (转)多因子模型水平测试题
- 怎样让vSAN发挥出高性能、低延迟的威力?
- 【优化算法】饥饿游戏搜索算法(HGS)【含Matlab源码 1802期】
- 【数字基带信号】基于matlab数字基带信号波形仿真【含Matlab源码 988期】
- 【多目标优化求解】基于matlab蜻蜓算法求解多目标优化问题【含Matlab源码 477期】
- canvas贝塞尔曲线爱心_HTML5 Canvas 绘制贝塞尔曲线 Bezier and quadratic curves
- python to datetime_Python中缺少datetime.timedelta.to_seconds()-float?
- python list拆分_python里如何把一个list分成两个
- Bootstrap模态框中再嵌套模态框导致第一个模态框的滚动条消失