深入介紹Word開發


上一篇文章中,我介紹了Word的對象模型和一些基本開發技巧。為了更好的介紹Word插件開發,我為本文制作了一個Word書簽的增強版,具體功能是讓用戶在Word中選擇一段文本,為它添加書簽並其標志為高亮,同時用戶可以為這段書簽寫注釋,以后當用戶點擊這個書簽時,我就會顯示注釋。以下是我錄制的視頻介紹:

 

這個插件將包括以下幾個技術點:

  1. 添加右鍵菜單
      • 添加右鍵菜單、控制右鍵菜單顯示
      • WindowBeforeRightClick 事件
      • 刪除右鍵菜單
  2. 修改正文內容、樣式
    1. 修改選定的內容
    2. 修改選定的樣式
  3. 添加控件
    1. 添加書簽
    2. 添加超鏈接
    3. 添加內容控件(Content Control)
  4. 基於用戶選中內容,執行程序
    1. WindowSelectionChange 事件
    2. 根據當前光標的位置,顯示懸浮框

以下是我對這些功能點的具體介紹

 

右鍵菜單

添加右鍵菜單

右鍵菜單是Word中相當常用的一個功能,我們在大部分的VSTO開發中也會通過修改這個菜單來擴展Word的功能。最通常地添加右鍵菜單的方法如下:

   1:      // 添加右鍵按鈕
   2:      Office.CommandBarButton addBtn = (Office.CommandBarButton)Application.CommandBars["Text"].Controls.Add(Office.MsoControlType.msoControlButton, missing, missing, missing, false);
   3:      
   4:      // 開始一個新Group,即在我們添加的Menu前加一條分割線   
   5:      addBtn.BeginGroup = true;
   6:      
   7:      // 為按鈕設置Tag
   8:      addBtn.Tag = "BookMarkAddin";
   9:      
  10:      // 添加按鈕上的文字
  11:      addBtn.Caption = "Add Bookmark";
  12:      
  13:      // 將按鈕初始設為不激活狀態
  14:      addBtn.Enabled = false;

顯示的效果為

01 右鍵菜單效果

 

控制右鍵菜單顯示

在很多情況下,我們希望根據用戶選擇內容來控制右鍵菜單的顯示,那么我們就需要用到WindowBeforeRightClick事件。以下是我在范例中寫的代碼,只有當用戶選擇兩個以上字符的時候,我才會把我剛才添加的右鍵菜單激活。請注意代碼里面的一些注釋,VSTO與Office的COM交互時,並不是很穩定,有很多需要注意的地方。

   1:      void Application_WindowBeforeRightClick(Word.Selection Sel, ref bool Cancel)
   2:      {
   3:          // 根據之前添加的Tag來找到我們添加的右鍵菜單
   4:          // 注意:我這里沒有通過全局變量來控制右鍵菜單,而是通過findcontrol來取得按鈕,因為這里的VSTO和COM對象處理有問題,使用全局變量來控制右鍵按鈕不穩定
   5:          Office.CommandBarButton addBtn = (Office.CommandBarButton)Application.CommandBars.FindControl(Office.MsoControlType.msoControlButton, missing, "BookMarkAddin", false);
   6:          addBtn.Enabled = false;
   7:          addBtn.Click -= new Office._CommandBarButtonEvents_ClickEventHandler(_RightBtn_Click);
   8:      
   9:          if (!string.IsNullOrWhiteSpace(Sel.Range.Text) && Sel.Range.Text.Length > 2)
  10:          {
  11:              addBtn.Enabled = true;
  12:              
  13:              // 這里是另外一個注意點,每次Click事件都需要重新綁定,你需要在之前先取消綁定。
  14:              addBtn.Click += new Office._CommandBarButtonEvents_ClickEventHandler(_RightBtn_Click);
  15:          }
  16:      }

 

刪除右鍵菜單

我建議在Addin啟動和關閉時候(ThisAddIn_Startup與ThisAddIn_Shutdown中),每次都清除由我們添加的右鍵菜單,雖然按照微軟的提示,如果在創建的時候把Temporary屬性設為true,系統會在程序退出時自動幫你刪除,但是根據我的經驗,微軟這個許諾沒有兌現。

   1:      private void RemoveRightBtns()
   2:      {
   3:          Office.CommandBarControls siteBtns = Application.CommandBars.FindControls(Office.MsoControlType.msoControlButton, missing, "BookMarkAddin", false);
   4:          // 這里我寫了一個循環,目標是清理所有由我創建的右鍵按鈕,尤其是由於Addin Crash時所遺留的按鈕
   5:          if (siteBtns != null)
   6:          {
   7:              foreach (Office.CommandBarControl btn in siteBtns)
   8:              {
   9:                  btn.Delete(true);
  10:              }
  11:          }
  12:      }

 

修改正文內容、樣式

修改選定的內容 
Word文檔內容的修改,主要是通過Range對象來實現的,比較容易。例如,你可以先通過 Application.ActiveDocument.Range(object start ,object end)方法來獲得一個你需要的Range,然后通過Range.Text來修改正文的內容,例如:

   1:      Word.Range range = Application.ActiveDocument.Range(0, 10);
   2:      if (range != null)
   3:      {
   4:          range.Text = "Justin";
   5:      }

這里需要指出的是,獲得Range的方式很多,你也可以通過用戶選擇的Selection對象來獲得Range,詳細內容可以參考我在上一篇隨筆中的Word對象模型部分

 

修改選定的樣式

修改樣式也是通過Range對象來實現的,這里我就寫兩個范例,一個是修改字體,一個是修改背景色(VSTO中稱為高亮色),大家可以在這里進一步擴展出去很多東西。

   1:      // 設置字體
   2:      range.Font.Name = "宋體";
   3:      
   4:      // 添加下划線(點)
   5:      range.Font.Underline = Word.WdUnderline.wdUnderlineDotted;
   6:      
   7:      // 將背景色設為黃
   8:      range.HighlightColorIndex = Word.WdColorIndex.wdYellow;

 

添加控件

Word在正文中提供了非常豐富的控件,例如書簽、超鏈接、注釋等,這些控件可以方便用戶編輯和閱讀文檔。所以也是我們開發人員需要注意的一個重點。添加書簽(以及其他的控件),在Word中實現的方法很多,本質都是通過獲得書簽集合(或其他對象的集合),然后通過這個集合的Add方法來添加數據。一般在添加的同時,我們會指定這個控件所對應的Range,即這個空間所包含的范圍。因為這種控件對象很多,我這里列舉幾個范例:

添加書簽

對Word中一段文字添加書簽,我們需要先去的這段文字的Range,然后通過以下方法來實現。

    // "VSTOBookMark"是書簽的名字
    Word.Bookmark mark = _Range.Bookmarks.Add("VSTOBookMark", _Range);


添加超鏈接

添加超鏈接和添加書簽類似,區別在於超鏈接需要指定url,且沒有名字。

    Word.Hyperlink link = range.Hyperlinks.Add(range, url);


添加內容控件(Content Control)

內容控件是Word 2007開始引如的新功能,是一批獨立的控件,用於增強用戶體驗,這里我介紹如何如在Word文檔中添加一個下拉框,這是一段Ribbon的代碼,為了方便我講解,我全部貼出來:

 

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using Microsoft.Office.Tools.Ribbon;
   6:   
   7:  using Office = Microsoft.Office.Core;
   8:  using Word = Microsoft.Office.Interop.Word;
   9:  using ToolsWord = Microsoft.Office.Tools.Word;
  10:   
  11:  namespace OfficeContentControlsDemo
  12:  {
  13:      public partial class Rb
  14:      {
  15:          private void Rb_Load(object sender, RibbonUIEventArgs e)
  16:          {
  17:   
  18:          }
  19:   
  20:          private void button1_Click(object sender, RibbonControlEventArgs e)
  21:          {
  22:              Word.Document currentDocument = Globals.ThisAddIn.Application.ActiveDocument;
  23:   
  24:              if (currentDocument.Paragraphs != null &&
  25:                  currentDocument.Paragraphs.Count != 0)
  26:              {
  27:                  // 在第一段文字前添加一個段落
  28:                  currentDocument.Paragraphs[1].Range.InsertParagraphBefore();
  29:                  currentDocument.Paragraphs[1].Range.Select();
  30:   
  31:                  // 將Interop的Document對象轉化為VSTO中的Document對象
  32:                  ToolsWord.Document document = Globals.Factory.GetVstoObject(currentDocument);
  33:   
  34:                  // 添加DropDownList
  35:                  ToolsWord.DropDownListContentControl dropdown = document.Controls.AddDropDownListContentControl(currentDocument.Paragraphs[1].Range, "MyContentControl");
  36:                  dropdown.PlaceholderText = "My DropdownList Test";
  37:                  dropdown.DropDownListEntries.Add("Test01", "01", 1);
  38:                  dropdown.DropDownListEntries.Add("Test02", "02", 2);
  39:                  dropdown.DropDownListEntries.Add("Test03", "03", 3);
  40:              }
  41:          }
  42:      }
  43:  }

運行效果

02 Content Control

這段代碼有兩個特殊的地方需要注意的:

  1. 首先,可能有人注意到了,我獲得第一個段落對象時,使用的是Paragraphs[1]而不是Paragraphs[0],這是因為VSTO中的很多集合的下標不是從0開始的,這可能是延續VB的風格。
  2. 其實,我在這里把Introp的Doucment對象轉化為了VSTO的Document對象。我們在前文中已經介紹了過了Introp的Doucment對象,它代表着一個Word文檔,即便你剛打開你的Word,是一個空的新文檔,也會有一個Document。而Microsoft.Office.Tools.Word下的Document。它們大體相同,區別在於
    1. Controls 屬性: 使用此屬性可在運行時在 Word 文檔中添加托管控件或者移除控件。
    2. VstoSmartTags 屬性: 使用此屬性可在文檔中添加Smart Tag(2010中 Smart Tag基本被廢了哭泣的臉)。
    3. InnerObject 屬性: 使用此屬性獲取 Microsoft.Office.Tools.Word.Document 的基礎 Microsoft.Office.Interop.Word.Document 對象。
    4. 文檔級事件: 僅在 Word 對象模型的應用程序級別提供的文檔級事件,例如 BeforeClose 和 BeforeSave。 也就是說,在 Word 對象模型中,這些事件在 Microsoft.Office.Interop.Word.Application 對象上可用。(而不是 Microsoft.Office.Interop.Word.Document 對象)

 

基於用戶選中內容,執行程序

在編程中,經常有客戶向我提問,能否根據用戶選擇的內容顯示相應的內容,這個功能看似復雜,其實實現起來很簡單。

WindowSelectionChange 事件

WindowsSelectionChange事件是這個功能的核心,每次當用戶移動光標或者點擊Word正文內容時都會觸發這個事件。事件參數為Selection,即當前選中的位置。接下來,我們來看一個實際的例子

  
根據當前光標的位置,顯示懸浮框

這是如何實現的代碼:

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using System.Xml.Linq;
   6:  using System.Windows.Forms;
   7:  using System.Drawing;
   8:   
   9:  using Word = Microsoft.Office.Interop.Word;
  10:  using Office = Microsoft.Office.Core;
  11:  using Microsoft.Office.Tools.Word;
  12:   
  13:  namespace BookMarkAddin
  14:  {
  15:      public partial class ThisAddIn
  16:      {
  17:          public FloatingPanel _FloatingPanel = null;
  18:   
  19:          private void ThisAddIn_Startup(object sender, System.EventArgs e)
  20:          {
  21:              this.Application.WindowSelectionChange += new Word.ApplicationEvents4_WindowSelectionChangeEventHandler(Application_WindowSelectionChange);
  22:          }
  23:          
  24:          void Application_WindowSelectionChange(Word.Selection Sel)
  25:          {
  26:              Globals.ThisAddIn._FloatingPanel = new FloatingPanel(bookmark);
  27:   
  28:                          // 當前用戶選中的屏幕坐標
  29:              Point currentPos = GetPositionForShowing(Sel);
  30:   
  31:              // 顯示懸浮框
  32:              Globals.ThisAddIn._FloatingPanel.Location = currentPos;
  33:              Globals.ThisAddIn._FloatingPanel.Show();
  34:          }
  35:   
  36:          private static Point GetPositionForShowing(Word.Selection Sel)
  37:          {
  38:              // get range postion
  39:              int left = 0;
  40:              int top = 0;
  41:              int width = 0;
  42:              int height = 0;
  43:              Globals.ThisAddIn.Application.ActiveDocument.ActiveWindow.GetPoint(out left, out top, out width, out height, Sel.Range);
  44:   
  45:              Point currentPos = new Point(left, top);
  46:              if (Screen.PrimaryScreen.Bounds.Height - top > 340)
  47:              {
  48:                  currentPos.Y += 20;
  49:              }
  50:              else
  51:              {
  52:                  currentPos.Y -= 320;
  53:              }
  54:              return currentPos;
  55:          }
  56:   
  57:          private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
  58:          {
  59:              try
  60:              {
  61:                  this.Application.WindowSelectionChange -= new Word.ApplicationEvents4_WindowSelectionChangeEventHandler(Application_WindowSelectionChange);
  62:              }
  63:              catch { }
  64:          }
  65:   
  66:          #region VSTO generated code
  67:          // .......
  68:          #endregion
  69:      }
  70:  }

最終的效果可以參考本文開始的視頻。這個功能可以推而廣之,比如可以把用戶當前選中的內容與Task Pane交互,這就看各位的需求了。

總結

至此,我已經介紹了Word插件開發的主要技巧,大家可以下載我制作的插件源代碼,里面包含了這些功能。

轉自:http://www.cnblogs.com/izualx/archive/2011/05/26/2058029.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM