你的客户端程序必须实现ActiveX文档服务.也就是说必须支持ActiveX Document实现4个接口:
IOleDocumentSite
IOleClientSite
IOleInPlaceSite
IOleInPlaceFrame

解决方案 »

  1.   

    ActiveX文档技术    ActiveX文档是Microsoft在OLE文档的基础上,结合Internet发展
    而成的,它是一种可以从Web服务器下载的特殊文档类型,当浏览器发
    现ActiveX文档文件时,它自动从硬盘上装入对应的ActiveX文档服务
    程序,并且服务程序接管了整个浏览器窗口,用以显示文档的内容,用
    户可以查看文档的内容,也可以编辑文档,但不能上载回服务器。例如
    ,我们在In ternet Explorer 3.0或更高版本的浏览器中访问Web服务
    器上的Excel文件(.xls)时,只要本地硬盘上安装了Microsoft Excel
    电子表格软件,浏览器就会利用Excel打开.xls文件,并且Excel软件界
    面和浏览器界面结合在一起。对用户来说,除了启动程序时有一点延
    时之外,感觉不到有两个独立的程序在运行,而且,浏览器中的历史记
    录也会把该文档作为W eb页面记录下来,以后"后退"时仍然可以回到
    该页面。
    图1 ActiveX文档示例图和(a)ActiveX文档
        本文试着从技术的角度对ActiveX文档作一介绍。
        一、ActiveX文档特性
        ActiveX文档(如图1)是在OLE文档的基础上发展起来的,因此,有
    必要对OLE文档(包括嵌入和链接两种情况)和ActiveX文档作一比较。
        OLE文档的服务程序在OLE包容器程序的子窗口中运行,并占有包
    容器文档视图的一个矩形区域,当文档对象被激活时,服务程序接管了
    包容器程序的菜单和工具条;而ActiveX 文档服务程序则接管了包容
    器应用的整个框架窗口,并且文档总是处于活动状态。运行在包容器
    框架窗口中的ActiveX文档服务程序,其运行方式与它单独运行的模式
    基本一样。我们可以从图2看出这种区别显示。
    图2 ActiveX文档和OLE文档界面对照
        除了在界面特性上ActiveX文档与OLE文档有很大相似之外,Activ
    eX文档突破了OLE文档的桌面环境,进一步可以与浏览器(即Microsoft
     Internet Explorer)结合起来,如图1 所示,在IE中可以直接打开远
    程Web站点上的文档文件,我们只需给出一个URL,比如:http
        //www.someone.com/example.doc,于是浏览器会在其窗口中打开
    Microsoft Word文档,而且Word会接管浏览器的菜单和工具条。当然,
    前提条件是机器上已经安装了Micros oft Word程序,如果没有安装的
    话,浏览器会提示下载文档文件。
        ActiveX文档服务程序不允许把修改过的结果存回到Internet机
    器上,但可以保存在本地硬盘上。也就是说,菜单"File Save"被禁止,
    而"File Save As"则可以执行。
        ActiveX文档和ActiveX控制都是OLE技术与Internet结合之后发
    展起来的新技术,它们都是ActiveX技术体系中的重要组成部分,而且,
    Microsoft Internet Explorer是它们共同的包容器,但在行为特性上
    两种技术有显著的区别,概括如下:
        程序类型不同 ActiveX文档的服务程序运行在自己的进程中,通
    常服务程序是一个E XE程序;而ActiveX控制通常是一个DLL或OCX程序
    ,它运行在其包容器进程中。
        界面方式不同 ActiveX文档服务程序占用浏览器的整个窗口;而A
    ctiveX控制通常只占用浏览器窗口的一个矩形区域。
        在HTML文件中的使用方式不同 ActiveX文档与HTML文件无关,但
    可以在HTML中通过超链接指向ActiveX文档文件;而ActiveX控制作为
    对象被嵌入在HTML文件中。
        数据保存方式不同 ActiveX文档服务程序可以操作磁盘文件,而A
    ctiveX控制一般不操作磁盘文件。
        服务程序转载方式不同 ActiveX控制可以自动下载并由浏览器登
    记注册,而ActiveX 文档服务程序不支持这种特性。
        ActiveX文档超越了OLE文档的桌面环境,为浏览器提供了强大的
    扩展功能,但由于在浏览器中打开ActiveX文档要求事先在客户机上装
    有ActiveX文档服务程序,所以它的使用受到了很大的限制,不过,在一
    般的企业内部网(Intranet)环境下,使用ActiveX文档技术,通过浏览
    器查看企业内部的一些资料,比起制作复杂的网页或开发专门的查询
    系统要方便、快捷得多。
        二、ActiveX文档结构模型
        ActiveX文档服务程序提供了文档的核心处理功能,包括文档的读
    写、文档的显示以及文档的编辑等,包容器程序负责创建并控制Activ
    eX文档对象,并把Web服务器上的数据通过适当的接口传递给ActiveX
    文档服务程序。由于ActiveX文档技术源于OLE文档,所以ActiveX文档
    服务程序与包容器程序之间的接口继承了OLE文档技术中采用的很多
    接口:A ctiveX文档服务程序继承了OLE文档服务程序的一些接口,包
    括IOleObject、IDataObjec t、IOleInPlaceObject和IOleInPlaceAc
    tiveObject;ActiveX文档包容器则继承了OLE文档包容器的一些接口,
    包括IOleClientSite和IOleInPlaceSite,并且,ActiveX文档的菜单协
    作过程与OLE文档的过程基本一致。
        在OLE文档结构的基础上,ActiveX文档服务程序和包容器还实现
    了另外一些接口,Ac tiveX文档服务程序实现了IOleDocument、IOleD
    ocumentView、IOleCommandTarget和IP rint接口;而ActiveX文档包
    容器则实现了IOleDocumentSite接口。
        OLE文档服务程序中最关键的函数是IOleObject::DoVerb,当用户
    双击嵌入对象或通过菜单激活嵌入对象时,包容器就会调用该函数。
    然而,对于ActiveX文档服务程序,最重要的函数是IOleDocumentView:
    :UIActivate。UIActivate找到包容器的站点(site)和框架窗口,把框
    架窗口设置为服务程序的父窗口,而且使服务程序的窗口覆盖包容器
    的框架窗口,然后激活服务程序窗口。
        在文档的数据处理方面,ActiveX文档与OLE链接对象的处理类似,
    浏览器把文档文件从Web服务器下载到本地的临时目录中,然后调用对
    象的IPersistFile::Load函数装载到ActiveX文档服务程序中。
        图3显示了ActiveX文档和包容器的接口示意。
    图3 ActiveX文档服务程序和包容器程序的接口示意
      
    ActiveX文档技术(二)    三、ActiveX文档服务程序的实现
        我们了解了ActiveX文档服务程序的接口后,就可以实现我们自己
    的ActiveX文档服务程序了,但如果直接利用Win32 API来编写代码的
    话,则完成基本框架的代码量就很大,而且有些基本的接口代码需要CO
    M(组件对象模型)原理作为背景知识才能正确编写。Micro soft Visu
    al C++ 5.0包含的MFC库(4.2版)提供了完全的框架支持,而且其集成
    环境Visu al Studio所提供的AppWizard可快速生成ActiveX文档服务
    程序的框架代码,从而大大简化基本代码的编写工作。
        在介绍MFC实现ActiveX文档服务程序的机制之前,我们先看一下M
    FC库中实现OLE文档服务程序的机制。类似于一般的MDI/SDI程序,支
    持OLE文档的OLE Server程序仍然遵循文档/视图(Doc/View)框架结构
    ,相关的类包括应用类(CWinApp派生类)、CMainFrame(CMDI FrameWnd
    派生类)、CChildFrame(CMDIChildWnd派生类)、COleServerDoc派生
    类(COleSe rverDoc为CDocument的派生类)、CView的派生类,与一般
    应用相比较,支持OLE文档服务特性需要多个类协同工作。
        1. 在CWinApp的派生类即应用类中,为支持OLE进行初始化,在Ini
    tInstance成员函数中调用AfxOleInit(),对OLE系统DLL进行初始化。
        2. CMainFrame不参与OLE过程,所以不必进行变动;但程序在OLE
    方式运行时,所使用的框架为CInPlaceFrame(从COleIPFrameWnd派生)
    ,它负责进行菜单及工具条的处理。
        3. CView派生类以及CChildFrame不受OLE的影响,所以不必变动

        4. Doc类是这些类中变化最大、也是最重要的类,其基类COleSer
    verDoc从CDocument 派生,在COleServerDoc中实现了OLE文档所必须
    的一些接口:IOleObject、IDataObject、IOleInPlaceObject、IOleI
    nPlaceActiveObject和IPersistStorage等。
        5. 为了支持OLE文档特性,AppWizard还生成了另一个从COleServ
    erItem派生的类,实际上,它代表了真正的OLE对象,它也实现了IOleOb
    ject、IDataObject接口。而且,COleS erverItem与COleServerDoc有
    很紧密的联系,通过COleServerItem::GetDocument可以获取相应的CO
    leServerDoc对象;通过COleServerDoc::GetEmbeddedItem可以获取相
    应的CO leServerItem对象。因为COleServerItem对象代表的是OLE文
    档对象,所以我们可以把读写数据处理以及对象自身的操作放在COleS
    erverItem的虚成员函数中完成,而把通用的文档操作以及对象的编辑
    操作放在COleServerDoc以及View类中完成。
        MFC对ActiveX文档的支持绝大部分继承于对OLE文档的支持,只是
    针对ActiveX文档的新特性重载和添加了一些方法,基本的结构不变。
    下面列出相应的改进。
      

  2.   

    1. 由于COleServerDoc是针对任意COM组件的,ActiveX文档侍者
    的文档类也从COleSe rverDoc派生。
        2. ActiveX文档对象在包容器程序中运行时,它所使用的框架类C
    InPlaceFrame从COl eDocIPFrameWnd派生,而COleDocIPFrameWnd类也
    是COleIPFrameWnd的派生类。在COleDo cIPFrameWnd中根据ActiveX
    文档对象的界面特性,重载了框架改变大小操作的特性(对象服务程序
    的窗口完全覆盖了包容器的框架窗口),并把它自己的菜单资源连到框
    架上。
        3. 代表文档对象的基类为CDocObjectServerItem,它从COleServ
    erItem派生。CDocO bjectServerItem类重载了一些操作特性,最主要
    的是激活操作(通过OnShow或OnOpen方法实现)。
        4. CDocObjectServer类不用于OLE文档服务程序,它实现了新的A
    ctiveX文档接口。服务程序创建一个CDocObjectServer类的对象,并
    把它与COleServerDoc对象连接起来,我们可以在派生文档类的COleSe
    rverDoc::GetDocObjectServer函数中看到其构造代码。然后,文档对
    象和与其相连的CDocObjectServer对象协同工作,共同完成ActiveX文
    档的功能。CDocObjectServer类实现了IOleDocument和IOleDocument
    View接口。通常我们不必从CD ocObjectServer派生新的类。
        图4给出了这些类协同工作的结构图。
    图4 MFC库实现ActiveX文档
        服务程序的类结构图
        四、ActiveX文档服务程序示例
        以上我们介绍了ActiveX文档的特性、其服务程序和包容器程序
    之间的模型关系,并进一步介绍了MFC对ActiveX文档的支持,现在我们
    利用Visual C++ 5.0或6.0提供的支持实现一个ActiveX文档服务例程
    序。
        如果我们从头开始创建工程,则我们可以在AppWizard生成工程的
    Step 3对话框中,选中Active Document Server选项,并在Step 4的Ad
    vanced Options指定相应的文档文件后缀名,如图5所示。完成了AppW
    izard的所有步骤后,我们就得到了一个ActiveX文档服务程序的框架,
    但没有任何实际的功能,工程中包含了上一节所介绍的各个类,我们就
    可以根据实际的需要,编写代码以实现所需的功能。限于篇幅,这里不
    再一一介绍。图5 AppWizard提供ActiveX文档特性支持
        另外一种情况是,如果我们已经写好了一个MFC程序,但它不支持A
    ctiveX文档特性,为了更好地与Internet以及浏览器协同工作,我们需
    要将其升级为ActiveX文档服务程序,这时我们可以选择两种方法:第
    一种方法,生成一个空的ActiveX文档框架工程,然后把原先工程中的
    代码移到新的框架工程中;第二种方法,对原来的工程进行改造,使其
    具有Activ eX文档特性。下面我们用一个例子来说明使用第二种方法
    的改造过程。
        本文采用的例子是Visual C++自带的例子Scribble(在Visual C+
    +光盘的Samples\M FC\Tutorial\Scribble\Step8目录下),其运行如
    图6所示。因为例子程序本身已经支持O LE文档,所以我们只要针对Ac
    tiveX文档对OLE文档所作的改进对原工程进行修改即可。( 未完待续
    )
    图6 Visual C++所带例程序Scribble的运行界面ActiveX文档技术(三)    以下是我们所作的改造步骤:
        1. 在Visual Studio中打开Scribble工程,首先在预编译头文件S
    tdafx.h中添加Acti veX文档支持所需要的头文件:
        #include
        2. 打开文件Scribitm.h和Scribitm.cpp,把CScribbleItem类的
    基类换为CDocObject ServerItem,对这两文件进行全程替换,把COleS
    erverItem换为CDocObjectServerItem即可。
        3. 打开文件IpFrame.h和IpFrame.cpp,把CInPlaceFrame类的基
    类换为COleDocIPFra meWnd,对这两文件进行全程替换,把COleIPFram
    eWnd换为COleDocIPFrameWnd即可。
        4. 打开文件Scribble.cpp,在BOOL CScribbleApp::InitInstanc
    e()函数中,把下面两行:
        EnableShellOpen();
        RegisterShellFileTypes(TRUE);
        插入在以下语句:
        m_pMainWnd- DragAcceptFiles();
        之后,并且把下面语句:
        m_server.UpdateRegistry(OAT_INPLACE_SERVER);
        改为:
        m_server.UpdateRegistry(OAT_DOC_OBJECT_SERVER);
        5. 在ScribDoc.h文件的CScribbleDoc类中加入以下成员函数:
        protected:
        virtual CDocObjectServer* GetDocObjectServer
        (LPOLEDOCUMENTSITE pDocSite)
        { return new CDocObjectServer(this, pDocSite); }
        经过上述步骤改造之后,重新编译连接得到的程序支持ActiveX文
    档特性,我们可以运行Scribble.exe程序,保存一个SCB文件(Scribb1.
    scb文件),并退出Scribble.exe程序(为了使浏览器能识别SCB文件,必
    须先单独运行一次,以便注册必要的信息);然后在Interne t Explore
    r中打开Scribb1.scb,则可以得到图1所示的结果。如果把Scribble1.
    scb放到Web服务器上,则可以通过HTTP协议在浏览器中打开远程的SCB
    文件。图1 运行在浏览器中的Scribble程序
        五、ActiveX文档包容器程序的实现
        我们再来看看ActiveX文档包容器(客户)程序的实现过程。Activ
    eX文档包容器程序必须实现4个接口:IOleDocumentSite、IOleClient
    Site、IOleInPlaceSite和IOleInPla ceFrame,其用途分别如下:
        1. IOleDocumentSite,它是ActiveX文档包容器专用的接口,可使
    ActiveX文档对象直接
        被包容器程序激活,而不必按照通常的实地(In-Place)激活对象
    的方式被激活。Act iveX文档对象调用IOleDocumentSite::ActiveMe
    成员函数激活自身,而不再调用IOleObj ect:
        :DoVerb函数。
        2. IOleClientSite,这是OLE复合文档技术使用的接口,也用于Ac
    tiveX文档技术。Ac tiveX文档包容器程序实现该接口,ActiveX文档
    对象通过该接口获取它的显示状态、显示区域的大小以及包容器提供
    的其他一些资源信息。
        3. IOleInPlaceSite,这是OLE复合文档技术使用的接口,也用于A
    ctiveX文档技术。A ctiveX文档包容器程序实现该接口,ActiveX文档
    对象通过该接口控制激活操作,在进行界面整合操作前给包容器发出
    通知。
        4. IOleInPlaceFrame,它控制包容器应用程序的主框架窗口,包
    括插入菜单项形成复合菜单、控制框架的模式等。服务程序通过IOle
    InPlaceFrame接口实现菜单的合并以及一些界面状态的控制。
        Microsoft Visual C++ 6.0包含的MFC库(6.0版)提供了完全的Ac
    tiveX文档包容器和服务程序的支持,通过AppWizard可快速生成Activ
    eX文档包容器程序的框架代码,框架程序包含了所有这些接口的实现
    。MFC库实现ActiveX文档包容器程序的结构如下:
        1. 在CWinApp的派生类即应用类中,为支持OLE进行初始化,在Ini
    tInstance成员函数中调用AfxOleInit(),对OLE系统DLL进行初始化。
        2. 虽然ActiveX文档在界面特性上与嵌入对象不太一致,但MFC中
    实现的ActiveX文档对象完全从嵌入对象继承过来,所以用以管理Acti
    veX文档对象的COleDocObjectItem类从COleClientItem(管理嵌入对
    象)派生。COleDocObjectItem类实现了新的接口IOleDocum entSite,
    并从COleClientItem继承了接口 IOleClientSite和IOleInPlaceSite
    的实现,接口IOleInPlaceFrame在COleDocObjectItem的内嵌成员m_pI
    nPlaceFrame中实现。因此,A ctiveX文档所要求的几个接口均在COle
    DocObjectItem类中实现了,而其他的类,包括CWi nApp、CDocument和
    CFrameWnd的派生类不必为支持ActiveX文档而增加新的代码。
        3. 如同处理嵌入对象一样,在CView派生类也需要增加一些管理
    操作,比如,创建Acti veX文档、激活对象、窗口大小调整等。创建对
    象可以直接调用COleClientItem::Creat eFromFile、COleClientIte
    m::CreateLinkFromFile或者COleClientItem::CreateNewIt em函数
    。在AppWizard生成的代码中,通过COleInsertDialog::CreateItem函
    数创建文档对象,读者可以根据需要改写这段代码。
        利用Visual C++的AppWizard生成包容器工程时,注意在Step 3对
    话框中,选中Activ e Document Container选项,如图2所示。完成了A
    ppWizard的所有步骤后,我们就得到了一个ActiveX文档包容器程序的
    框架,它可以通过对话框插入任何ActiveX文档,运行结果如图3所示,
    我们可以在框架代码的基础上进行改写或者增加新的代码,这里不再
    一一说明。
    图2 创建ActiveX文档包容器程序时AppWizard选项示意图
    图3 VC新建的ActiveX文档包容器程序运行示意图
        六、结束语
        本文介绍了ActiveX文档的特性和结构,并简单描述了MFC库所提
    供的支持,通过例子说明了实现ActiveX文档特性并不复杂。这种特性
    可以使一个应用与Internet/Intranet 联系起来,也从另一方面为浏
    览器提供了扩展功能,在Internet网络不断发展的今天,Act iveX文档
    特性为我们的应用走进Internet/Intranet提供了捷径。(
      

  3.   

    如果是自己的流可以考虑直接做个ActiveX控件来解决,不用做OLE服务.