標籤:
最近發現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++外掛程式模板工程(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中將菜單名字和回呼函數綁定。
第六,實現相關菜單的回呼函數。
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 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.
6、注意事項
對於Unicode模式下文本的操作需要轉換,否則會出現亂碼:
#ifdef UNICODE WCHARwText[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++外掛程式開發