创建属于自己的OneNote插件
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插件相关推荐
- 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | 主线程创建 Activity 实例之前使用插件 Activity 类替换占位的组件 )
Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...
- 如何创建一个基本JQuery的插件
如何创建一个基本的插件 有时您希望在整个代码中提供一些功能.例如,也许你想要一个单一的方法,你可以调用一个jQuery选择,对选择执行一系列的操作.在这种情况下,您可能需要编写一个插件. 链接jQue ...
- VS2019正确创建C++步骤以及扩展插件美化你的VS2019的IDE开发环境
使用扩展插件来美化你的IDE开发环境 前言 vs2019创建c++的步骤 1.错误分析 2.解决方法 拓展插件 附件 结语 前言 在安装了Visual Studio 2019社区版后,有的小伙伴会觉得 ...
- eclipse创建pojo_使用Eclipse Hibernate插件逐步为POJO域Java类和hbm自动生成代码
eclipse创建pojo 概述: 在本教程中,我们将使用Eclipse Hibernate工具自动生成域对象和相应的hbm xml文件. 如果您正在处理大型或中型项目,并且开始时有超过5个以上的表, ...
- 10条建议让你创建更好的jQuery插件(转载)
为了避免重复造轮子,自己手动开发jquery 插件,让小组其他成员可以直接使用.学习开发中,看到Phillip Senn 写的 关于jquery 插件开发注意10点,转载之! ------------ ...
- 我的世界(9)-服务器地图创建、管理(Multiverse插件)
文章目录 前言 相关介绍 上一篇笔记 下一篇笔记 一.指令 二.配置 [1]. config.yml [2]. worlds.yml 三.地图的架构 四.世界创建 五.地图导入 前言 Minecraf ...
- OneNote插件找不到选项卡的解决
OneNote是一个功能强大的数字笔记系统.而各种不同的插件,让OneNote更加趋于完善. 一般安装了一些新插件,都会有新的选项卡出现.某天偶然间发现插件的选项卡都没了.莫非我的插件都蒸发了?答案是 ...
- 创建自己的Visual Studio插件仓库
文章目录 使用插件的问题 如何建立私有插件仓库 下载插件安装文件 创建插件仓库描述Atom.xml 添加私有插件仓库 下载安装 共享插件仓库 使用插件的问题 目前在使用Visual Studio 20 ...
- Vue 3 + TypeScript + Vite创建项目并安装常用插件
创建项目 创建项目 npm init vite √ Project name: ... wego-admin √ Select a framework: » vue √ Select a varian ...
- Joomla教程:创建Joomla语言包安装插件 【转】
当你为第三方的插件扩展做翻译时,通常是直接做到插件包中的,但有时你的语言包需要单独提交.后面这种情况下,也许会不大容易让使用者知道应该将语言包上传到哪里. 为了避免这种情况的发生,我们可以模仿Joom ...
最新文章
- 【图灵有聊】说好的安全呢?
- 编译linux内核报错‘make menuconfig‘ requires the ncurses libraries
- 处理通知栏点击操作_解读 | 企业主动披露申请 e操作来啦
- Nginx实现负载均衡时常用的分配服务器策略
- 多功能监护系统开发与设计
- 基于py3和pymysql的数据库查询,查询某几列的数据
- WinFrm程序使用的图片展示控件.带删除的
- 产品经理业务流程图的绘制流程分享
- 直插电阻的分类和区别
- kakfa安装与简单使用
- SpringBoot ActiveMQ 整合使用
- 免费皮肤、英雄池限免,腾讯手游有多卷?
- 【Linux】树状目录结构
- 同时和同步有什么区别?
- firefox linux 中文字体,Ubuntu下的Firefox字体配置方案
- 每年技术研究方向一览
- 快速认识陌生字的方法!几秒钟就可查到怎么读!
- android usb 摄像头 分辨率,Android 驱动USB摄像头
- 三维计算机动画的特征是真实性,三维动画的基本内涵与艺术特点
- 如何在3dmax中添加声音轨道?
热门文章
- 手机能打开的表白代码_不是程序员都能学会的5个表白代码,一学就会,附源码...
- 批处理Bat教程-第一章:前言
- 使用TF卡烧录Jetson NX开发板
- 用java代码模拟鼠标双击事件
- DNF单机版搭建(局域网、外网)
- bochs运行xp_bochs安卓最新版下载
- vfp 什么是VFP?
- Mac OS黑苹果系统安装工具及懒人版镜像文件 for macOS High Sierra/macOS Sierra
- 服务器拷贝数据库文件,服务器怎么拷贝数据库文件
- python实现第三方验证码获取_Python 原生爬虫教程