标签:
最近发现NotePad++不支持按行号区间的文本复制,就想自己动手开发一个NotePad++插件,支持输入起始行号和结束行号,然后复制该区域的文本到新文档或者复制到系统剪切板,方便文本的操作。效果如下图:
本文主要介绍NotePad++插件开发的基本流程以及相关的注意点。
Notepad++是使用C++开发的开源免费的文本编辑器,它是一个多国语言版的编辑器,包含简体中文,使用它可以方便地编辑C、C++、Java、C#、XML、HTML、PHP、CSS等等纯文本文件,支持正则搜索、文件夹搜索、编码转换、文件比较等,可以媲美UltraEdit,最重要的是支持自己扩展插件的开发。
NotePad++官方网站的地址是:http://notepad-plus-plus.org/
Sourceforge地址:http://sourceforge.net/apps/mediawiki/notepad-plus
另外,Npp是基于开源控件Scintilla 开发的。Scintilla官网地址:http://www.scintilla.org/
插件中心:http://docs.notepad-plus-plus.org/index.php/Plugin_Central
开发一个NotePad++插件大概需要六步:
第一,下载Np++插件模板工程(http://notepad-plus.sourceforge.net/commun/pluginDemoTemplate/NppPluginTemplate.zip),并且解压到本地。
第二,用VS打开工程中的NppPluginTemplate.vcproj 项目,可以重命名该工程。
第三,在PluginDefinition.h头文件中定义插件名字,即
const TCHAR NPP_PLUGIN_NAME[] = TEXT("Notepad++
plugin template");
第四,定义插件中菜单的个数const int nbFunc = 2;
第五,在PluginDefinition.cpp中将菜单名字和回调函数绑定。
第六,实现相关菜单的回调函数。
a.交互句柄
struct NppData { HWND _nppHandle; HWND _scintillaMainHandle; HWND _scintillaSecondHandle; };
通过接口extern "C" __declspec(dllexport) void setInfo(NppData notpadPlusData)传入到插件,编写插件时,需要保存传过来的 notpadPlusData的值。
b.菜单与回调函数绑定
struct FuncItem { TCHAR _itemName[nbChar]; PFUNCPLUGINCMD _pFunc; int _cmdID; bool _init2Check; ShortcutKey *_pShKey; };该结构定义了插件菜单名与相应的回调函数的对应关系。如
//注册菜单回调函数 FuncItem CRunlogMenu::arrFuncItems[N_NBFUNCITEMS] = { { TEXT("Line Range Copy"), funcRangeCopy, 0, false, NULL }, //{ TEXT("Statistics"), funcStatistics, 0, false, NULL }, { TEXT(""), NULL, 0, false, NULL }, // separator { TEXT("About"), funcAbout, 0, false, NULL } };
与主界面的交互都是通过发送NPPM_开头的消息进行的,如获取当前文件的全路径名:
TCHAR str[100]; int strLen = 100; ::SendMessage(m_nppData._nppHandle, NPPM_GETNPPDIRECTORY, (WPARAM) strLen, (LPARAM) str);其他相关的NPPM_消息的介绍见:http://docs.notepad-plus-plus.org/index.php/Messages_And_Notifications
操作当前文本都是通过SCI消息来获取,如获取选择的文本内容
首先获取当前文档句柄:
int currentView = 0; SendNppMsg( NPPM_GETCURRENTSCINTILLA, 0, (LPARAM) ¤tView ); return ( (currentView == 0) ? m_nppData._scintillaMainHandle : m_nppData._scintillaSecondHandle );然后采用该句柄发送SCI_GETSELTEXT消息
::SendMessage(m_hSciWnd, uMsg, wParam, lParam);
下面给出几个比较重要的SCI消息,用于在开发插件的过程中参考:
SCI_GETTEXTRANGE(<unused>, Sci_TextRange *tr)
This collects the text between the positions cpMin
and cpMax
and copies it to lpstrText
(see structSci_TextRange
in Scintilla.h
).
If cpMax
is -1, text isreturned to the end of the document. The text is 0 terminated, so you mustsupply a buffer that is at least 1 character longer than the number ofcharacters you wish to read. The return value is the length
of the returnedtext not including the terminating 0.
获取总行
SCI_GETLINECOUNT
This returns the number of lines in thedocument. An empty document contains 1 line. A document holding only an end ofline sequence has 2 lines.
获取文档总字节数SCI_GETTEXTLENGTH
SCI_GETLENGTH
Both these messages return the length of thedocument in byte
获取文档是否修改
SCI_GETMODIFY
This returns non-zero if the document ismodified and 0 if it is unmodified. The modified status of a document is determinedby the undo position relative to the save point. The save point is set by SCI_SETSAVEPOINT
,
usually when you have saved data to a file.
选择文本
SCI_SETSEL(int anchorPos, intcurrentPos)
This message sets both the anchor and the currentposition. If currentPos
is negative, itmeans the end of the document. If anchorPos
is negative, itmeans remove any selection (i.e. set the anchor
to the same position as currentPos
). The caret is scrolled into view after this operation.
跳到某一行
SCI_GOTOLINE(int line)
This removes any selection and sets the caret atthe start of line number line
and scrolls the view(if needed) to make it visible. The anchor position is set the same as thecurrent position. If line
is
outside the linesin the document (first line is 0), the line set is the first or last.
获取当前的位置
SCI_GETCURRENTPOS
This returns the current position.
获取鼠标位置SCI_GETANCHOR
This returns the current anchor position.
选择所有文本
SCI_SELECTALL
This selects all the text in the document. Thecurrent position is not scrolled into view.
获取某行的首位置
SCI_POSITIONFROMLINE(int line)
This returns the document position thatcorresponds with the start of the line. If line
is negative, the positionof the line holding the start of the selection is returned. If line
is greater than the
lines in the document, the return valueis -1. If line
is equal to thenumber of lines in the document (i.e. 1 line past the last line), the returnvalue is the end of the document.
获取某行的长度
SCI_LINELENGTH(int line)
This returns the length of the line, includingany line end characters. If line
is negative orbeyond the last line in the document, the result is 0. If you want the lengthof the line not including any end of line characters, use SCI_GETLINEENDPOSITION(line)
- SCI_POSITIONFROMLINE(line)
.
拷贝当前选择的文本
SCI_GETSELTEXT(<unused>,char *text NUL-terminated)
This copies the currently selected text and aterminating 0 byte to the text
buffer. The buffersize should be determined by calling with a NULL pointer for the text
argument SCI_GETSELTEXT(0,0)
.
This allowsfor rectangular and discontiguous selections as well as simple selections. See MultipleSelection for information on how multipleand rectangular
selections and virtual space are copied.
对于Unicode模式下文本的操作需要转换,否则会出现乱码:
#ifdef UNICODE WCHAR wText[65]; ListView_GetItemText(_hListCtrl, _pCurProp->cursorItem, _pCurProp->cursorSubItem, wText, SUBITEM_LENGTH); wText[_pCurProp->cursorPos] = (TCHAR)wParam; ::WideCharToMultiByte(CP_ACP, 0, wText, -1, text, SUBITEM_LENGTH, NULL, NULL); #else ListView_GetItemText(_hListCtrl, _pCurProp->cursorItem, _pCurProp->cursorSubItem, text, SUBITEM_LENGTH); #endif
PS:附本次开发的基于行号文本区域复制的插件下载地址,解压后将NppPluginTextSelect.dll放在NotePad++的安装目录Notepad++\plugins下即可,然后重新启动NotePad++软件,在【插件】菜单中查找【Text Selection Helper】菜单项。
http://download.csdn.net/detail/xiaoding133/8912559
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/xiaoding133/article/details/46946441