COM 是一种软件创建中可重用组件的规范准则,现代的 Windows 程序中有许多地方都会使用到 COM 组件,例如:

  • Graphics(Direct2D
  • Text(DirectWrite)
  • The Windows Shell
  • The Ribbon control
  • UI animation

上述列表中的使用的技术是 COM 标准的一个子集,并不是纯的 COM 标准组件。

COM 组件 以难以学习著称,但是如果你仅仅是使用现有 COM 组件,其实并不会给你造成很多困扰。

本章节主要介绍在程序中如何使用 COM 组件,并简单的介绍一下相关的理论知识。理解 COM 组件设计背后的原因,会有利于编程实践。

COM 在 1993 年被引入用来支持对象链接技术( Object Linking)和 OLE(Embedding ) 嵌入式技术。因为 OLE 是建立在 COM 组件技术基础之上,所以一些人会感觉 COM 组件的门槛非常高。其实学习 COM组件并不需要掌握 OLE 技术。

COM 组件是一个二进制标准,并不是一个语言标准。它定义了应用程序和软件组件之间的二进制接口。作为一个二进制标准,COM 组件 是跨语言的。本章内容有几个关注点:

  • 对象接口和实现的分离。

  • 管理对象的生命周期。

  • 运行期间发现对象具有的功能。

什么是 COM 接口?
如果你了解 C# 或者 Java 语言,接口就会是一个非常熟悉的概念。接口是一个对象上一组操作的集合,不涉及任何实现的细节,接口标志着方法和实现的分离。计算机中这种现象叫做解耦(decoupled)。
初始化 COM 组件库
任何 Windows 程序在使用 COM 组件 前都必须调用 CoInitializeEx 函数初始化。使用 COM 接口 的每个线程都需要执行这个初始化步骤, CoInitializeEx 函数的声明如下。
COM 组件中的错误码
COM 组件 中的函数一般返回值都是 HRESULT 类型,该值代表着 COM 接口 调用的结果正确与否。HRESULT是一个32位的整型值。其中最高位代表着成功还是失败。0 表示成功,1 表示失败。
创建 COM 组件对象
当在线程内初始化 COM 组件 库之后就可以安全的调用 COM 接口了。如果想要使用 COM 接口,你的程序首先创建一个实现该接口的对象。
打开一个对话框
Windows 操作系统内部提供了大量的 COM 接口,为了在程序中打开一对话框,可以使用一个叫做 Common Item Dialog 的 COM 组件。
管理对象的生命周期
COM 接口 还有一个规则在上面的信息中没有提及,这就是每个 COM 接口都必须直接的或者间接的继承一个叫做 IUnknown 的接口类。这个接口为 COM 组件提供一些底层的功能支持。
查询COM组件接口
我们已经知道了一个对象可以实现一个或多个接口,在上面对话框的案例中,Common Item Dialog 对象实现了 IFileOpenDialog 接口,这个接口定义显示和获取选择文件的基本方法。
COM 组件的内存分配
有时候需要通过一些方法在堆上分配内存缓冲区,并将缓冲区的地址返回给调用者。为此 COM 定义了一组用来在堆上申请释放内存的函数。
COM 编码实践
本篇文章主要介绍了在使用 COM 组件中常见的一些问题,包括 __uuidof 运算符,IID_PPV_ARGS 宏的使用,以及如何安全的释放 COM 组件。
常见的错误处理方法
COM 组件中使用 HRESULT 类型的值表示方法或者函数调用的结果成功与否。各种各样的 SDK 在头文件中定义了很多不同的 HRESULT 类型的常量。