OneNote是一款很受欢迎的笔记软件,其分章节的结构特点非常适合记录课堂笔记,读书笔记和知识体系,但与Office其他明星产品相比,OneNote的资历更短,功能也不及Word、Excel强大,还好我们可以通过AddIn来扩展OneNote的功能。

发现国内OneNote插件开发的资料基本没有,好不容易找到两篇也是针对2010版的开发,在此附上链接:

http://www.malteahrens.com/#/blog/howto-onenote-dev/

https://support.microsoft.com/en-us/help/2555352/how-to-develop-an-onenote-2010-ribbon-add-in-application

现在正式进入开发阶段,由于涉及注册表,所以需要以管理员权限打开VS,不然会无法生成工程的。

第一步:创建工程

首先要完善开发环境,OneNote二次开发不像Word、Excel有现成的VSTO工具,需要创建安装和部署的工程,已有教程中都是用VS2010自带的安装和部署工具来安装测试,VS2015移除了该功能,需要手动安装一个部署软件,这是地址Microsoft Visual Studio 2015 Installer Projects。

接下来创建工程,我们需要创建一个类库,如图

工程创建好后设置工程属性,在程序集信息中勾选使程序集COM可见,

在生成中勾选为COM互操作注册

第二步:创建Ribbon配置文件

1.添加一个叫ribbon的XML文件

2.将配置文件存入工程资源以便运行时访问

3.写ribbon配置文件代码

此处我们添加一个叫做Custom的Ribbon选项卡

<?xml version="1.0" encoding="utf-8" ?>
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" loadImage="GetImage"><ribbon><tabs><tab id="tabCustom" label="Custom"><group id="groupHello" label="Hello"><button id="buttonHello" label="Hello World!" size="large" screentip="Press this for a 'Hello World!' message" onAction="showHello" image="HelloWorld.png" /></group></tab></tabs></ribbon>
</customUI>

如果想在已有选项卡中添加功能,只需要将tab中的值改为idMso="指定Tab页"即可

第三部:写功能代码

1.为工程添加引用,这里主要需要添加三个引用,分别是:Extensibility,office和Microsoft OneNote 15.0 Type Library

2.在Class1中添加如下using

using System.Runtime.InteropServices;
using Extensibility;
using Microsoft.Office.Core;
using OneNote = Microsoft.Office.Interop.OneNote;

3.创建一个新的GUID以标识工程

  工具→创建GUID(G)

  

  将创建的GUID粘贴到记事本,之后还要用

4.在Class1上添加标记

[Guid("743A0108-BBE3-4D22-A6A8-3C00ADD2B610"), ProgId("HelloWorld.Class1")]
public class Class1
{
}

5.实现接口IDTExtensibility2

  IDTExtensibility2来自Extensibility名空间,需要实现以下方法:  

public void OnAddInsUpdate(ref Array custom) { }
public void OnBeginShutdown(ref Array custom) { }
public void OnConnection(object Application, ext_ConnectMode ConnectMode, object AddInInst, ref Array custom) { }
public void OnDisconnection(ext_DisconnectMode RemoveMode, ref Array custom) { }
public void OnStartupComplete(ref Array custom) { }

6.OnConnection()方法在插件加载时调用,传递了OneNote的实例,我们创建一个object类型的变量application来接收

private object application;
public void OnConnection(object Application, ext_ConnectMode ConnectMode, object AddInInst, ref Array custom)
{application = Application;
}

7.为了实现Ribbon按钮事件,需要添加IRibbonExtensibility接口,IRibbonExtensibility来自Microsoft.Office.Core名空间,包含获取Ribbon界面的方法

public string GetCustomUI(string RibbonID)
{return Properties.Resources.ribbon;
}

此时返回工程中的ribbon.xml配置信息

8.现在实现与ribbon.xml文件中按钮的onAction事件调用的函数,注意此函数是公共的并且以IRibbonControl作为参数

public void showHello(IRibbonControl control)
{var app = application as OneNote.Application;var win = app.Windows;string id = (application as OneNote.Application).Windows.CurrentWindow.CurrentPageId;string title;app.GetPageContent(id, out title);var doc = XDocument.Parse(title);string pageTitle = doc.Descendants().FirstOrDefault().Attribute("ID").NextAttribute.Value;MessageBox.Show("Current Page = " + pageTitle, "Hello World!");
}

这里实现了输出当前页标题的功能。

9.为Ribbon按钮添加图片,需要将图片添加到资源中

还要实现ribbon.xml中loadImage的GetImage方法

public IStream GetImage(string imageName)
{MemoryStream mem = new MemoryStream();Properties.Resources.HelloWorld.Save(mem, ImageFormat.Png);return new CCOMStreamWrapper(mem);
}

这里采用将图片转为流的方式

class CCOMStreamWrapper: IStream
{public CCOMStreamWrapper(System.IO.Stream streamWrap){m_stream = streamWrap;}public void Clone(out IStream ppstm){ppstm = new CCOMStreamWrapper(m_stream);}public void Commit(int grfCommitFlags){m_stream.Flush();}public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten){}public void LockRegion(long libOffset, long cb, int dwLockType){throw new System.NotImplementedException();}public void Read(byte[] pv, int cb, IntPtr pcbRead){Marshal.WriteInt64(pcbRead, m_stream.Read(pv, 0, cb));}public void Revert(){throw new System.NotImplementedException();}public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition){long posMoveTo = 0;Marshal.WriteInt64(plibNewPosition, m_stream.Position);switch (dwOrigin){case 0:{/* STREAM_SEEK_SET */posMoveTo = dlibMove;}break;case 1:{/* STREAM_SEEK_CUR */posMoveTo = m_stream.Position + dlibMove;}break;case 2:{/* STREAM_SEEK_END */posMoveTo = m_stream.Length + dlibMove;}break;default:return;}if (posMoveTo >= 0 && posMoveTo < m_stream.Length){m_stream.Position = posMoveTo;Marshal.WriteInt64(plibNewPosition, m_stream.Position);}}public void SetSize(long libNewSize){m_stream.SetLength(libNewSize);}public void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int grfStatFlag){pstatstg = new System.Runtime.InteropServices.ComTypes.STATSTG();pstatstg.cbSize = m_stream.Length;if ((grfStatFlag & 0x0001/* STATFLAG_NONAME */) != 0)return;pstatstg.pwcsName = m_stream.ToString();}public void UnlockRegion(long libOffset, long cb, int dwLockType){throw new System.NotImplementedException();}public void Write(byte[] pv, int cb, IntPtr pcbWritten){Marshal.WriteInt64(pcbWritten, 0);m_stream.Write(pv, 0, cb);Marshal.WriteInt64(pcbWritten, cb);}private System.IO.Stream m_stream;
}

10.当关闭OneNote的时候要确保清空占用的内存

public void OnDisconnection(ext_DisconnectMode RemoveMode, ref Array custom)
{application = null;GC.Collect();GC.WaitForPendingFinalizers();
}

public void OnBeginShutdown(ref Array custom)
{if (application != null){application = null;}
}

11.Class1的全部代码如下:

using System;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Windows.Forms;
using System.Xml.Linq;
using Extensibility;
using Microsoft.Office.Core;
using OneNote = Microsoft.Office.Interop.OneNote;namespace HelloWorld
{[Guid("743A0108-BBE3-4D22-A6A8-3C00ADD2B610"), ProgId("HelloWorld.Class1")]public class Class1: IDTExtensibility2, IRibbonExtensibility{private OneNote.Application onApp = new OneNote.Application();private object application;public void OnConnection(object Application, ext_ConnectMode ConnectMode, object AddInInst, ref Array custom){application = Application;}public void OnDisconnection(ext_DisconnectMode RemoveMode, ref Array custom){application = null;GC.Collect();GC.WaitForPendingFinalizers();}public void OnAddInsUpdate(ref Array custom){}public void OnStartupComplete(ref Array custom){}public void OnBeginShutdown(ref Array custom){if (application != null){application = null;}}public string GetCustomUI(string RibbonID){return Properties.Resources.ribbon; }public void showHello(IRibbonControl control){var app = application as OneNote.Application;var win = app.Windows;string id = (application as OneNote.Application).Windows.CurrentWindow.CurrentPageId;string title;app.GetPageContent(id, out title);var doc = XDocument.Parse(title);string pageTitle = doc.Descendants().FirstOrDefault().Attribute("ID").NextAttribute.Value;MessageBox.Show("Current Page ID = " + pageTitle, "Hello World!");}public IStream GetImage(string imageName){MemoryStream mem = new MemoryStream();Properties.Resources.HelloWorld.Save(mem, ImageFormat.Png);return new CCOMStreamWrapper(mem);}}
}

第四步:安装和部署

1.在解决方案中添加安装和部署的项目

2.修改注册表,右击Setup工程→View→注册表,将注册表中的项清空

3.按如下步骤新建键

HKEY_CLASSES_ROOT→AppID→{工程的GUID}

  右击→New:

类型 名称
字符串值 DllSurrogate  

HKEY_CLASSES_ROOT→CLSID→{工程的GUID}

  右击→New:

类型 名称
字符串值 AppID {工程的GUID}

HKEY_CURRENT_USER→Software→Microsoft→Office→OneNote→AddIns→工程的ProgId

  右击→New:

类型 名称
字符串值 Description 自定义的工程描述
字符串值 FriendlyName 自定义的工程名称
DWORD LoadBehavior 3

HKEY_LOCAL_MACHINE→Software→Classes→AppID→{工程的GUID}

  右击→New:

类型 名称
字符串值 DllSurrogate  

HKEY_LOCAL_MACHINE→Software→Classes→CLSID→{工程的GUID}

  右击→New:

类型 名称
字符串值 AppID {工程的GUID}

完成后的效果如图所示:

4.此时就可以安装我们的工程了,首先如图进入文件系统

然后选择安装目录:Application Folder (一般是 C:\Program Files\ ···) → 右击 → Add → Project Output… → OK

5.此时就可以生成解决方案了,如果报错,你可能需要用管理员权限打开VS

6.最后如图进行安装就完成了:

转载于:https://www.cnblogs.com/JohnHwangBlog/p/6305380.html

创建属于自己的OneNote插件相关推荐

  1. 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | 主线程创建 Activity 实例之前使用插件 Activity 类替换占位的组件 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  2. 如何创建一个基本JQuery的插件

    如何创建一个基本的插件 有时您希望在整个代码中提供一些功能.例如,也许你想要一个单一的方法,你可以调用一个jQuery选择,对选择执行一系列的操作.在这种情况下,您可能需要编写一个插件. 链接jQue ...

  3. VS2019正确创建C++步骤以及扩展插件美化你的VS2019的IDE开发环境

    使用扩展插件来美化你的IDE开发环境 前言 vs2019创建c++的步骤 1.错误分析 2.解决方法 拓展插件 附件 结语 前言 在安装了Visual Studio 2019社区版后,有的小伙伴会觉得 ...

  4. eclipse创建pojo_使用Eclipse Hibernate插件逐步为POJO域Java类和hbm自动生成代码

    eclipse创建pojo 概述: 在本教程中,我们将使用Eclipse Hibernate工具自动生成域对象和相应的hbm xml文件. 如果您正在处理大型或中型项目,并且开始时有超过5个以上的表, ...

  5. 10条建议让你创建更好的jQuery插件(转载)

    为了避免重复造轮子,自己手动开发jquery 插件,让小组其他成员可以直接使用.学习开发中,看到Phillip Senn 写的 关于jquery 插件开发注意10点,转载之! ------------ ...

  6. 我的世界(9)-服务器地图创建、管理(Multiverse插件)

    文章目录 前言 相关介绍 上一篇笔记 下一篇笔记 一.指令 二.配置 [1]. config.yml [2]. worlds.yml 三.地图的架构 四.世界创建 五.地图导入 前言 Minecraf ...

  7. OneNote插件找不到选项卡的解决

    OneNote是一个功能强大的数字笔记系统.而各种不同的插件,让OneNote更加趋于完善. 一般安装了一些新插件,都会有新的选项卡出现.某天偶然间发现插件的选项卡都没了.莫非我的插件都蒸发了?答案是 ...

  8. 创建自己的Visual Studio插件仓库

    文章目录 使用插件的问题 如何建立私有插件仓库 下载插件安装文件 创建插件仓库描述Atom.xml 添加私有插件仓库 下载安装 共享插件仓库 使用插件的问题 目前在使用Visual Studio 20 ...

  9. Vue 3 + TypeScript + Vite创建项目并安装常用插件

    创建项目 创建项目 npm init vite √ Project name: ... wego-admin √ Select a framework: » vue √ Select a varian ...

  10. Joomla教程:创建Joomla语言包安装插件 【转】

    当你为第三方的插件扩展做翻译时,通常是直接做到插件包中的,但有时你的语言包需要单独提交.后面这种情况下,也许会不大容易让使用者知道应该将语言包上传到哪里. 为了避免这种情况的发生,我们可以模仿Joom ...

最新文章

  1. 【图灵有聊】说好的安全呢?
  2. 编译linux内核报错‘make menuconfig‘ requires the ncurses libraries
  3. 处理通知栏点击操作_解读 | 企业主动披露申请 e操作来啦
  4. Nginx实现负载均衡时常用的分配服务器策略
  5. 多功能监护系统开发与设计
  6. 基于py3和pymysql的数据库查询,查询某几列的数据
  7. WinFrm程序使用的图片展示控件.带删除的
  8. 产品经理业务流程图的绘制流程分享
  9. 直插电阻的分类和区别
  10. kakfa安装与简单使用
  11. SpringBoot ActiveMQ 整合使用
  12. 免费皮肤、英雄池限免,腾讯手游有多卷?
  13. 【Linux】树状目录结构
  14. 同时和同步有什么区别?
  15. firefox linux 中文字体,Ubuntu下的Firefox字体配置方案
  16. 每年技术研究方向一览
  17. 快速认识陌生字的方法!几秒钟就可查到怎么读!
  18. android usb 摄像头 分辨率,Android 驱动USB摄像头
  19. 三维计算机动画的特征是真实性,三维动画的基本内涵与艺术特点
  20. 如何在3dmax中添加声音轨道?

热门文章

  1. 手机能打开的表白代码_不是程序员都能学会的5个表白代码,一学就会,附源码...
  2. 批处理Bat教程-第一章:前言
  3. 使用TF卡烧录Jetson NX开发板
  4. 用java代码模拟鼠标双击事件
  5. DNF单机版搭建(局域网、外网)
  6. bochs运行xp_bochs安卓最新版下载
  7. vfp 什么是VFP?
  8. Mac OS黑苹果系统安装工具及懒人版镜像文件 for macOS High Sierra/macOS Sierra
  9. 服务器拷贝数据库文件,服务器怎么拷贝数据库文件
  10. python实现第三方验证码获取_Python 原生爬虫教程