首页 > 代码库 > 支持按行号区域文本选择的NotePad++插件开发

支持按行号区域文本选择的NotePad++插件开发

           近期发现NotePad++不支持按行号区间的文本复制,就想自己动手开发一个NotePad++插件,支持输入起始行号和结束行号,然后复制该区域的文本到新文档或者拷贝到系统剪切板,方便文本的操作。

效果例如以下图:

   技术分享

        本文主要介绍NotePad++插件开发的基本流程以及相关的注意点。

1、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

2、NotePad++开发过程

      开发一个NotePad++插件大概须要六步:

      第一。下载Np++插件模板project(http://notepad-plus.sourceforge.net/commun/pluginDemoTemplate/NppPluginTemplate.zip),而且解压到本地。

       第二,用VS打开project中的NppPluginTemplate.vcproj 项目,能够重命名该project。

    第三,在PluginDefinition.h头文件里定义插件名字,即

     const TCHAR NPP_PLUGIN_NAME[] = TEXT("Notepad++ plugin template");

    第四,定义插件中菜单的个数const int nbFunc = 2;

    第五,在PluginDefinition.cpp中将菜单名字和回调函数绑定。

    第六。实现相关菜单的回调函数。

3、与NotePad++主界面交互的主要数据结构

a.交互句柄

struct NppData {
	HWND _nppHandle;
	HWND _scintillaMainHandle;
	HWND _scintillaSecondHandle;
};

该数据结构包括和NP++的交互的句柄,当中包括主窗体和次窗体句柄。

该数据成员在载入插件的时候传入,以供插件和NP++主界面进行消息交互。

通过接口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 }
};


4、与NotePad++的消息交互

   与主界面的交互都是通过发送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

5.获取当前文档文本相关属性

  操作当前文本都是通过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 textargument 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.


6、注意事项

        对于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

支持按行号区域文本选择的NotePad++插件开发