開發OneNote Add-Ins詳解(下)

開發OneNote Add-Ins詳解(下)

接續上一篇UI已經完成了之後,這一篇就繼續來把功能補上。

 

在開始之前,強力推薦安裝 OMSpy - A OneNote developer’s tool

這套軟體可以看到目前OneNote的文件結構

我覺得與其看文件,不如從現有的結構中學習反而比較快速。

例如這篇的目標是把選擇的圖片插入到OneNote的Page上,那我就先在空白的頁面上

先插入一張圖片,在開啟OMSpy工具來看長出了什麼樣的XML

image

由右上角的Content內容可得知,我在OneNote做了那些設定會長出什麼樣的XML出來。

例如圖片,則只要有下列這樣的結構就可以了

<one:Image format="png" originalPageNumber="0">
   <one:Position x="36.0" y="86.4000015258789" z="0" />
   <one:Size width="18.0" height="18.0" />
   <one:Data>
		Base64String資料
   </one:Data>
</one:Image>

 

接著在上一篇留下的gallery_Click事件中,加上

//取得組件所在目錄
static string codeBase = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

public void gallery_Click(IRibbonControl control, string selectedId, int selectedIndex)
{
    var path = Path.Combine(codeBase, "images");

    //經由組件所在目錄加上ID的命名規則找到圖片
    var imagePath = Path.Combine(path, selectedId.Substring(selectedId.IndexOf('_') + 1));

    //讀取圖片並轉為Base64String
    var baseString = Convert.ToBase64String(File.ReadAllBytes(imagePath));

    //插入到OneNote
    InsertIconToOneNotePage(baseString);
}

在讀取圖片之後,剩下的就是一些對XML的操作,由於這些操作不是本篇重點,因此我就簡單帶過

private void InsertIconToOneNotePage(string base64String)
{
    string notebookXml;

    //取得OneNote內容的結構,第二個參數可指定範圍
    onApp.GetHierarchy(null, HierarchyScope.hsPages, out notebookXml);

    //將string轉為XDocument
    var doc = XDocument.Parse(notebookXml);

    //取得命名空間
    ns = doc.Root.Name.Namespace;

    //取得目前可視頁面
    var pageNode = doc.Descendants(ns + "Page")
                      .Where(n => n.Attribute("isCurrentlyViewed") != null && n.Attribute("isCurrentlyViewed").Value == "true")
                      .FirstOrDefault();

    if (pageNode != null)
    {
        //頁面ID
        var existingPageId = pageNode.Attribute("ID").Value;

        //滑鼠游標位置
        string[] position = GetMousePointPosition(existingPageId);

        //插入圖片
        var page = InsertIcon(base64String, position);

        page.Root.SetAttributeValue("ID", existingPageId);

        //更新內容
        onApp.UpdatePageContent(page.ToString(), DateTime.MinValue);
    }
}

取得滑鼠游標位置

/// <summary>
/// 取得滑鼠所在的點
/// Get Mouse Point
/// </summary>
private string[] GetMousePointPosition(string pageID)
{
    string pageXml;
    //如果指定PageID的內容
    onApp.GetPageContent(pageID, out pageXml, PageInfo.piSelection);

    //因為當滑鼠在某個區塊時,Outline節點會多了一個Attribute為selected
    //因此可利用此來判斷游標位置
    var node = XDocument.Parse(pageXml).Descendants(ns + "Outline")
                                       .Where(n => n.Attribute("selected") != null && n.Attribute("selected").Value == "partial")
                                       .FirstOrDefault();
    if (node != null)
    {
        //滑鼠座標會放在Position元素中
        var attrPos = node.Descendants(ns + "Position").FirstOrDefault();
        if (attrPos != null)
        {
            var x = attrPos.Attribute("x").Value;
            var y = attrPos.Attribute("y").Value;
            return new string[] { x, y };
        }
    }
    return null;
}

 

插入表情符號

/// <summary>
/// 插入表情符號至 OneNote
/// Generate XML Insert To OneNote
/// </summary>
private XDocument InsertIcon(string base64String, string[] position)
{
    //由前面觀察到的插入圖片產生的結構
    //依樣畫葫蘆寫出一樣的結構

    //format這邊寫死成png,可以需求改成動態的
    XElement imageElement = new XElement(ns + "Image");
    imageElement.Add(new XAttribute("format", "png"));
    imageElement.Add(new XAttribute("originalPageNumber", "0"));

    //如果有找到滑鼠的座標,則插入一個Position的XElement
    if (position != null && position.Length == 2)
    {
        XElement pos = new XElement(ns + "Position");
        pos.Add(new XAttribute("x", position[0]));
        pos.Add(new XAttribute("y", position[1]));
        imageElement.Add(pos);
    }

    //插入Data XElement,內容為Base64String
    XElement dataElement = new XElement(ns + "Data", base64String);
    imageElement.Add(dataElement);

    XElement page = new XElement(ns + "Page");
    page.Add(imageElement);

    XDocument doc = new XDocument();
    doc.Add(page);

    return doc;
}

重新編譯並且安裝過後,就完成了。

image

 

由於是範例的關係,所以功能並不完善,也沒有介面可以新增Icon

(如果真的要新增,必須於安裝路徑修改Ribbon.xml及放入圖片到images資料夾)

如果有興趣的可以試著寫寫看,並且分享讓大家有越來越多好用的工具。

 

範例原始檔下載