欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

c++开发模板notepad++插件开发入门

程序员文章站 2023-01-28 13:52:52
notepad++的插件开发可以去它的官网下载模板,提供了c/c++,delphi,等语言的插件模板,这里提供一下c++的开发模板。 这个工程是能直接编译跑过的,它实现了两个命令, hellonot...

notepad++的插件开发可以去它的官网下载模板,提供了c/c++,delphi,等语言的插件模板,这里提供一下c++的开发模板。

这个工程是能直接编译跑过的,它实现了两个命令, hellonotepad++ 和hello (with dialog)

前者是实现了新建一个文档并输入了一段话,后者仅仅是弹出个messagebox,并不是我们想的是一个dock窗体.

这里先解释一下各个文件是干嘛用的.

menucmdid.h的意义跟他的名字一样,里面是定义了notepad++里面各个菜单项的id值,应该是点击了它对应的菜单触发了相应的回调的时候用得到,我这次的开发并没有用到这个文件里面的值.

notepad_plus_msgs.h里面则定义了一些枚举值,比如我们获取到的当前编辑状态是什么语言,其对应的枚举值在langtype里面就可以对应上,其中最主要的还是定义了notepad++本身的一些操作会促发的消息的枚举值,比如打开了文档,保存了文档,这些都是通过一个函数传过来给你的,你就需要根据类型去区分这次的操作是什么,从而做出响应

plugindefinition.h里面比较简单,就定义了几个函数跟插件的一些信息,比如plugininit是插件加载的时候调用的, commandmenuinit是初始化菜单用的,每个函数的顶部也有相关的英文说明.我们的每一个命令,都是要对应一个函数的,那些函数也可以定义在这个头文件里面, plugindefinition.cpp是它里面的每个函数的实现.

plugininterface.h就是整个插件跟notepad++交互的入口了,它定义了一些导出函数,比如:

void setinfo(nppdata),是将notepad++的句柄传递过来,我们根据句柄,就可以给它发送一些信号,这是我们能做二次开发的前提.

const tchar * getname()是返回这个插件的名字.

funcitem * getfuncsarray(int *)是获取我们所有的命令信息,我们自定义的命令都是没有参数跟返回值的.我们的命令是要以数组的方式存起来, int* 是用来获取我们的命令个数的,返回值是数组的首地址.

void benotified(scnotification *).这个函数就厉害了,这就是notepad++每次发生变化的时候用来通知我们的回调函数,无论是文件操作发生了变化或者是文本里面的内容发生了变化,比如你打开了文档,或者在文档里面新增或者删除了个字符,都会反应到这个函数里面. scnotification这个结构体的内容非常多,里面每一项变量都列举了哪些消息会用到它.

lresult messageproc(uint message, wparam wparam, lparam lparam) 这个好像是接收notepad++的窗体信号的,比如移动了它,最大化了,最小化了等,这个函数我没有用到.

然后就是resource.h了.就是在里面定义一些资源id而已

scintilla.h这个也很重要.在介绍这个之前,得先说明一下,notepad++的语法分析,语法高亮,智能提示,文本编辑等这些很重要的东西是基于scintilla做的,还有其他基于scintilla做的编辑器,比如notepad2, scite等,这个库在windows平台上就是一个窗体控件(这个东西也封装到qt上了,有机会一定要试一试),通过windows消息进行交互,你可以给他发一些消息,然后告诉他你应该做哪些事情,应该显示成什么样子,当他发生了改变,它也会给你发消息(通过benotified),告诉你他哪里变了.所以scintilla.h这里文件很重要,是交互的基础,是双方做的一个约定.里面基本都是一些宏定义跟结构体,关于这些宏定义跟结构体,在这里https://www.scintilla.org/scintilladoc.html可以找到英文的解释,做notepad++的插件开发 ,很多的工作都是在找我们需要用到的功能,是通过哪个消息去控制的.

最后就是nppplugindemo.cpp了,这个东西里面主要放了dllmain,dll加载的入口函数,跟plugininterface.h里面的一些导出函数的实现.然后我们如果是支持unicode字符集的话,还会有一个isunicode()的导出函数.

以上就是官方给的例子里面用到的文件说明了,官方还提供一些文件,但是这里没用到,比如dockingfeature文件夹里面的东西,那个是跟窗体有关的,后面会讲到.

以上的工程编译以后是个dll,放在notepad++的plugins文件夹,再打开软件,就会在插件菜单选项卡下看到这个插件了.

下面我们来看一下这个命令是怎么构成的.

struct funcitem {
         tchar_itemname[nbchar];
         pfuncplugincmd _pfunc;
         int _cmdid;
         bool _init2check;
         shortcutkey *_pshkey;
};

funcitem结构体就保存了命令的所有信息,其中_itemname是命令名字,不能超过64个字节, _pfunc是函数指针,要求无返回值无参数, _cmdid这个是注册以后的id值,这个我们不用管,是notepad++加载我们的命令以后去设置的,我们后面比如要做个有图标的选项卡,比如这些

就可以去取这个菜单id来使用了. _init2check这个是用来判断菜单前面是不是有个勾勾,标识菜单状态用的. shortcutkey就是默认快捷键了,它的结构体一看就明白,无须多说.

设置好命令的这些参数,我们就可以在命令对应的函数里面写我们的响应代码了,我们是通过句柄来发送消息的,下面我们来看一下hello这个命令.

void hello()
{
    // open a new document
    ::sendmessage(nppdata._npphandle, nppm_menucommand, 0, idm_file_new);

    // get the current scintilla
    int which = -1;
    ::sendmessage(nppdata._npphandle, nppm_getcurrentscintilla, 0, (lparam)&which);
    if (which == -1)
        return;
    hwnd curscintilla = (which == 0)?nppdata._scintillamainhandle:nppdata._scintillasecondhandle;

    // say hello now :
    // scintilla control has no unicode mode, so we use (char *) here
    ::sendmessage(curscintilla, sci_settext, 0, (lparam)"hello, notepad++!");
}
::sendmessage(nppdata._npphandle, nppm_menucommand, 0,idm_file_new);

这里发送了一个消息,句柄就是nppdata._npphandle,nppdata这个是一个全局静态的变量,它里面存放了notepad++的句柄跟scintilla的句柄,但是scintilla有两个,应该是考虑了文档对比等功能的时候要用两个编辑框吧,一般我们用_scintillamainhandle就可以了.

然后这个消息的第二个参数是nppm_menucommand,代表是菜单消息的,然后最后是idm_file_new,就是相当于点击了文件新建的菜单选项了,换成其他的比如idm_file_close啊就是关闭文档了.

然后第二步是获取scintilla句柄,代码是

int which = -1;

::sendmessage(nppdata._npphandle, nppm_getcurrentscintilla, 0,(lparam)&which);

if (which == -1)

return;

hwnd curscintilla = (which== 0)?nppdata._scintillamainhandle:nppdata._scintillasecondhandle;

还是先通过notepad++的句柄和getcurrentscintilla,获取scintilla的状态,是0就是main那个句柄,否则就是second那个句柄,如果返回-1,那么就是没有激活的编辑框

第三步就是往里面写内容了

::sendmessage(curscintilla, sci_settext, 0, (lparam)"hello,notepad++!");

通过scintilla的句柄和settext这个信号变量,然后在最后的参数里面写上要设置的文本的内容.就完成了文本的设置.

从这里来看,做notepad++的开发也并不难,只要去摸清楚那些操作对应的信号枚举值跟参数,就可以了,具体就可以去scintilla官网查文档了.

入门开发就是这么简单.