Notepad++插件开发实战:核心功能开发详解
1. 获取当前编辑窗口内容
// 获取当前编辑窗口句柄
HWND hScintilla = (HWND)::SendMessage(nppData._nppHandle, NPPM_GETCURRENTSCINTILLA, 0, 0);
int which = -1;
::SendMessage(nppData._nppHandle, NPPM_GETCURRENTSCINTILLA, 0, (LPARAM)&which);
hScintilla = (which == 0) ? nppData._scintillaMainHandle : nppData._scintillaSecondHandle;
// 获取当前文档内容
int length = ::SendMessage(hScintilla, SCI_GETLENGTH, 0, 0);
char* buffer = new char[length + 1];
::SendMessage(hScintilla, SCI_GETTEXT, length + 1, (LPARAM)buffer);
// 使用后释放内存
delete[] buffer;
2. 文本查找与替换API
// 设置搜索参数
Sci_TextToFind ttf;
ttf.chrg.cpMin = 0;
ttf.chrg.cpMax = -1;
ttf.lpstrText = "search_text";
// 执行查找
int pos = ::SendMessage(hScintilla, SCI_FINDTEXT, SCFIND_MATCHCASE, (LPARAM)&ttf);
// 替换文本
if (pos != -1) {
::SendMessage(hScintilla, SCI_SETTARGETRANGE, ttf.chrgText.cpMin, ttf.chrgText.cpMax);
::SendMessage(hScintilla, SCI_REPLACETARGET, -1, (LPARAM)"new_text");
}
3. 正则表达式处理示例
// 设置正则表达式搜索
::SendMessage(hScintilla, SCI_SETSEARCHFLAGS, SCFIND_REGEXP | SCFIND_MATCHCASE, 0);
// 编译正则表达式
TCHAR pattern[] = _T("\\b\\w+\\b");
::SendMessage(hScintilla, SCI_SETTARGETSTART, 0, 0);
::SendMessage(hScintilla, SCI_SETTARGETEND, -1, 0);
// 循环匹配
int pos = 0;
while ((pos = ::SendMessage(hScintilla, SCI_SEARCHINTARGET,
_tcslen(pattern), (LPARAM)pattern)) != -1)
{
int start = ::SendMessage(hScintilla, SCI_GETTARGETSTART, 0, 0);
int end = ::SendMessage(hScintilla, SCI_GETTARGETEND, 0, 0);
// 处理匹配结果...
::SendMessage(hScintilla, SCI_SETTARGETSTART, end, 0);
::SendMessage(hScintilla, SCI_SETTARGETEND, -1, 0);
}
4. 自定义对话框设计实现
// 对话框资源ID定义
#define IDD_MY_DIALOG 101
#define IDC_EDIT_BOX 1001
// 对话框过程函数
INT_PTR CALLBACK DialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK) {
TCHAR text[256];
GetDlgItemText(hwnd, IDC_EDIT_BOX, text, 255);
// 处理输入文本...
EndDialog(hwnd, IDOK);
}
break;
}
return FALSE;
}
// 显示对话框
void showDialog() {
DialogBoxParam(
hInstance,
MAKEINTRESOURCE(IDD_MY_DIALOG),
nppData._nppHandle,
DialogProc,
0
);
}
关键开发技巧
Scintilla消息机制
- 使用
SCI_
前缀消息操作编辑器 - 位置参数使用字节偏移量而非行号
- 文本处理注意UTF-8编码转换
- 使用
线程安全注意事项
// GUI操作必须在主线程执行 ::PostMessage(nppData._nppHandle, NPPM_MSGTOPLUGIN, (WPARAM)_T("MyPlugin"), (LPARAM)&myNotification);
高效文本处理
- 大文件处理使用分块读取
- 避免频繁的整文档获取
- 使用
SCI_GETLINECHARACTERPTR
直接访问行缓冲
跨版本兼容性
// 通过NPPM_GETNPPVERSION获取版本 int nppVersion = ::SendMessage(nppData._nppHandle, NPPM_GETNPPVERSION, 0, 0); int major = (nppVersion >> 16) & 0xFFFF; int minor = nppVersion & 0xFFFF;
调试技巧
// 输出调试信息到控制台
void debugLog(const char* message) {
char buffer[1024];
sprintf_s(buffer, "[MyPlugin] %s\n", message);
::OutputDebugStringA(buffer);
}
// 内存泄漏检测(MSVC)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
int APIENTRY DllMain(HANDLE hModule, DWORD reason, LPVOID reserved) {
if (reason == DLL_PROCESS_ATTACH) {
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
}
return TRUE;
}
实战示例:全文批注插件
void addComments() {
HWND hScintilla = getCurrentScintilla();
// 获取选中文本范围
int start = ::SendMessage(hScintilla, SCI_GETSELECTIONSTART, 0, 0);
int end = ::SendMessage(hScintilla, SCI_GETSELECTIONEND, 0, 0);
// 逐行处理
int lineStart = ::SendMessage(hScintilla, SCI_LINEFROMPOSITION, start, 0);
int lineEnd = ::SendMessage(hScintilla, SCI_LINEFROMPOSITION, end, 0);
for (int line = lineStart; line <= lineEnd; ++line) {
int pos = ::SendMessage(hScintilla, SCI_POSITIONFROMLINE, line, 0);
::SendMessage(hScintilla, SCI_INSERTTEXT, pos, (LPARAM)"// ");
}
}
开发注意事项:
- 使用
SCI_BEGINUNDOACTION
/SCI_ENDUNDOACTION
包裹批量操作 - 跨平台兼容性避免Windows API硬编码
- 插件初始化时注册
NPPN_READY
通知 - 多视图场景区分主/副编辑窗口
通过以上核心功能实现,开发者可构建:
- 代码格式化工具
- 自定义语法检查器
- 文档分析插件
- 文本处理工作流自动化工具
提示:官方插件模板可从Notepad++仓库获取(Plugins->Plugin Template),建议基于模板开发确保结构规范