示例 3:打開現有的 word 文檔
同 documents.saveas 方法一樣,documents.open 方法簽名在 office 2000 和 officexp 之間也存在差別,因此新名稱包裝在 #if 聲明中。open 方法和 saveas 方法一樣簡單,如下所示: 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);
幫助中的 word 2002 visual basic 參考以及 msdn(英文)中有關 documents.open 方法的說明記錄了這些可選參數。
本示例中比較讓人感興趣的代碼是,打開的文檔中的文本先被突出顯示,然后被剪切: object first=0; object last=doc.characters.count; range r = doc.range(ref first, ref last); r.select(); thread.sleep (2000); r.cut();
第一個字符和最后一個字符位置的整數值被封裝到第一個和最后一個對象,然后傳遞給 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
要生成 example3.cs,可以在 visual studio .net command prompt(visual studio .net 命令提示)窗口中執行以下操作: - 打開保存 example3.cs 源文件的目錄(例如 c:/csofficesamples),并在命令提示后鍵入 csc /r:"c:/office xp pias/microsoft.office.interop.word.dll" /d:officexp example3.cs。
(如果 office xp pia 保存在其他位置,則需要使用相應值替換下面的“驅動器”和“安裝路徑”:csc /r:驅動器:/<安裝路徑>/microsoft.office.interop.word.dll /d:officexp example3.cs。) - 要運行 example3.exe(與 example3.cs 源文件位于同一文件夾中),雙擊該程序即可。
示例 4:使用 word 公開的事件
本示例涉及的內容要比其他幾個多一些,但實際上并不復雜。看起來復雜的主要原因在于標識事件及其處理程序類型的名稱長一些。看一看 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 命令提示)窗口中執行以下操作: - 打開保存 example4.cs 源文件的目錄(例如 c:/csofficesamples),并在命令提示后鍵入 csc /r:"c:/office xp pias/microsoft.office.interop.word.dll" /d:officexp example4.cs。
(如果 office xp pia 保存在其他位置,則需要使用相應值替換下面的“驅動器”和“安裝路徑”:csc /r:驅動器:/<安裝路徑>/microsoft.office.interop.word.dll /d:officexp example4.cs。) - 要運行 example4.exe(與 example4.cs 源文件位于同一文件夾中),雙擊該程序即可。
示例 5:動畫顯示 office 助手
有些用戶喜歡 office 助手,有些人則討厭它們。無論如何,example5.cs 在此處都僅僅是為了增添一點樂趣。本示例程序還使用位于 mso.dll 中的助手類型信息。該程序使用兩個 pia: - microsoft.office.interop.word.dll
- office.dll
example5.cs 源文件中的每個重要步驟都作了詳細注釋。由于易于理解,此處不準備對此代碼加以介紹。如何生成和運行 example5.cs
要生成 example5.cs,可以在 visual studio .net command prompt(visual studio .net 命令提示)窗口中執行以下操作: - 打開保存 example5.cs 源文件的目錄(例如 c:/csofficesamples 目錄),并在命令提示后鍵入 csc /r:"c:/office xp pias/microsoft.office.interop.word.dll" /r:"c:/office xp pias/office.dll" example5.cs。
(如果 office xp pia 保存在其他位置,則需要使用相應值替換下面的“驅動器”和“安裝路徑”:csc /r:驅動器:/<安裝路徑>/microsoft.office.interop.word.dll /r:drive:/<安裝路徑>/office.dll example5.cs。) - 要運行 example5.exe(與 example5.cs 源文件位于同一文件夾中),雙擊該程序即可。
示例 6:默認屬性和索引屬性
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
要生成 excel1.cs,可以在 visual studio .net command prompt(visual studio .net 命令提示)窗口中執行以下操作: - 打開保存 excel1.cs 源文件的目錄(例如 c:/csofficesamples 目錄),在命令提示后鍵入 csc /r:"c:/office xp pias/microsoft.office.interop.excel.dll" /d:officexp excel1.cs。
(如果 office xp pia 保存在其他位置,則需要使用相應值替換下面的“驅動器”和“安裝路徑”:csc /r:驅動器:/<安裝路徑>/microsoft.office.interop.excel.dll /d:officexp excel1.cs。) - 要運行 excel1.exe(與 excel1.cs 源文件位于同一文件夾中),雙擊該程序即可。
小結
c# 的 com 互操作是一種非常有用的工具,因為利用它可以直接使用現有對象而無需為那些對象重寫代碼。本文可幫助您利用現有 com 對象代碼。
下面是一些有關 pia、.net 安全性、.net 和 com 互操作等內容的文章鏈接,從中可以獲得更詳細的信息。 - introduction to com interop(英文)
- primary interop assemblies (pias)(英文)
- microsoft .net framework faq(英文)
- microsoft .net/com migration and interoperability(英文)
- .net interop: get ready for microsoft .net by using wrappers to interact with com-based applications(英文)
- exposing .net framework components to com(英文)
- calling a .net component from a com component(英文)
- calling com components from .net clients(英文)