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清單文件
1.1
20160
ScheduleSmartDocument
{15960625-1612-46AB-877C-BBCB59503FCE}
smartDocument
Simple Schedule Smart Document
Excel.Application.11
solutionActionHandler
1.0
ScheduleSmartDocument.dll
{0A9D54DE-12F8-4711-AF10-7D4ACA1D1924}
Other
1.0
ScheduleGraphic.GIF
{443E624C-AE85-4b20-8522-1CFD5B4E7CBC}
Schedule Smart Document XSL Transform
Transform
http://schemas.microsoft.com/Office/word/2003/Wordml
primaryTransform
1.0
ScheduleReport.xsl
如果你還需要隨著解決方案安裝一些附加的文件(例如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引用幾個鏈接的清單,就好像它們是一個大的清單一樣。【未完待續】