科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件使用C++和XML建立智能文档(二)

使用C++和XML建立智能文档(二)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

使用C++和XML建立智能文档(二)

作者:Mike Kelly,陶刚编译 来源:赛迪网 2007年11月7日

关键字: 智能文档 XML C++ Linux

  • 评论
  • 分享微博
  • 分享邮件

目录

ISmartDocument接口教程
属性包
建立智能文档操作DLL
安装智能文档解决方案

ISmartDocument接口教程

下一步是建立智能文档操作DLL并安装它。在你编写智能文档操作处理程序DLL(它实现了ISmartDocument接口方法)之前,最好先了解一下这个接口。

当用户在文档中移动的时候,你的操作处理程序DLL将建立并管理一组出现在文档操作事务面板中的控件,允许你基于文档中的位置提供自定义的用户界面。映射到文档的XML大纲元素定义了用户在文档中的位置。XML元素应该指定给用户显示哪些控件。图2显示了你可以建立的控件类型。你将使用操作处理程序DLL中实现的ISmartDocument接口的方法建立这些控件。当这些控件被激活的时候(例如进入了文本框或者点击了某个按钮),Office通过ISmartDocument接口方法调用你的自定义操作处理程序DLL代码。

图2.智能文档控件类型

我把IsmartDocument接口的方法分为几类:配置方法,它为Office描述了建立在文档操作事务面板中的控件(图3);控件绘制时(draw-time)方法,它们作为控件调用并绘制在事务面板上(图4);修改通知方法,Office把它们作为文档操作事务面板控件调用,由用户维护(图5)。

图3. ISmartDocument接口配置方法

图4. ISmartDocument接口控件绘制方法

图5. ISmartDocument接口通知方法

注意,对于大多数DLL,你不会使用所有的控件类型或实现所有的IsmartDocument方法。例如,因为我的事务面板中没有ActiveX或列表框控件,在例子中就只有这些方法的样板实现。甚至于根本不编写任何操作处理程序DLL也可能利用一些简单的智能文档特性(例如提供超级链接或内容敏感性帮助文本)。作为代替的是你只需要在关联的Word或Excel智能文档中简单地提供一个XML文件,该文件描述了你希望与多种XML元素关联的操作。

图6摘录了ISmartDocument方法的参数。

图6. ISmartDocument通用方法参数

当Office载入你的操作DLL的时候,它首先调用图3所示的配置方法。Office首先调用SmartDocInitialize(允许你执行具体的一次性的初始化)。接着它将通过调用你的get_SmartDocXmlTypeCount实现查询文档中定义的拥有关联控件的XML元素的数量(文档中的XML元素没有关联控件的情况也是可以的)。在例子中,文档操作面板是空的,因此你可能希望为这些元素定义一些标准的帮助内容。你一旦告诉Office你对多少XML文档元素有兴趣后,它将查询每个元素的名称,这些名称是通过调用多个get_SmartDocXmlTypeName获得的。你必须返回XML元素的合格的名称(例如schema#element)。每个元素都有说明,当用户定位到这个元素中的时候,说明会出现在文档操作面板的标题中。这是通过调用get_SmartDocXmlTypeCaption返回的。对get_SmartDocXmlTypeName和 get_SmartDocXmlTypeCaption的调用是成对出现的,每个XML元素执行一次。下一步,Office希望知道每个元素的显示的事务面板中的控件信息。这些信息包括:

·get_ControlCount——给定的某个元素的控件数量。

·get_ControlID——允许你根据某个元素的控件索引(从1开始)给每个控件指定一个唯一的ID号。

·get_ControlNameFromID——在给定控件ID后返回控件的(非固定的)名称。这个名称没有显示,但是用于引用Word或Excel对象模型中的控件。

·get_ControlTypeFromID——给定控件ID后,返回控件的类型(从图2中)。

当用户在文档中移动的时候,Office用适当的控件更新文档操作事务面板,它接着在事务面板中绘制控件的时候调用控件绘制方法(图4所示)。首先它调用get_ControlCaptionFromID,允许你为控件提供一个说明。注意说明不是在配置的时候提供的,而是在显示的时候提供的,因此可以动态地修改它。Office不会绘制有空白的或NULL说明字符串的控件。这可能用于动态地隐藏和显示控件。为了隐藏一个控件,你只需要简单地为该控件从get_ControlCaptionFromID返回一个一个NULL或空字符串。

接着Office为每个控件调用该控件类型特定的填充方法(例如PopulateHelpContent)。你使用这些方法为控件提供内容,例如图像的位置或超级链接的文本。注意与控件关联的文档元素的XML和Text内容被传递到所有的填充方法。同时也要注意,C_TYPE_LABEL和C_TYPE_SEPARATOR类型的控件没有关联的填充方法。在所有的控件绘制了并且事务面板完成了以后,Office将调用OnPaneUpdateComplete。

当用户与事务面板中的控件交互操作的时候,Office调用图5显示的列表中的某个通知方法。标签和分隔符没有关联的通知方法。对于其它控件,通知方法表明要么状态改变了,要么被点击了,这都可能调用一个操作(例如超级链接或图像)。

注意,通知太多比太少更容易造成Office出错。例如,在Excel中的单元选择发生改变的时候(即使XML元素仍然没有变化),Office重新绘制文档操作工作面板并调用你的方法,这样在事务面板上你才拥有真正的动态内容。例如,你能够通过Excel对象模型查询被选择的单元的值并根据这个值更新控件。在示例代码中我利用了这个优点来更新事务面板中被选择的事务的信息,而不需要在文档操作DLL中操作Excel VBA事件。

属性包

大多数控件绘制方法都提供了ISmartDocProperties参数。这是一个名称/值对的属性组(继承自IPropertyBag),提供了控件上的附加信息。这是你指定控件的大小、字体、对齐方式等的地方。图7提供了应用于所有控件的关键的名称。属性值,包括整形属性的值,都是作为BSTR提供给的ISmartDocProperties::Write的。例如,PopulateTextboxContent下述代码行会把文本框控件的宽度设置为50个像素:

Props->Write(CComBSTR("W"), CComBSTR("50"));

图7. 所用控件的ISmartDocProperties

拥有关联标签的控件(C_TYPE_TEXTBOX、C_TYPE_CHECKBOX)都有图8所示的附加属性以描述该控件的标签属性。注意这些只能影响该控件的标签,不会影响绘制控件的字体。最后,还有一些其它的属性只能应用于特定类型的控件。这些属性显示在图9中。

图8.控件标签的IsmartDocProperties

图9. 其它的ISmartDocProperties名称/值对

建立智能文档操作DLL

我决定在Visual C++中使用活动模版库(ATL)建立智能文档操作DLL。ATL是个很好的选择,因为它的覆盖区域比MFC小一些,但是它仍然提供了操作智能文档需要的大量方便的COM功能。但是,如果你更熟悉MFC,你也可以选择它。

从MSDN Online上下载Office 2003智能文档SDK之后,我启动Visual Studio .NET并建立了一个新的ATL类型的项目,接着使用Add | Class给项目添加一个ATL简单对象。这就是示例代码中的CScheduleSmartDoc。从该对象的类环境菜单(使用View | Class打开类资源管理器)中,我使用Add | Implement Interface让这个类实现ISmartDocument接口。如果在开发计算机上没有安装Office 2003,你必须把有Office 2003的计算机上的类型库复制到你的计算机上。你一般可以在C:\Program Files\Common Files\Microsoft Shared\Smart Tag\mstag.tlb中找到它,但是你要确保得到的是1.2版本(Office 2003版本)。接着你应该把我的示例代码和接口描述作为向导,实现你所需要的方法。

安装智能文档解决方案

Office使用一个XML文件(叫作XML扩展包列表文件)描述你的智能文档解决方案,它包含了更新和配置该解决方案的目录。典型情况下这个文件叫作manifest.xml。我在示例代码中添加了一个框架manifest.xml(图10所示),并用红色高亮度显示了你应该修改的东西。

·解决方案的ID。你应该使用GuidGen为智能文档解决方案生成一个唯一的GUID。这是强制性的,所有的解决方案都需要有一个唯一的ID,并且虽然没有严格的限制为GUID,但是这是确保唯一性的最好的方法。

·updateFrequency,它是Office应该多久(按分钟记)检查服务器的清单更新一次。更新都是由XML扩展包清单中指定的每个文件的版本标志控制的。如果版本不同,并且更新事件超期了,Office将把对应的新版本的文件从服务器下载到本地计算机上。

·智能文档操作DLL的文件路径。这可以是URL或网络路径(如果DLL布署在网络上)或与清单文件位置关联的路径或文件名称。

·智能文档操作DLL的CLSID。因为它实现了IsmartDocument COM接口,它就拥有一个Office用于载入它的COM CLSID。你可以在生成的用于实现ISmartDocument接口的ATL类的头文件中找到它。它是coclass(例子中的CScheduleSmartDoc)的uuid属性。

图10. XML清单文件

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<manifest xmlns="http://schemas.microsoft.com/office/xmlexpansionpacks/2003">
    <version>1.1</version>
    <updateFrequency>20160</updateFrequency>
    <uri>ScheduleSmartDocument</uri>
    <solution>
        <solutionID>{15960625-1612-46AB-877C-BBCB59503FCE}</solutionID>
        <type>smartDocument</type>
        <alias lcid="*">Simple Schedule Smart Document</alias>
        <targetApplication>Excel.Application.11</targetApplication>
        <file>
            <type>solutionActionHandler</type>
            <version>1.0</version>
            <filePath>ScheduleSmartDocument.dll</filePath>
            <CLSID>{0A9D54DE-12F8-4711-AF10-7D4ACA1D1924}</CLSID>
            <regsvr32/>
        </file>
        <file>
            <type>Other</type>
            <version>1.0</version>
            <filePath>ScheduleGraphic.GIF</filePath>
        </file> 
    </solution>
    <solution>
        <solutionID>{443E624C-AE85-4b20-8522-1CFD5B4E7CBC}</solutionID> 
        <alias>Schedule Smart Document XSL Transform</alias> 
        <type>Transform</type> 
        <context>http://schemas.microsoft.com/office/word/2003/wordml
            </context> 
        <file>
            <type>primaryTransform</type> 
            <version>1.0</version> 
            <filePath>ScheduleReport.xsl</filePath> 
        </file>
    </solution> 
</manifest>

如果你还需要随着解决方案安装一些附加的文件(例如GIF或包含附加文本的HTML文件),你可以把它们列举在元素的下面,使用元素分隔开。我只有出现在事务面板中的一张附加的GIF。

另一件阻碍了我几个小时的事情是清单中的元素的名称必须与你用于映射文档元素的XML大纲的名称相同。在例子中是ScheduleSmartDocument。

一旦你的智能文档与XML大纲一起标识了,你就能附加一个XML扩展包,把操作处理程序DLL与该文档关联。在Excel中,通过Data | XML | XML Expansion Packs打开对话框。你使用这个对话框先添加少量的扩展包(执行解决方案的manifest.xml文件),接着给文档附加一个扩展包。这个过程与用XML标记文档相似,只有智能文档开发者需要这样做——用户不需要这个对话框。换句话说,你使用Add-Ins 对话框(Tools | Templates and Add-Ins)的“XML扩展包”选项卡给文档附加了一个扩展包。

当用户打开拥有关联扩展包的文档的时候,Office将自动安装或更新他们的本地计算机上的扩展包文件。典型情况下扩展包安装在C:\Documents and Settings\All Users\Application Data\Microsoft\Schemas目录中,但是在未来的Office版本中可能改变这种情况。如果用户没有系统管理员权限,扩展包就安装在相应的每个用户的应用程序数据目录中(例如C:\Documents and Settings\Mike\Local Settings\Application Data\Microsoft\Schemas)。该XML扩展包中的用true标记的文件不会被下载并安装在用户的计算机上,而是每次使用时从服务器位置上直接打开。

如果你已经在本地计算机上开发了一个解决方案,你会发现在把它复制到布署服务器之后,Office仍然在你的开发计算机上使用的路径中查找清单文件。我也碰到了这个问题,最后发现Office把解决方案的路径加密存储在称为Solution URL的自定义文档属性中了。你把这个文件布署到服务器之后,需要把这个属性改变为服务器路径或使用“XML扩展包”对话框从布署服务器上附加该扩展包(这样将重新设置该属性的值)。接着你可以把拥有解决方案文件的服务器路径Excel工作薄保存回服务器。

为了作为用户测试这种情形,你应该关闭工作薄,选择Data | XML | XML Expansion Packs(Word中在Tools | Templates and Add-Ins下面),并从本地计算机上删除ScheduleSmartDocument扩展包文件。这使得你的开发计算机看起来像一台正常的用户计算机,即不知道扩展包的任何信息。下一步,从服务器上打开电子表格。这时候会出现一个对话框,询问你是否希望下载XML扩展包,你应该点击“是”。Office将下载扩展包清单中列举的文件并把它们安装在本地计算机上。

XML扩展包的特性比我们的简单的解决方案需要的特性多一些。实际上它们可以用于从服务器到客户端分发任何类型的文件,甚至于可以被链接成“清单集合”,这会引起Word或Excel引用几个链接的清单,就好像它们是一个大的清单一样。

查看本文来源
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章