扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:佚名 来源:Microsoft 2007年11月14日
关键字:
要生成 xample2.cs,可以在 Visual Studio .NET Command Prompt(Visual Studio .NET 命令提示)窗口中执行以下操作:
图 3:使用命令行编译 example2.cs
同 Documents.SaveAs 方法一样,Documents.Open 方法签名在 Office 2000 和 OfficeXP 之间也存在差别,因此新名称包装在 #if 声明中。Open 方法和 SaveAs 方法一样简单,如下所示:
<FONT class=90v> object fileName = Environment.CurrentDirectory+"\\example3"; object optional=Missing.Value; #if OFFICEXP _Document doc = app.Documents.Open2000( ref fileName, #else _Document doc = app.Documents.Open( ref fileName, #endif ref optional, ref optional, ref optional, ref optional, ref optional, ref optional, ref optional, ref optional, ref optional, ref optional, ref optional);</FONT> |
帮助中的 Word 2002 Visual Basic 参考以及 MSDN(英文)中有关 Documents.Open 方法的说明记录了这些可选参数。
本示例中比较让人感兴趣的代码是,打开的文档中的文本先被突出显示,然后被剪切:
<FONT class=90v> object first=0; object last=doc.Characters.Count; Range r = doc.Range(ref first, ref last); r.Select(); Thread.Sleep (2000); r.Cut();</FONT> |
第一个字符和最后一个字符位置的整数值被封装到第一个和最后一个对象,然后传递给 Document.Range() 函数,该函数返回 Select() 函数调用的 Range 对象。这种显式封装是必需的,因为 Range 对象期待引用其参数,并且任何隐式或显式的转换都会将参数改为右值,而右值是不能按引用传递的。本示例使文本突出显示持续两秒钟,而后对文本进行剪切。剪切操作也可以通过以下代码实现:
object first=0; object units = WdUnits.wdCharacter; object last=doc.Characters.Count; doc.Range(ref first, ref last).Delete(ref units, ref last); |
要生成 example3.cs,可以在 Visual Studio .NET Command Prompt(Visual Studio .NET 命令提示)窗口中执行以下操作:
本示例涉及的内容要比其他几个多一些,但实际上并不复杂。看起来复杂的主要原因在于标识事件及其处理程序类型的名称长一些。看一看 Office XP 版本的 DocumentOpen 和 DocumentChange 事件处理程序的设置代码:
... #if OFFICEXP ApplicationEvents3_DocumentOpenEventHandler myOpenDoc = new ApplicationEvents3_DocumentOpenEventHandler (MyOpenEventHandler); ApplicationEvents3_DocumentChangeEventHandler myChangeDoc = new ApplicationEvents3_DocumentChangeEventHandler(DocChange); #else ... |
这两条语句仅仅是声明事件的事件处理程序。随后的几行代码中,这些处理程序将指定给 Application 对象 app
中的事件:
app.DocumentOpen += myOpenDoc; app.DocumentChange += myChangeDoc;
现在就可以使用这两个事件了。调用 Open 方法时,这两个事件将同时引发。依次打开超链接阅读有关 DocumentOpen(英文)和 DocumentChange(英文)方法的文档。
那么,如何知道哪些事件可用及其处理程序的调用方法呢?如果使用 ILDASM 检查 Word 2002 PIA (Microsoft.Office.Interop.Word.dll),会发现在有些类型前面标有绿色倒三角标志。该标志表示成员是一个事件。图 4 显示了 ILDASM 树视图图标的帮助。
图 4:ILDASM 的树视图图标帮助
图 5:使用 ILDASM 查看 Application 对象的事件
图 5 显示了 Application 对象的事件的部分屏幕快照。每一行最左边的标识符是事件名称。冒号右边是事件处理程序的完整限定类型名。例如,DocumentBeforeSave 事件要求有如下类型的处理程序:
Microsoft.Office.Interop.Word .ApplicationEvents3_DocumentBeforeSaveEventHandler |
请注意,事件并未告诉我们任何有关事件处理程序签名的信息。因此,需要看一下事件处理程序声明。在 ILDASM 中,如果双击 ApplicationEvents3_DocumentBeforeSaveEventHandler 类型,就会看到类似图 6 显示的内容。
图 6:在 ILDASM 中查看事件处理程序声明
让我们感兴趣的是 Invoke 方法。为事件处理程序编写的函数必须具有此签名。但是如何知道参数的含义及其使用的值呢?这就是 Word 2002 Visual Basic 文档的重要性所在。对于 DocumentBeforeSave 事件,文档(英文)叙述如下:
Private Sub object_DocumentBeforeSave(ByVal Doc As Document, SaveAsUI As Boolean, Cancel As Boolean) |
该文档接下来描述了每个参数的含义。请记住,C# 在默认情况下按值传递参数,而 Visual Basic 在默认情况下按引用传递参数。这就是为什么两个 Boolean 参数在用 ILDASM 显示时后面要跟 & 符号,而在 C# 中使用时则用关键字 ref 标记的原因了。同样,Visual Basic 中的 Subs 在 C# 中被看作返回 void 的方法。因此,DocumentSave 事件的处理程序应类似于如下所示:
public static void SaveHandler (Document doc, ref bool b1, ref bool b2) { MessageBox.Show ("Saving document", "DocumentSave event", MessageBoxButtons.OK, MessageBoxIcon.Information); } |
当通过调用 SaveAs 方法保存文档时,DocumentBeforeSave 事件将在保存文档前引发。
在 SaveAs 方法调用的后面几行代码中,您将看到如下代码片段:
app.DocumentChange -= myChangeDoc;
此代码行解除了 DocumentChange 事件的挂钩,这样该事件就不会在调用 Quit 期间引发了。
如何生成和运行 example4.cs要生成 example4.cs,可以在 Visual Studio .NET Command Prompt(Visual Studio .NET 命令提示)窗口中执行以下操作:
有些用户喜欢 Office 助手,有些人则讨厌它们。无论如何,example5.cs 在此处都仅仅是为了增添一点乐趣。本示例程序还使用位于 mso.dll 中的助手类型信息。该程序使用两个 PIA:
example5.cs 源文件中的每个重要步骤都作了详细注释。由于易于理解,此处不准备对此代码加以介绍。
如何生成和运行 example5.cs要生成 example5.cs,可以在 Visual Studio .NET Command Prompt(Visual Studio .NET 命令提示)窗口中执行以下操作:
Word 2002 很少用到默认属性和索引属性,而 Excel 2002 却经常用到它们,因此本示例 (excel1.cs) 利用了这一事实。
同所有 Office XP 互操作代码一样,本示例程序从实例化 Application 对象开始。创建工作簿和工作表后,创建了一个用于保存列标题的字符串数组。创建完该数组后,您将看到如下代码片段:
wksRange = wks.get_Range("A2", "D2");此代码获取单元格 A2 到 D2 的 Range 对象。但既然工作表有一个 Range 属性,为什么还需要直接调用访问函数呢?并且这样做为何不象通常那样会产生语法错误?
与 Visual Basic 和 Visual C++ 不同,C# 没有适用于索引属性的语法结构。要在 C# 中使用索引属性,就必须直接调用访问函数。_Worksheet.Range 属性便是一个很好的例子。要在 Visual C++ 中获取 Range 属性的值,代码应如下所示:
myRange = myWorksheet->Range["A2", "D2"];要在 C# 中执行相同的操作,代码则应如下所示:
myRange = myWorksheet.get_Range("A2", "D2");设置 Range 属性,而不是向其赋值,是对 set 访问函数的调用:
myWorksheet.set_Range("A2", "D2", myRange);Microsoft Excel 2000 中的 Range.Value 属性是一个常规属性,但在 Excel 2002 中,则变成了一个索引属性。这就是为什么在本示例程序中使用该属性时要将其括在 #if OFFICEXP 语句中的原因。
_Workbook.Worksheets 具有所谓的默认属性。默认属性在互操作程序集中被看作是名称为 Item 的属性。通常必须指定 Item 成员才能从 C# 使用默认属性,但是在 Excel 库中,TLBIMP 只需少量代码就可以创建称为 get__Default 或 set__Default 的访问函数。如果这两个访问函数存在,C# 就可以使用索引生成器语法而不是直接调用访问函数。本示例中的这两行代码如下所示:
_Worksheet wks2 = (_Worksheet)wkb.Worksheets["Market Share!"]; ((_Worksheet)wkb.Worksheets["Market Share!"]).Name = "Fred"; |
要生成 excel1.cs,可以在 Visual Studio .NET Command Prompt(Visual Studio .NET 命令提示)窗口中执行以下操作:
C# 的 COM 互操作是一种非常有用的工具,因为利用它可以直接使用现有对象而无需为那些对象重写代码。本文可帮助您利用现有 COM 对象代码。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者