本文还有配套的精品资源,点击获取
简介:MSWord编程利用Visual C++通过COM接口与Microsoft Office Word应用程序直接交互,实现文档自动化处理。涉及 msword.h 头文件和 msword.cpp 实现文件,分别用于声明和定义与MSWord交互所需的函数。MSWord编程涉及COM接口、自动化技术、 IDispatch 接口和Word对象模型。开发者必须管理COM环境和正确释放COM对象以避免内存泄漏。MSWord编程在自动化文档生成和编辑等领域有广泛应用。
1. Visual C++与Microsoft Office的自动化
Visual C++作为微软的经典开发工具之一,其强大的功能不仅限于底层的系统编程,还涵盖了与各种应用软件进行交互的可能性。在本章中,我们将探讨Visual C++与Microsoft Office,特别是Word的自动化编程。我们将从基础的自动化原理讲起,逐步深入到具体的实现方法,包括COM接口编程以及具体的自动化操作案例。通过本章内容,读者应能够掌握如何使用Visual C++来控制Microsoft Office软件,完成从创建文档到复杂的数据处理等一系列任务,从而提高工作效率和软件的可用性。接下来,我们将详细了解COM接口的原理和操作,为深入理解自动化编程奠定基础。
2. 通过COM接口编程与Word交互
2.1 COM接口基础
2.1.1 COM简介与接口的定义
组件对象模型(Component Object Model, COM)是Microsoft提出的一种以组件为发布单元的对象模型。它的核心是接口(Interface),接口是一组预定义方法的集合,为实现和使用它的不同对象提供了一种统一的交互方式。
COM的接口定义包括一系列的函数指针,这些指针指向接口实现的成员函数。接口本身不包含任何函数实现。一个接口可以有多个实现,而一个对象可以实现多个接口。COM接口的设计,使用了GUID(全局唯一标识符)来唯一标识每一个接口,确保了接口的全局唯一性。
接口在C++中的实现通常依赖于虚函数表(v-table)。每个接口都对应一个v-table,该v-table包含指向接口成员函数实现的指针。当通过接口调用成员函数时,实际上是通过v-table来定位到相应的函数实现。
// 示例:COM接口定义
interface IUnknown
{
virtual HRESULT QueryInterface(REFIID riid, void** ppvObject) = 0;
virtual ULONG AddRef() = 0;
virtual ULONG Release() = 0;
};
2.1.2 如何创建和注册COM组件
创建COM组件,通常需要以下步骤:
定义接口:创建一个或多个接口,使用 interface 关键字定义,并为每个接口指定一个唯一的GUID。
实现组件:创建一个类来实现前面定义的接口。这个类需要继承 IUnknown 接口,因为所有COM接口都派生自 IUnknown 。
注册组件:编写代码注册COM组件,以便系统能够找到并加载该组件。注册信息一般包含组件的CLSID(类标识符)、组件的类型(如in-process或out-of-process)、组件的名称等。
利用注册表或Windows注册表编辑器(regedit.exe),插入相应键值。
创建实例:使用 CoCreateInstance 函数创建COM组件的实例。
// 示例:创建COM组件
#include
// 声明接口
interface IMyComponent : public IUnknown
{
// 接口成员函数声明...
};
// 实现组件
class CMyComponent : public IMyComponent
{
public:
// 实现IUnknown的三个方法...
HRESULT QueryInterface(REFIID riid, void** ppvObject) override;
ULONG AddRef() override;
ULONG Release() override;
// 实现其他接口方法...
};
// 注册组件
// 使用注册表函数或编写注册脚本...
// 使用组件
CoCreateInstance(CLSID_MyComponent, NULL, CLSCTX_INPROC_SERVER, IID_IMyComponent, (void**)&pMyComponent);
2.2 使用COM接口与MS Word的连接
2.2.1 初始化COM库与Word应用程序实例化
在使用Word或其他Office应用程序进行自动化之前,需要初始化COM库。这是通过调用 CoInitialize 或 CoInitializeEx 函数完成的,它们负责设置COM线程环境。初始化完成后,就可以创建Word应用程序的实例了。
Word的自动化接口是 _Application ,它代表整个Word应用程序。实例化Word应用程序对象通常使用 CoCreateInstance 函数,并传入Word的CLSID和 _Application 接口的IID。一旦实例化成功,就可以通过这个接口访问Word的所有功能了。
// 示例:初始化COM库并创建Word实例
#include
int main()
{
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hr))
{
// 初始化失败处理...
return -1;
}
IDispatch* pWordApp = NULL;
hr = CoCreateInstance(CLSID_Application, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void**)&pWordApp);
if (FAILED(hr) || pWordApp == NULL)
{
// 创建实例失败处理...
CoUninitialize();
return -1;
}
// 通过pWordApp操作Word...
pWordApp->Release();
CoUninitialize();
return 0;
}
2.2.2 连接到已运行的Word实例
有时,用户可能已经在运行Word应用程序,此时我们可能想要连接到这个已经存在的实例进行操作。COM提供了方法 GetActiveObject 来实现这一目标。通过传递Word应用程序的CLSID和标识符(通常是程序的名称), GetActiveObject 函数可以返回一个当前运行的实例的接口指针。
// 示例:连接到已运行的Word实例
IDispatch* pActiveWordApp = NULL;
hr = GetActiveObject(CLSID_Application, NULL, &pActiveWordApp);
if (SUCCEEDED(hr) && pActiveWordApp != NULL)
{
// 已运行的Word实例存在,进行操作...
pActiveWordApp->Release();
}
2.2.3 创建新文档和操作界面元素
连接到Word实例后,通常下一步是创建新文档并进行操作。可以通过 Documents 集合来访问文档,以及对文档进行各种操作。此外,还可以获取或修改文档的界面元素,如工具栏、菜单等。
// 示例:创建新文档并操作
VARIANT varNewDoc;
VariantInit(&varNewDoc);
varNewDoc.vt = VT_DISPATCH;
IDispatch* pDocuments = NULL;
hr = pWordApp->GetMember("Documents", &varNewDoc);
if (SUCCEEDED(hr) && varNewDoc.pdispVal != NULL)
{
pDocuments = varNewDoc.pdispVal;
// 使用Documents集合创建新文档
DISPID dispIDNew;
OLECHAR* szNew = L"New";
hr = pDocuments->GetIDsOfNames(IID_NULL, &szNew, 1, LOCALE_USER_DEFAULT, &dispIDNew);
if (SUCCEEDED(hr))
{
// 调用New方法创建新文档
DISPPARAMS dispParamsNoArgs = {NULL, NULL, 0, 0};
hr = pDocuments->Invoke(dispIDNew, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispParamsNoArgs, NULL, NULL, NULL);
if (SUCCEEDED(hr))
{
// 新文档创建成功,可以继续其他操作...
}
}
}
在上述代码中,我们通过Word的 Documents 属性来访问文档集合。使用 GetIDsOfNames 获取 New 方法的DISPID( Dispatch ID),然后通过 Invoke 函数调用它来创建一个新文档。这些步骤展示了如何通过COM接口与Word进行交互来执行自动化任务。
通过这些基本操作,开发人员可以开始探索Word对象模型提供的更深层次的功能,包括但不限于文档编辑、格式设置、插入对象以及事件处理等。这些高级功能的实现将涉及到更多COM接口和Word对象模型的具体细节。
3. msword.h头文件和msword.cpp实现文件的作用
3.1 头文件与实现文件的基本结构
3.1.1 msword.h的结构和功能解析
msword.h 头文件是整个自动化过程中与COM接口进行交互的桥梁,它在程序设计中扮演着定义和声明自动化操作所需类和接口的角色。通过 msword.h ,开发者可以清晰地了解Word自动化功能中的类结构、接口定义以及相关的操作方法。这使得开发者能够明确地知道如何通过代码来创建和管理Word文档,以及如何通过COM接口操作Word的各种功能。
以下是 msword.h 的一个典型结构示例:
// msword.h
#ifndef MSWORD_H
#define MSWORD_H
// 包含COM接口和相关类型的定义
#include
#include
// 定义Word自动化相关的类和接口
class CWordDocument
{
public:
void Open(const OLECHAR* fileName);
void Close();
// 其他文档操作相关的方法
};
// 定义自动化操作中使用的常量和枚举类型
enum WordApplicationConstants
{
WdSaveChanges = 1,
WdDoNotSaveChanges = 2,
// 其他常用常量
};
#endif // MSWORD_H
在上述代码中, CWordDocument 类为操作Word文档提供了一系列方法,例如 Open 用于打开文档, Close 用于关闭文档等。 WordApplicationConstants 枚举则提供了一些常用的常量,用于指定如保存文档时的选择。
3.1.2 msword.cpp中的函数和方法实现
msword.cpp 实现文件则包含了 msword.h 头文件中声明的类和函数的具体实现。这里会详细地编写方法,使其能够通过调用COM接口与Word应用程序进行通信。
// msword.cpp
#include "msword.h"
void CWordDocument::Open(const OLECHAR* fileName)
{
HRESULT hr = S_OK;
// 初始化COM库
hr = CoInitialize(NULL);
if (FAILED(hr))
{
// 错误处理逻辑
return;
}
// 创建Word应用程序实例
IDispatch* pApp;
hr = CoCreateInstance(CLSID_App, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void**)&pApp);
// 通过IDispatch接口与Word应用程序交互,完成后续操作...
}
void CWordDocument::Close()
{
// 实现关闭文档的逻辑...
}
// 其他方法的实现...
在 msword.cpp 中, Open 方法首先会调用 CoInitialize 初始化COM库,然后使用 CoCreateInstance 创建Word应用程序的实例。其他文档操作的逻辑,在此函数中通过调用COM接口的方法来实现。
3.2 msword.h头文件中的关键定义
3.2.1 定义和声明Word自动化相关的类和接口
msword.h 头文件中定义的类和接口是整个程序操作Word文档的核心。例如,一个典型的 CWordDocument 类,它封装了Word文档的打开、保存、编辑等操作。这样的封装不仅简化了操作,还使得代码更加清晰和易于维护。
class CWordDocument
{
public:
CWordDocument();
virtual ~CWordDocument();
HRESULT CreateInstance();
HRESULT ConnectToRunningInstance();
HRESULT Save();
HRESULT Quit();
// 其他文档操作相关的方法和属性
};
3.2.2 定义自动化操作中使用的常量和枚举类型
为了操作Word文档的方便, msword.h 还会定义一系列常量和枚举。这些值在实际操作中被用来指定特定的行为或状态,例如保存时的不同选项。
enum WordSaveOptions
{
wdSaveChanges = 1, // 保存所有更改
wdDoNotSaveChanges = 2, // 不保存更改
wdPromptToSaveChanges = 3, // 提示保存更改
};
通过定义这样的枚举,开发者在处理保存选项时,就可以通过 wdSaveChanges 等直观的枚举值,而不是难记的数字。这大大提高了代码的可读性和易用性。
总结来说, msword.h 头文件和 msword.cpp 文件共同构成了Word自动化程序的基础框架。头文件定义了程序与Word交互的接口和方法,而实现文件则提供了这些方法的具体逻辑。理解了这一章节的内容,对于进一步深入到Word自动化编程的核心概念和实现细节有着至关重要的作用。
4. COM接口的基础知识
4.1 COM接口的核心概念
4.1.1 接口与实现的分离
COM (Component Object Model) 是微软公司推出的一种组件对象模型,它允许多个不同的软件组件在各种不同的环境下进行交互。核心思想之一是将接口与实现完全分离。在COM中,接口是使用一组虚函数指针来描述的一组操作,而实现则是一个或多个继承了该接口的类。
接口的定义使用了 interface 关键字,并继承自 IUnknown ,它提供了一组核心方法: AddRef 、 Release 和 QueryInterface 。 AddRef 和 Release 用于管理对象的引用计数,而 QueryInterface 用于查询对象是否支持某个特定的接口。
// 示例:COM接口定义
interface IMyCOMInterface : public IUnknown {
virtual HRESULT DoSomething() = 0;
virtual HRESULT DoAnotherThing() = 0;
};
在这个例子中, IMyCOMInterface 定义了一个接口,它包含两个方法: DoSomething 和 DoAnotherThing 。这里的 = 0 表示这两个方法是纯虚函数,必须在派生类中被实现。
接口和实现分离的设计模式允许同一个接口由不同的类实现,这意味着客户端代码可以不依赖于特定的实现,只要遵循相同的接口就可以与任何实现了该接口的对象进行交互。这种设计极大的增强了代码的灵活性和可重用性。
4.1.2 接口版本管理与兼容性
随着软件组件的升级和发展,接口也需要进行版本管理,以保持向后兼容性。COM使用接口的 GUID (全局唯一标识符) 来区分不同的接口版本。如果一个接口发生了改变,新的接口会得到一个新的 GUID。这样,在不破坏现有客户的情况下,开发者可以添加新的方法或者修改旧方法,同时保留旧的接口不变。
// 示例:接口定义和GUID
interface IMyCOMInterface : public IUnknown {
// COM接口方法
};
// 在实现文件中定义接口的GUID
#include "GuidDef.h"
uuid("964B7113-6C7A-4962-9C8F-08F9C292D352"),
interface IMyCOMInterface : public IUnknown
{
// 方法定义
};
在上面的示例中, uuid 宏定义了 IMyCOMInterface 的GUID,这是确保接口唯一性的关键。版本管理时,应保持旧接口及其GUID不变,同时在新的接口定义中指定新的GUID。这样,旧的客户端代码仍然可以使用旧的接口,而新的客户端代码可以利用新接口提供的新功能。
4.2 COM编程实践
4.2.1 创建COM对象
创建COM对象通常涉及调用 CoCreateInstance 函数,它根据提供的CLSID(类标识符)和接口标识符实例化一个COM对象。在COM编程中,所有的COM对象都必须实现 IUnknown 接口,这是使用COM对象的基础。
#include
IMyCOMInterface* pIMyCOMInterface;
HRESULT hr = CoCreateInstance(CLSID_MyCOMObject, NULL, CLSCTX_INPROC_SERVER, IID_IMyCOMInterface, (void**)&pIMyCOMInterface);
if (FAILED(hr)) {
// 创建COM对象失败的处理
}
在上面的代码块中, CoCreateInstance 根据 CLSID_MyCOMObject (已注册的COM组件的类标识符)和 IID_IMyCOMInterface (请求接口的标识符)创建了一个COM对象,并且将接口指针赋值给 pIMyCOMInterface 。创建成功后,就可以通过这个接口指针调用COM对象提供的各种方法。
4.2.2 使用接口与COM对象交互
一旦获得了COM对象的接口指针,就可以通过该接口调用COM对象提供的方法。这是与COM对象进行交互的主要方式。
if (pIMyCOMInterface) {
HRESULT hr = pIMyCOMInterface->DoSomething();
if (FAILED(hr)) {
// 方法调用失败的处理
}
pIMyCOMInterface->Release(); // 释放接口指针,减少引用计数
}
在这个代码片段中,通过 pIMyCOMInterface 接口调用 DoSomething 方法。调用完毕后,为了防止内存泄漏,必须调用 Release 方法来减少接口的引用计数。当引用计数降至零时,COM对象会自动清理自身所占用的资源。
4.2.3 引用计数与对象生命周期管理
引用计数是COM管理对象生命周期的一种机制。每个COM对象都有一个引用计数器,记录有多少个接口指针指向它。当一个接口指针不再被需要时,调用 Release 方法来减少引用计数。当引用计数降至零时,对象会调用自身的 FinalRelease 方法进行清理工作,并最终释放对象本身。
pIMyCOMInterface->AddRef(); // 增加引用计数
// 使用接口进行一些操作
pIMyCOMInterface->Release(); // 减少引用计数
在上面的代码块中, AddRef 调用用于增加COM对象的引用计数。通常,每当创建一个新的接口指针时,就会调用 AddRef 。释放接口指针时,需要调用 Release 来平衡之前 AddRef 的调用。正确的管理引用计数对于防止内存泄漏和确保程序稳定运行至关重要。
5. 使用 IDispatch 接口进行晚绑定
5.1 IDispatch 接口概述
5.1.1 晚绑定的概念与作用
在程序设计中,绑定是指将程序中的一个调用与相应的代码体关联起来的过程。绑定可以发生在编译时(早期绑定)或运行时(晚绑定)。 IDispatch 接口主要在晚绑定中发挥作用,允许在运行时动态地调用COM对象的方法和属性。
晚绑定的主要优点是灵活性和可扩展性。它让开发人员可以在不修改程序代码的情况下,调用新的方法或属性。这在处理不同版本的COM组件或未知的接口时特别有用。
5.1.2 IDispatch 的成员函数介绍
IDispatch 接口定义了四个成员函数: - GetTypeInfoCount : 获取类型信息的数量。 - GetTypeInfo : 获取类型信息的接口。 - GetIDsOfNames : 将一个方法或属性的名字映射到一个 DISPID 。 - Invoke : 调用一个方法或访问一个属性。
DISPID (Dispatch ID)是一个在 IDispatch 中使用的唯一标识符,用于标识方法或属性。
5.2 实现晚绑定操作
5.2.1 构造DISPID与方法调用
为了使用 IDispatch 进行晚绑定,首先需要获取对应方法的 DISPID 。这通常通过 GetIDsOfNames 函数实现,你需要传入要查找的方法名,然后它会返回相应的 DISPID 。
一旦有了 DISPID ,就可以使用 Invoke 方法来调用对应的方法。 Invoke 方法需要以下参数: - DISPID : 要调用方法的标识符。 - riid : 接口的标识符。 - lcid : 语言代码标识符。 - wFlags : 调用的标志。 - pdispparams : 指向 DISPPARAMS 结构的指针,用于传递方法的参数。 - pvarResult : 指向 VARIANT 结构的指针,用于接收返回值。 - pexcepinfo : 指向 EXCEPINFO 结构的指针,用于异常信息。 - puArgErr : 指向 UINT 的指针,用于指定传入参数中的错误参数索引。
示例代码如下:
// 假设 pdisp 接口指针已经成功获取
VARIANT vResult;
DISPID dispid;
DISPPARAMS dispParams = {NULL, NULL};
EXCEPINFO excepInfo;
UINT argErr;
OLECHAR* method = L"MethodName"; // 方法名字符串
// 获取DISPID
HRESULT hr = pdisp->GetIDsOfNames(IID_NULL, &method, 1, LOCALE_USER_DEFAULT, &dispid);
if (FAILED(hr)) {
// 处理错误
}
// 调用方法
hr = pdisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,
&dispParams, &vResult, &excepInfo, &argErr);
if (FAILED(hr)) {
// 处理错误
}
// 检查是否获取了结果
if (V_VT(&vResult) != VT_EMPTY) {
// 使用返回值
VariantClear(&vResult); // 清理VARIANT
}
5.2.2 参数传递与返回值处理
在使用 DISPPARAMS 结构体进行方法调用时,可以传递参数给目标方法。 DISPPARAMS 结构体包含两个 VARIANT 数组: rgvarg (传递给方法的参数)和 rgdispidNamedArgs (命名参数的 DISPID )。
若方法有返回值,其结果会被存储在 VARIANT 类型的 pvarResult 参数中。使用完毕后,需要调用 VariantClear 来清理 VARIANT ,以避免内存泄漏。
5.2.3 错误处理与异常情况应对
当通过 IDispatch 接口调用方法时,可能会发生多种错误,比如方法不存在、参数传递错误、COM内部错误等。错误处理是晚绑定中非常重要的一个环节。应检查 Invoke 方法的返回值以及可能的异常信息。
如果 Invoke 方法返回失败,可以通过 excepInfo 结构体获取更多错误信息。 excepInfo 包含错误的错误代码、描述、帮助文件、帮助上下文以及源文件名和行号信息。
对于异常情况的处理,通常会结合 try-catch 语句,捕获可能抛出的异常,并提供合适的用户反馈或错误记录。
通过以上详细介绍,我们了解到 IDispatch 接口是实现晚绑定的关键组件,它为程序提供了灵活地调用不同COM对象和版本的能力。接下来,我们将进一步探讨如何在实际应用中使用 IDispatch ,包括创建自动化脚本和处理各种COM对象。
6. Word对象模型的使用方法
6.1 Word对象模型概览
6.1.1 对象模型的层次结构
在深入Word自动化编程前,理解Word对象模型的层次结构至关重要。Word对象模型是按照逻辑文档结构来组织的,每一层代表了文档的不同组成部分。模型的顶层是 Application 对象,这是用户与Word交互的入口点,相当于Word软件本身。
紧接着是 Documents 集合,它包含文档集合,可以用来操作Word中的多个文档。每一个文档( Document )对象代表了一个打开的文档。文档内部又可以细分为各种文本和结构元素,如 Paragraphs (段落集合), Sections (节集合), Tables (表格集合)等。
要操控文档内容,你需要了解这些对象的属性和方法。例如,可以使用 Paragraphs 集合中的 Item 方法来访问特定的段落对象,并对其进行格式化或者添加文本。同样, Tables 集合允许你添加新表格,或者修改已有表格内容。
6.1.2 文档、段落、格式等常用对象介绍
文档对象是Word对象模型的核心,通过 Document 对象可以执行几乎所有的文档操作。它提供了诸如 Save 、 Close 、 ExportAsFixedFormat (导出为固定格式)等方法来管理文档的生命周期。
段落( Paragraph )对象是文档的组成单位,代表了一个段落。可以使用 Range 属性来指定段落中特定的文本范围,并通过 Format 属性来改变文字样式或排版,例如字体大小、颜色或对齐方式。
格式( Format )对象允许你对文本进行格式化,它包括了字体( Font )、段落( ParagraphFormat )和表格( TableFormat )的格式化设置。这使得对文档的视觉效果进行详细调整成为可能。
6.2 对象模型编程技巧
6.2.1 创建与访问文档和子对象
要创建并访问Word文档和其中的子对象,首先需要实例化 Application 对象,然后使用该对象来打开或创建新文档。例如:
#import "C:\Program Files (x86)\Common Files\Microsoft Shared\OFFICE14\MSO.DLL" \
rename("RGB", "MSORGB")
#import "C:\Program Files (x86)\Microsoft Office\Office14\MSWORD.OLB"
using namespace Word;
int main()
{
CoInitialize(NULL);
ApplicationPtr pApp; // Word 应用程序实例
DocumentsPtr pDocs; // 文档集合
DocumentPtr pDoc; // 文档对象
pApp.CreateInstance(__uuidof(Application));
pDocs = pApp->Documents;
// 创建新文档
pDoc = pDocs->Add();
pDoc->SaveAs2(L"C:\\test.docx");
pApp->Quit();
CoUninitialize();
return 0;
}
6.2.2 文档编辑与格式化操作
对文档进行编辑和格式化操作是Word自动化的核心。在上述代码基础上,可以添加新的段落,对文本进行格式化,甚至插入图片和表格。
// 创建段落并添加文本
ParagraphsPtr pParagraphs = pDoc->Paragraphs;
ParagraphPtr pParagraph = pParagraphs->Add();
pParagraph->Range->Text = L"这是自动化插入的段落。";
// 格式化文本
FontPtr pFont = pParagraph->Range->Font;
pFont->Bold = true;
pFont->Italic = true;
pFont->Size = 14;
6.2.3 事件处理和回调函数设置
在Word自动化中,有时需要对特定事件作出响应,如文档保存、打开等。由于COM是基于事件的模型,Word对象模型支持事件触发,允许开发者注册和响应这些事件。事件处理可以通过 DocumentEvents 对象实现。而回调函数通常在C++代码中注册,以便在特定事件发生时调用。
例如,注册一个文档保存事件:
// 注册文档保存事件
pDoc->Saved += new _dispDocumentEvents_SavedEventHandler(OnDocumentSaved);
// 回调函数定义
void OnDocumentSaved(DocumentPtr pDoc)
{
std::wcout << "Document " << pDoc->Name << " has been saved." << std::endl;
}
通过这些编程技巧,开发者可以灵活地操作Word文档,实现复杂自动化任务。在下一章中,我们将探讨如何管理COM环境以及正确释放COM对象,确保资源的有效利用和程序的稳定性。
本文还有配套的精品资源,点击获取
简介:MSWord编程利用Visual C++通过COM接口与Microsoft Office Word应用程序直接交互,实现文档自动化处理。涉及 msword.h 头文件和 msword.cpp 实现文件,分别用于声明和定义与MSWord交互所需的函数。MSWord编程涉及COM接口、自动化技术、 IDispatch 接口和Word对象模型。开发者必须管理COM环境和正确释放COM对象以避免内存泄漏。MSWord编程在自动化文档生成和编辑等领域有广泛应用。
本文还有配套的精品资源,点击获取