Windows编程之COM组件


***【在线视频教程】***

好文章,来自【福优学苑@音视频+流媒体】

Windows编程之COM组件


COM编程入门

第一部分——什么是COM,如何使用COM

    本文的目的是为刚刚接触COM的 程序员提供编程指南,并帮助他们理解COM的基本概念。内容包括COM规范简介,重要的COM术语以及如何重用现有的COM组件。本文不包括如何编写自己的COM对象和接口。


    COM即 组件对象模型,是Component Object Model                 取前三个字母的缩写,这三个字母在当今Windows的世界中随处可见。随时涌现出来的大把大把的新技术都以COM为基础。各种文档中也充斥着诸如COM对象、接口、服务器之类的术语。因此,对于一个程序员来说,不仅要掌握使用COM的方法,而且还要彻底熟悉COM的所有一切。


    本文由浅入深描述COM的内在运行机制,教你如何使用第三方提供的COM对象(以Windows   外壳组件Shell为例)。读完本文后,你就能掌握如何使用Windows操作系统中内建的组件和第三方提供的COM对象。


    本文假设你精通C++语言。在例子代码中使用了一点MFC和ATL,如果你不熟悉MFC和ATL也没关系,本文会对这些代码进行完全透彻的解释。本文包括以下几个部分:

    简单地说,COM是一种跨应用和语言共享 二进制代码的方法。与C++不同,它提倡 源代码重用。ATL便是一个很好的例证。源码级重用虽然好,但只能用于C++。它还带来了名字冲突的可能性,更不用说不断拷贝重用代码而导致工程膨胀和臃肿。

    Windows使用DLLs在二进制级共享代码。这也是Windows程序运行的关键——重用kernel32.dll,                 user32.dll等。但DLLs是针对C接口而写的,它们只能被C或理解C调用规范的语言使用。由 编程语言来负责实现共享代码,而不是由DLLs本身。这样的话DLLs的使用受到限制。

    MFC引入了另外一种MFC扩展DLLs二进制共享机制。但它的使用仍受限制——只能在MFC程序中使用。

    COM通过定义二进制标准解决了这些问题,即COM明确指出二进制模块(DLLs和EXEs)必须被编译成与指定的结构匹配。这个标准也确切规定了在内存中如何组织COM对象。COM定义的二进制标准还必须独立于任何编程语言(如C++中的命名修饰)。一旦满足了这些条件,就可以轻松地从任何编程语言中存取这些模块。由 编译器负责所产生的 二进制代码与标准兼容。这样使后来的人就能更容易地使用这些 二进制代码。

    在内存中,COM对象的这种标准形式在C++ 虚函数中偶尔用到,所以这就是为什么许多COM代码使用C++的原因。但是记住,编写模块所用的语言是无关的,因为结果 二进制代码为所有语言可用。

此外,COM不是Win32特有的。从理论上讲,它可以被移植到Unix或其它操作系统。但是我好像还从来没有在Windows以外的地方听说过COM。


什么是COM接口?

    COM即Component Object Model,到底是用来干啥的呢?

    如果你了解Java或者C#,你应该会很了解interface。

    在C++中,最接近接口概念的应该是虚类了,所谓虚类,就是只包含虚函数的类。下面是接口的例子 


// The following is not actual COM.
// Pseudo-C++:
interface IDrawable
{
    void Draw();
};

IDrawable这个接口定义了任何可绘制的对象必须支持的方法,(顺便说一句,接口的名字必须以I开头)。

在这个接口中,IDrawable接口定义了一个最简单的操作:Draw。所有的接口都是抽象的,故而下面的代码是不能够编译的。


IDrawable draw;

draw.Draw();


在C++中,虚类的实现主要依靠多态:


class Shape : public IDrawable
{
public:
    virtual void Draw();    // Override Draw and provide implementation.
};
class Bitmap : public IDrawable
{
public:
    virtual void Draw();    // Override Draw and provide implementation.
};


 Shape Bitmap类定义了两个完全不同的可绘制对象。每一个类继承IDrawable类并且重写了类里面的虚函数。任何使用IDrawable的程序必须通过IDrawable指针来处理Shape和Bitmap,而不是直接定义Shape 或Bitmap的指针。

IDrawable *pDrawable = CreateTriangleShape();
if (pDrawable)
{
    pDrawable->Draw();
}

下面是一个IDrawablez指针数组的循环。数组可能没有明确的分类(shapes,bitmaps或者其它),但他们都继承IDrawable类。

void DrawSomeShapes(IDrawable **drawableArray, size_t count)
{
    for (size_t i = 0; i < count; i++)
    {
        drawableArray[i]->Draw();
    }
}


    COM最重要的一点就是调用代码从来看不到派生类。换句话说,你不能够在你的code中声明Shape或者Bitmap类型。所有关于Shape or Bitmap 的操作都是通过使用IDrawable指针实现的。通过这种方式,COM能够保持接口和实现的分隔,从而实现多态。需要注意的是,上面的代码并不是真正的COM代码,它们只是为了解释说明COM。

当你使用COM的时候,你要记住接口不是对象!不同的对象能够实现同一个接口,同一个对象也能够实现不同的接口。


// An interface for serialization.
class ISerializable
{
public:
    virtual void Load(PCWSTR filename) = 0;    // Load from file.
    virtual void Save(PCWSTR filename) = 0;    // Save to file.
};
// Declarations of drawable object types.
class Shape : public IDrawable
{
    ...
};
class Bitmap : public IDrawable, public ISerializable
{
    ...
};

Ok,就介绍到这里。


好文章,来自【福优学苑@音视频+流媒体】
***【在线视频教程】***