Notepad++插件开发实战

Notepad++插件开发实战:核心功能开发详解

1. 获取当前编辑窗口内容

cpp 复制代码
// 获取当前编辑窗口句柄
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

cpp 复制代码
// 设置搜索参数
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. 正则表达式处理示例

cpp 复制代码
// 设置正则表达式搜索
::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. 自定义对话框设计实现

cpp 复制代码
// 对话框资源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
    );
}

关键开发技巧

  1. Scintilla消息机制

    • 使用SCI_前缀消息操作编辑器
    • 位置参数使用字节偏移量而非行号
    • 文本处理注意UTF-8编码转换
  2. 线程安全注意事项

    cpp 复制代码
    // GUI操作必须在主线程执行
    ::PostMessage(nppData._nppHandle, NPPM_MSGTOPLUGIN, 
                 (WPARAM)_T("MyPlugin"), 
                 (LPARAM)&myNotification);
  3. 高效文本处理

    • 大文件处理使用分块读取
    • 避免频繁的整文档获取
    • 使用SCI_GETLINECHARACTERPTR直接访问行缓冲
  4. 跨版本兼容性

    cpp 复制代码
    // 通过NPPM_GETNPPVERSION获取版本
    int nppVersion = ::SendMessage(nppData._nppHandle, NPPM_GETNPPVERSION, 0, 0);
    int major = (nppVersion >> 16) & 0xFFFF;
    int minor = nppVersion & 0xFFFF;

调试技巧

cpp 复制代码
// 输出调试信息到控制台
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;
}

实战示例:全文批注插件

cpp 复制代码
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)"// ");
    }
}

开发注意事项:

  1. 使用SCI_BEGINUNDOACTION/SCI_ENDUNDOACTION包裹批量操作
  2. 跨平台兼容性避免Windows API硬编码
  3. 插件初始化时注册NPPN_READY通知
  4. 多视图场景区分主/副编辑窗口

通过以上核心功能实现,开发者可构建:

  • 代码格式化工具
  • 自定义语法检查器
  • 文档分析插件
  • 文本处理工作流自动化工具

提示:官方插件模板可从Notepad++仓库获取(Plugins->Plugin Template),建议基于模板开发确保结构规范

相关推荐
C雨后彩虹7 分钟前
任务总执行时长
java·数据结构·算法·华为·面试
weixin_462446238 分钟前
用 Go 快速搭建一个 Coze (扣子)API 流式回复模拟接口(Mock Server)
开发语言·golang·状态模式
小鸡吃米…12 分钟前
Python编程语言面试问题二
开发语言·python·面试
谁动了我的代码?24 分钟前
QT<34> 利用线程池处理耗时任务以及回调函数的使用
开发语言·qt
柒.梧.26 分钟前
数据结构:二叉排序树构建与遍历的解析与代码实现
java·开发语言·数据结构
李迟27 分钟前
Golang实践录:接口文档字段转结构体定义
开发语言·golang
徐同保1 小时前
js 点击按钮 把文本转成文件并下载下来
开发语言·javascript·ecmascript
zhuzewennamoamtf1 小时前
Linux内核platform抽象、数据结构、内核匹配机制
linux·运维·数据结构
2501_930707781 小时前
使用C#代码更改 PowerPoint 幻灯片大小
开发语言·c#·powerpoint
CoderCodingNo2 小时前
【GESP】C++三级真题 luogu-B4414 [GESP202509 三级] 日历制作
开发语言·c++·算法